Browse Source

增加设置预先扫描文件夹

zk 1 year ago
parent
commit
a8d415884c

+ 0 - 4
app/src/main/java/com/datarecovery/master/utils/FilesSearch.java

@@ -38,10 +38,6 @@ public class FilesSearch {
         return Flowable.create((FlowableOnSubscribe<XFile>) emitter -> {
                     try {
                         CancellationSignal cancellationSignal = XFileSearch.searchExternalStorageAsync(context, new XFileSearch.FileFilter() {
-                            @Override
-                            public List<String[]> getScanPaths() {
-                                return null;
-                            }
 
                             @Override
                             public boolean acceptFile(XFile file) {

+ 2 - 11
app/src/main/java/com/datarecovery/master/utils/ImageDeepDetector.java

@@ -20,6 +20,7 @@ import com.atmob.common.crypto.CryptoUtils;
 import com.atmob.common.runtime.ActivityUtil;
 import com.atmob.common.runtime.ContextUtil;
 import com.datarecovery.master.BR;
+import com.datarecovery.master.utils.filedetect.FileScanHelper;
 import com.datarecovery.master.utils.filedetect.ImageType;
 import com.datarecovery.master.utils.xfile.XFile;
 import com.datarecovery.master.utils.xfile.XFileSearch;
@@ -69,19 +70,9 @@ public class ImageDeepDetector {
     public static Flowable<List<ImageFile>> detect(Context context) {
         return Flowable.create((FlowableOnSubscribe<XFile>) emitter -> {
                     try {
-                        CancellationSignal cancellationSignal = XFileSearch.searchExternalStorageAsync(context,
-                                new XFileSearch.FilePreScanDirectory() {
-                                    @Override
-                                    public List<String> preScanPaths() {
 
-                                        return null;
-                                    }
-                                },
+                        CancellationSignal cancellationSignal = XFileSearch.searchPreExternalStorageAsync(context, FileScanHelper.getPreScanDirectory(),
                                 new XFileSearch.FileFilter() {
-                                    @Override
-                                    public List<String[]> getScanPaths() {
-                                        return null;
-                                    }
 
                                     @Override
                                     public boolean acceptFile(XFile file) {

+ 18 - 10
app/src/main/java/com/datarecovery/master/utils/filedetect/FileScanHelper.java

@@ -86,12 +86,7 @@ public class FileScanHelper {
     public static Flowable<List<DetectFile>> refreshImageDetect(@NonNull Context context, @RefreshScanType int scanType) {
         return Flowable.create((FlowableOnSubscribe<XFile>) emitter -> {
                     try {
-                        CancellationSignal cancellationSignal = XFileSearch.searchExternalStorageAsync(context, new XFileSearch.FileFilter() {
-                            @Override
-                            public List<String[]> getScanPaths() {
-                                return getImageScanDirectory(scanType);
-                            }
-
+                        CancellationSignal cancellationSignal = XFileSearch.searchSpecifyExternalStorageAsync(context, getImageScanDirectory(scanType), new XFileSearch.FileFilter() {
                             @Override
                             public boolean acceptFile(XFile file) {
                                 return isAcceptImageFile(scanType, file);
@@ -289,11 +284,11 @@ public class FileScanHelper {
         wakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
     }
 
-    private static List<String[]> getGallery() {
+    public static List<String[]> getGallery() {
         return galleryList;
     }
 
-    private static @NonNull List<String[]> getFactoryGalleryDir() {
+    public static @NonNull List<String[]> getFactoryGalleryDir() {
         List<String[]> brandGallery = new ArrayList<>();
         int brand = BrandUtil.getBrand();
         switch (brand) {
@@ -364,11 +359,11 @@ public class FileScanHelper {
         return brandGallery;
     }
 
-    private static List<String[]> getWeiXin() {
+    public static List<String[]> getWeiXin() {
         return wxDirList;
     }
 
-    private static List<String[]> getQQ() {
+    public static List<String[]> getQQ() {
         return qqList;
     }
 
@@ -384,6 +379,19 @@ public class FileScanHelper {
         return null;
     }
 
+    public static List<String[]> getPreScanDirectory() {
+        List<String[]> preList = new ArrayList<>();
+        preList.add(new String[]{"DCIM"});
+        preList.add(new String[]{"Pictures"});
+        preList.add(new String[]{"Download"});
+        preList.add(new String[]{"Android", "data", "com.android.gallery3d"});
+        preList.add(new String[]{"Android", "data", "com.android.gallery"});
+        preList.addAll(FileScanHelper.getFactoryGalleryDir());
+        preList.add(new String[]{"Android", "data", "com.tencent.mm"});
+        preList.add(new String[]{"Android", "data", "com.tencent.mobileqq"});
+        return preList;
+    }
+
     public static void searchExternalDirectory(Context context) {
     }
 

+ 138 - 62
app/src/main/java/com/datarecovery/master/utils/xfile/XFileSearch.java

@@ -10,13 +10,16 @@ import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.WorkerThread;
 
+import com.atmob.common.logging.AtmobLog;
 import com.atmob.common.thread.ThreadPoolUtil;
 import com.datarecovery.master.utils.FileUtil;
 
 import java.io.File;
+import java.io.FileFilter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Queue;
@@ -40,11 +43,11 @@ public class XFileSearch {
      * Android Q及以上:除了应用私有目录,可以通过文件路径访问,需要权限{@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
      * 应用私有目录只能通过SAF访问,需要用户手动授权可以访问的目录
      */
-    public static List<XFile> searchExternalStorage(Context context, FileFilter fileFilter) {
+    public static List<XFile> searchExternalStorage(Context context, List<String[]> specifyScanPaths, FileFilter fileFilter) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
-            return searchExternalStorageOld(context, fileFilter);
+            return searchExternalStorageOld(context, specifyScanPaths, fileFilter);
         } else {
-            return searchExternalStorageNew(context, fileFilter);
+            return searchExternalStorageNew(context, specifyScanPaths, fileFilter);
         }
     }
 
@@ -59,31 +62,45 @@ public class XFileSearch {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 searchExternalStorageOldAsync(context, null, fileFilter, callback, cancellationSignal);
             } else {
-                searchExternalStorageNewAsync(context, fileFilter, callback, cancellationSignal);
+                searchExternalStorageNewAsync(context, null, null, fileFilter, callback, cancellationSignal);
             }
         });
         return cancellationSignal;
     }
 
-    public static CancellationSignal searchExternalStorageAsync(Context context, FilePreScanDirectory filePreScanDirectory, FileFilter fileFilter, FileSearchCallback callback) {
+
+    public static CancellationSignal searchPreExternalStorageAsync(Context context, List<String[]> filePreScanDirectory, FileFilter fileFilter, FileSearchCallback callback) {
         CancellationSignal cancellationSignal = new CancellationSignal();
         ThreadPoolUtil.getInstance().execute(() -> {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
-                searchExternalStorageOldAsync(context, filePreScanDirectory, fileFilter, callback, cancellationSignal);
+                searchExternalStorageOldAsync(context, null, fileFilter, callback, cancellationSignal);
             } else {
-                searchExternalStorageNewAsync(context, fileFilter, callback, cancellationSignal);
+                searchExternalStorageNewAsync(context, filePreScanDirectory, null, fileFilter, callback, cancellationSignal);
             }
         });
         return cancellationSignal;
     }
 
-    private static void searchExternalStorageNewAsync(Context context, FileFilter fileFilter,
+    public static CancellationSignal searchSpecifyExternalStorageAsync(Context context, List<String[]> specifyScanPaths, FileFilter fileFilter, FileSearchCallback callback) {
+        CancellationSignal cancellationSignal = new CancellationSignal();
+        ThreadPoolUtil.getInstance().execute(() -> {
+            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+                searchExternalStorageOldAsync(context, specifyScanPaths, fileFilter, callback, cancellationSignal);
+            } else {
+                searchExternalStorageNewAsync(context, null, specifyScanPaths, fileFilter, callback, cancellationSignal);
+            }
+        });
+        return cancellationSignal;
+    }
+
+
+    private static void searchExternalStorageNewAsync(Context context, List<String[]> filePreScanDirectory, List<String[]> specifyScanPaths, FileFilter fileFilter,
                                                       FileSearchCallback callback,
                                                       CancellationSignal cancellationSignal) {
         final int maxThreadCount = 5;
         Lock lock = new ReentrantLock();
         Condition condition = lock.newCondition();
-        List<XFile> startFiles = getExternalStorageFilesNew(context, fileFilter);
+        List<XFile> startFiles = getExternalStorageFilesNew(context, filePreScanDirectory, specifyScanPaths, fileFilter);
         ArrayList<XFile> tasks = new ArrayList<>();
         for (XFile startFile : startFiles) {
             try {
@@ -157,20 +174,20 @@ public class XFileSearch {
         }
     }
 
-    private static void searchExternalStorageOldAsync(Context context, FilePreScanDirectory filePreScanDirectory, FileFilter fileFilter,
+    private static void searchExternalStorageOldAsync(Context context, List<String[]> specifyScanPaths, FileFilter fileFilter,
                                                       FileSearchCallback callback,
                                                       CancellationSignal cancellationSignal) {
-        List<XFile> startFiles = getExternalStorageFilesOld(context, fileFilter, filePreScanDirectory);
+        List<XFile> startFiles = getExternalStorageFilesOld(context, specifyScanPaths);
         searchInternalAsync(startFiles, fileFilter, callback, cancellationSignal);
     }
 
-    private static List<XFile> searchExternalStorageNew(Context context, FileFilter fileFilter) {
-        List<XFile> startFiles = getExternalStorageFilesNew(context, fileFilter);
+    private static List<XFile> searchExternalStorageNew(Context context, List<String[]> specifyScanPaths, FileFilter fileFilter) {
+        List<XFile> startFiles = getExternalStorageFilesNew(context, null, specifyScanPaths, fileFilter);
         return searchInternal(startFiles, fileFilter);
     }
 
-    private static List<XFile> searchExternalStorageOld(Context context, FileFilter fileFilter) {
-        List<XFile> startFiles = getExternalStorageFilesOld(context, fileFilter, null);
+    private static List<XFile> searchExternalStorageOld(Context context, List<String[]> specifyScanPaths, FileFilter fileFilter) {
+        List<XFile> startFiles = getExternalStorageFilesOld(context, specifyScanPaths);
         return searchInternal(startFiles, fileFilter);
     }
 
@@ -221,14 +238,14 @@ public class XFileSearch {
     }
 
     @NonNull
-    private static List<XFile> getExternalStorageFilesNew(Context context, FileFilter fileFilter) {
+    private static List<XFile> getExternalStorageFilesNew(Context context, List<String[]> filePreScanDirectory, List<String[]> specifyScanPaths, FileFilter fileFilter) {
         List<StorageVolume> readableStorageVolumes = XStorageManager.getReadableStorageVolumes(context);
         List<XFile> startFiles = new ArrayList<>();
         for (StorageVolume storageVolume : readableStorageVolumes) {
             Uri treeUri = StorageVolumeUtil.getTreeUri(storageVolume);
-            if (fileFilter != null && fileFilter.getScanPaths() != null && !fileFilter.getScanPaths().isEmpty()) {
-                File directory = StorageVolumeUtil.getDirectory(storageVolume);
-                for (String[] scanPath : fileFilter.getScanPaths()) {
+            File directory = StorageVolumeUtil.getDirectory(storageVolume);
+            if (specifyScanPaths != null && !specifyScanPaths.isEmpty()) {
+                for (String[] scanPath : specifyScanPaths) {
                     String filePath = FileUtil.getFilePath(scanPath);
                     if (filePath.contains("Android%2Fdata")) {
                         XSAFFile xsafFile = new XSAFFile(context, treeUri, scanPath);
@@ -252,6 +269,105 @@ public class XFileSearch {
                         }
                     }
                 }
+            } else if (filePreScanDirectory != null && !filePreScanDirectory.isEmpty()) {
+                List<XFile> normalFiles = new ArrayList<>();
+                List<XFile> androidDataFiles = new ArrayList<>();
+                List<XFile> allFiles = new ArrayList<>();
+
+                for (String[] scanPath : filePreScanDirectory) {
+                    String filePath = FileUtil.getFilePath(scanPath);
+                    if (filePath.contains("Android%2Fdata")) {
+                        XSAFFile xsafFile = new XSAFFile(context, treeUri, scanPath);
+                        try {
+                            if (xsafFile.exists()) {
+                                allFiles.add(xsafFile);
+                                androidDataFiles.add(xsafFile);
+                            }
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    } else {
+                        if (directory != null) {
+                            XPathFile xPathFile = new XPathFile(context, directory, filePath);
+                            try {
+                                if (xPathFile.exists()) {
+                                    allFiles.add(xPathFile);
+                                    normalFiles.add(xPathFile);
+                                }
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    }
+                }
+                if (directory != null) {
+                    XPathFile androidEx = new XPathFile(context, directory);
+                    XFile androidXSA = null;
+                    XSAFFile androidDataXSA = new XSAFFile(context, treeUri, new String[]{"Android", "data"});
+                    if (androidDataXSA.exists()) {
+                        XFile[] xFiles = androidDataXSA.listFiles();
+                        for (XFile x : xFiles) {
+                            XFile tag = null;
+                            for (XFile next : androidDataFiles) {
+                                try {
+                                    if (x.getPath().equals(next.getPath())) {
+                                        tag = next;
+                                        break;
+                                    }
+                                } catch (Exception ignore) {
+                                }
+                            }
+                            if (tag == null) {
+                                allFiles.add(x);
+                            } else {
+                                androidDataFiles.remove(tag);
+                            }
+                        }
+                    }
+                    if (androidEx.exists()) {
+                        XFile[] xFiles = androidEx.listFiles();
+                        for (XFile x : xFiles) {
+                            try {
+                                if ("Android".equals(x.getName())) {
+                                    androidXSA = x;
+                                    continue;
+                                }
+                            } catch (Exception ignore) {
+                            }
+                            XFile tag = null;
+                            for (XFile next : normalFiles) {
+                                try {
+                                    if (x.getPath().equals(next.getPath())) {
+                                        tag = next;
+                                        break;
+                                    }
+                                } catch (Exception ignore) {
+                                }
+                            }
+                            if (tag == null) {
+                                allFiles.add(x);
+                            } else {
+                                normalFiles.remove(tag);
+                            }
+                        }
+                    }
+                    try {
+                        if (androidXSA != null && androidXSA.exists()) {
+                            XFile[] xFiles = androidXSA.listFiles();
+                            for (XFile xFile : xFiles) {
+                                try {
+                                    if (xFile.getPath().contains("Android%2Fdata") || xFile.getPath().contains("Android/data")) {
+                                        continue;
+                                    }
+                                    allFiles.add(xFile);
+                                } catch (Exception ignore) {
+                                }
+                            }
+                        }
+                    } catch (Exception ignore) {
+                    }
+                }
+                startFiles.addAll(allFiles);
             } else {
                 XSAFFile xsafFile = new XSAFFile(context, treeUri, Arrays.asList("Android", "data"));
                 try {
@@ -261,8 +377,6 @@ public class XFileSearch {
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
-
-                File directory = StorageVolumeUtil.getDirectory(storageVolume);
                 if (directory != null) {
                     XPathFile xPathFile = new XPathFile(context, directory);
                     try {
@@ -279,7 +393,7 @@ public class XFileSearch {
     }
 
     @NonNull
-    private static List<XFile> getExternalStorageFilesOld(Context context, FileFilter fileFilter, FilePreScanDirectory filePreScanDirectory) {
+    private static List<XFile> getExternalStorageFilesOld(Context context, List<String[]> specifyScanPaths) {
         List<StorageVolume> readableStorageVolumes = XStorageManager.getReadableStorageVolumes(context);
         List<XFile> startFiles = new ArrayList<>();
         for (StorageVolume storageVolume : readableStorageVolumes) {
@@ -287,8 +401,8 @@ public class XFileSearch {
             if (directory == null) {
                 continue;
             }
-            if (fileFilter != null && fileFilter.getScanPaths() != null && !fileFilter.getScanPaths().isEmpty()) {
-                for (String[] searchPath : fileFilter.getScanPaths()) {
+            if (specifyScanPaths != null && !specifyScanPaths.isEmpty()) {
+                for (String[] searchPath : specifyScanPaths) {
                     try {
                         File file = new File(directory, FileUtil.getFilePath(searchPath));
                         if (file.exists()) {
@@ -298,38 +412,6 @@ public class XFileSearch {
 
                     }
                 }
-            } else if (filePreScanDirectory != null && filePreScanDirectory.preScanPaths() != null && !filePreScanDirectory.preScanPaths().isEmpty()) {
-                // 预扫描目录
-                List<XFile> preFiles = new ArrayList<>();
-                for (String searchPath : filePreScanDirectory.preScanPaths()) {
-                    try {
-                        File file = new File(directory, searchPath);
-                        if (file.exists()) {
-                            preFiles.add(new XPathFile(context, file));
-                        }
-                    } catch (Exception ignore) {
-
-                    }
-                }
-                XFile androidData = new XPathFile(context, directory);
-                File androidDataFile = new File(directory, "Android%2Fdata");
-                String androidDataFilePath = androidDataFile.getPath();
-                List<XFile> rootFiles = new ArrayList<>();
-                File[] files = androidDataFile.listFiles();
-                if (files != null) {
-                    for (File file : files) {
-                        if (!androidDataFilePath.contains(file.getPath())) {
-                            rootFiles.add(new XPathFile(context, file));
-                        }
-                    }
-                }
-                try {
-                    if (androidDataFile.exists()) {
-
-                    }
-                } catch (Exception ignore) {
-
-                }
             } else {
                 XFile androidData = new XPathFile(context, directory);
                 try {
@@ -554,15 +636,9 @@ public class XFileSearch {
         }
     }
 
-    public interface FilePreScanDirectory {
-        //仅一级目录以及Android/data目录
-        List<String> preScanPaths();
-    }
 
     public interface FileFilter {
 
-        List<String[]> getScanPaths();
-
         boolean acceptFile(XFile file);
 
         boolean acceptDirectory(XFile file);