+++ /dev/null
-package org.openintents.filemanager;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import org.openintents.filemanager.util.FileUtils;
-import org.openintents.filemanager.util.ImageUtils;
-import org.openintents.filemanager.util.MimeTypes;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.support.v2.os.Build;
-import android.util.Log;
-
-public class DirectoryScanner extends Thread {
-
- private static final String TAG = "OIFM_DirScanner";
-
- private File currentDirectory;
- boolean cancel;
-
- private String mSdCardPath;
- private Context context;
- private MimeTypes mMimeTypes;
- private Handler handler;
- private long operationStartTime;
- private String mFilterFiletype;
- private String mFilterMimetype;
-
- private boolean mWriteableOnly;
-
- private boolean mDirectoriesOnly;
-
- // Update progress bar every n files
- static final private int PROGRESS_STEPS = 50;
-
- // APK MIME type
- private static final String MIME_APK = "application/vnd.android.package-archive";
-
- // Cupcake-specific methods
- static Method formatter_formatFileSize;
-
- static {
- initializeCupcakeInterface();
- }
-
-
-
- DirectoryScanner(File directory, Context context, Handler handler, MimeTypes mimeTypes, String filterFiletype, String filterMimetype, String sdCardPath, boolean writeableOnly, boolean directoriesOnly) {
- super("Directory Scanner");
- currentDirectory = directory;
- this.context = context;
- this.handler = handler;
- this.mMimeTypes = mimeTypes;
- this.mFilterFiletype = filterFiletype;
- this.mFilterMimetype = filterMimetype;
- this.mSdCardPath = sdCardPath;
- this.mWriteableOnly = writeableOnly;
- this.mDirectoriesOnly = directoriesOnly;
- }
-
- private void clearData() {
- // Remove all references so we don't delay the garbage collection.
- context = null;
- mMimeTypes = null;
- handler = null;
- }
-
- public void run() {
- Log.v(TAG, "Scanning directory " + currentDirectory);
-
- File[] files = currentDirectory.listFiles();
-
- int fileCount = 0;
- int dirCount = 0;
- int sdCount = 0;
- int totalCount = 0;
-
- if (cancel) {
- Log.v(TAG, "Scan aborted");
- clearData();
- return;
- }
-
- if (files == null) {
- Log.v(TAG, "Returned null - inaccessible directory?");
- totalCount = 0;
- } else {
- totalCount = files.length;
- }
-
- operationStartTime = SystemClock.uptimeMillis();
-
- Log.v(TAG, "Counting files... (total count=" + totalCount + ")");
-
- int progress = 0;
-
- /** Dir separate for return after sorting*/
- List<IconifiedText> listDir = new ArrayList<IconifiedText>(totalCount);
- /** Dir separate for sorting */
- List<File> listDirFile = new ArrayList<File>(totalCount);
-
- /** Files separate for return after sorting*/
- List<IconifiedText> listFile = new ArrayList<IconifiedText>(totalCount);
- /** Files separate for sorting */
- List<File> listFileFile = new ArrayList<File>(totalCount);
-
- /** SD card separate for sorting - actually not sorted, so we don't need an ArrayList<File>*/
- List<IconifiedText> listSdCard = new ArrayList<IconifiedText>(3);
-
- boolean noMedia = false;
-
- // Cache some commonly used icons.
- Drawable sdIcon = context.getResources().getDrawable(R.drawable.ic_launcher_sdcard);
- Drawable folderIcon = context.getResources().getDrawable(R.drawable.ic_launcher_folder);
- Drawable genericFileIcon = context.getResources().getDrawable(R.drawable.icon_file);
-
- Drawable currentIcon = null;
-
- boolean displayHiddenFiles = PreferenceActivity.getDisplayHiddenFiles(context);
-
- if (files != null) {
- for (File currentFile : files){
- if (cancel) {
- // Abort!
- Log.v(TAG, "Scan aborted while checking files");
- clearData();
- return;
- }
-
- progress++;
- updateProgress(progress, totalCount);
-
- //If the user doesn't want to display hidden files and the file is hidden,
- //skip displaying the file
- if (!displayHiddenFiles && currentFile.isHidden()){
- continue;
- }
-
-
- if (currentFile.isDirectory()) {
- if (currentFile.getAbsolutePath().equals(mSdCardPath)) {
- currentIcon = sdIcon;
-
- listSdCard.add(new IconifiedText(
- currentFile.getName(), "", currentIcon));
- } else {
- if (!mWriteableOnly || currentFile.canWrite()){
- listDirFile.add(currentFile);
- }
- }
- }else{
- String fileName = currentFile.getName();
-
- // Is this the ".nomedia" file?
- if (!noMedia) {
- if (fileName.equalsIgnoreCase(".nomedia")) {
- // It is!
- noMedia = true;
- }
- }
-
- String mimetype = mMimeTypes.getMimeType(fileName);
-
- String filetype = FileUtils.getExtension(fileName);
- boolean ext_allow = filetype.equalsIgnoreCase(mFilterFiletype) || mFilterFiletype == "";
- boolean mime_allow = mFilterMimetype != null &&
- (mimetype.contentEquals(mFilterMimetype) || mFilterMimetype.contentEquals("*/*") ||
- mFilterFiletype == null);
- if (!mDirectoriesOnly && (ext_allow || mime_allow)) {
- listFileFile.add(currentFile);
- }
- }
- }
- }
-
- Log.v(TAG, "Sorting results...");
-
- //Collections.sort(mListSdCard);
- int sortBy = PreferenceActivity.getSortBy(context);
- boolean ascending = PreferenceActivity.getAscending(context);
-
-
- Collections.sort(listDirFile, Comparators.getForDirectory(sortBy, ascending));
- Collections.sort(listFileFile, Comparators.getForFile(sortBy, ascending));
-
- for(File f : listDirFile){
- listDir.add(new IconifiedText(
- f.getName(), FileUtils.formatDate(context, f.lastModified()), folderIcon));
- }
-
- for(File currentFile : listFileFile){
- String mimetype = mMimeTypes.getMimeType(currentFile.getName());
- currentIcon = getDrawableForMimetype(currentFile, mimetype);
- if (currentIcon == null) {
- currentIcon = genericFileIcon;
- } else {
- int width = genericFileIcon.getIntrinsicWidth();
- int height = genericFileIcon.getIntrinsicHeight();
- // Resizing image.
- currentIcon = ImageUtils.resizeDrawable(currentIcon, width, height);
-
- }
-
- String size = "";
-
- try {
- size = (String) formatter_formatFileSize.invoke(null, context, currentFile.length());
- } catch (Exception e) {
- // The file size method is probably null (this is most
- // likely not a Cupcake phone), or something else went wrong.
- // Let's fall back to something primitive, like just the number
- // of KB.
- size = Long.toString(currentFile.length() / 1024);
- size +=" KB";
-
- // Technically "KB" should come from a string resource,
- // but this is just a Cupcake 1.1 callback, and KB is universal
- // enough.
- }
-
- listFile.add(new IconifiedText(
- currentFile.getName(), size + " , " + FileUtils.formatDate(
- context, currentFile.lastModified()), currentIcon));
- }
-
- if (!cancel) {
- Log.v(TAG, "Sending data back to main thread");
-
- DirectoryContents contents = new DirectoryContents();
-
- contents.listDir = listDir;
- contents.listFile = listFile;
- contents.listSdCard = listSdCard;
- contents.noMedia = noMedia;
-
- Message msg = handler.obtainMessage(FileManagerActivity.MESSAGE_SHOW_DIRECTORY_CONTENTS);
- msg.obj = contents;
- msg.sendToTarget();
- }
-
- clearData();
- }
-
- private void updateProgress(int progress, int maxProgress) {
- // Only update the progress bar every n steps...
- if ((progress % PROGRESS_STEPS) == 0) {
- // Also don't update for the first second.
- long curTime = SystemClock.uptimeMillis();
-
- if (curTime - operationStartTime < 1000L) {
- return;
- }
-
- // Okay, send an update.
- Message msg = handler.obtainMessage(FileManagerActivity.MESSAGE_SET_PROGRESS);
- msg.arg1 = progress;
- msg.arg2 = maxProgress;
- msg.sendToTarget();
- }
- }
-
- /**
- * Return the Drawable that is associated with a specific mime type
- * for the VIEW action.
- *
- * @param mimetype
- * @return
- */
- Drawable getDrawableForMimetype(File file, String mimetype) {
- if (mimetype == null) {
- return null;
- }
-
- PackageManager pm = context.getPackageManager();
-
- // Returns the icon packaged in files with the .apk MIME type.
- if(mimetype.equals(MIME_APK)){
- String path = file.getPath();
- PackageInfo pInfo = pm.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
- if (pInfo!=null) {
- ApplicationInfo aInfo = pInfo.applicationInfo;
-
- // Bug in SDK versions >= 8. See here: http://code.google.com/p/android/issues/detail?id=9151
- if(Build.VERSION.SDK_INT >= 8){
- aInfo.sourceDir = path;
- aInfo.publicSourceDir = path;
- }
-
- return aInfo.loadIcon(pm);
- }
- }
-
- int iconResource = mMimeTypes.getIcon(mimetype);
- Drawable ret = null;
- if(iconResource > 0){
- try {
- ret = pm.getResourcesForApplication(context.getPackageName()).getDrawable(iconResource);
- }catch(NotFoundException e){}
- catch(NameNotFoundException e){}
- }
-
- if(ret != null){
- return ret;
- }
-
- Uri data = FileUtils.getUri(file);
-
- Intent intent = new Intent(Intent.ACTION_VIEW);
- //intent.setType(mimetype);
-
- // Let's probe the intent exactly in the same way as the VIEW action
- // is performed in FileManagerActivity.openFile(..)
- intent.setDataAndType(data, mimetype);
-
- final List<ResolveInfo> lri = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-
- if (lri != null && lri.size() > 0) {
- //Log.i(TAG, "lri.size()" + lri.size());
-
- // return first element
- int index = 0;
-
- // Actually first element should be "best match",
- // but it seems that more recently installed applications
- // could be even better match.
- index = lri.size()-1;
-
- final ResolveInfo ri = lri.get(index);
- return ri.loadIcon(pm);
- }
-
- return null;
- }
-
- private static void initializeCupcakeInterface() {
- try {
- formatter_formatFileSize = Class.forName("android.text.format.Formatter").getMethod("formatFileSize", Context.class, long.class);
- } catch (Exception ex) {
- // This is not cupcake.
- return;
- }
- }
-}
-
-/**
- * The container class for all comparators.
- */
-class Comparators{
- public static final int NAME = 1;
- public static final int SIZE = 2;
- public static final int LAST_MODIFIED = 3;
-
-
- public static Comparator<File> getForFile(int comparator, boolean ascending){
- switch(comparator){
- case NAME: return new NameComparator(ascending);
- case SIZE: return new SizeComparator(ascending);
- case LAST_MODIFIED: return new LastModifiedComparator(ascending);
- default: return null;
- }
- }
- public static Comparator<File> getForDirectory(int comparator, boolean ascending){
- switch(comparator){
- case NAME: return new NameComparator(ascending);
- case SIZE: return new NameComparator(ascending); //Not a bug! Getting directory's size is verry slow
- case LAST_MODIFIED: return new LastModifiedComparator(ascending);
- default: return null;
- }
- }
-}
-
-
-abstract class FileComparator implements Comparator<File>{
- protected boolean ascending = true;
-
- public FileComparator(boolean asc){
- ascending = asc;
- }
-
- public FileComparator(){
- this(true);
- }
-
- public int compare(File f1, File f2){
- return comp((ascending ? f1 : f2), (ascending ? f2 : f1));
- }
-
- protected abstract int comp(File f1, File f2);
-}
-
-class NameComparator extends FileComparator{
- public NameComparator(boolean asc){
- super(asc);
- }
-
- protected int comp(File f1, File f2) {
- return f1.getName().toLowerCase().compareTo(f2.getName().toLowerCase());
- }
-}
-
-class SizeComparator extends FileComparator{
- public SizeComparator(boolean asc){
- super(asc);
- }
-
- protected int comp(File f1, File f2) {
- return ((Long)f1.length()).compareTo(f2.length());
- }
-
- /*//Very inefficient
- private long getFileSize(File f){
- if(f.isFile())
- return f.length();
- int ret = 0;
- for(File file : f.listFiles())
- ret += getFileSize(file);
-
- return ret;
- }
- */
-}
-
-class LastModifiedComparator extends FileComparator{
- public LastModifiedComparator(boolean asc){
- super(asc);
- }
-
- protected int comp(File f1, File f2) {
- return ((Long)f1.lastModified()).compareTo(f2.lastModified());
- }
-}
\ No newline at end of file