Browse Source

优化查询速度

zk 1 year ago
parent
commit
476e6a5f63

+ 8 - 3
app/src/main/java/com/datarecovery/master/data/repositories/FileScanRepository.java

@@ -3,9 +3,11 @@ package com.datarecovery.master.data.repositories;
 
 import com.atmob.common.logging.AtmobLog;
 import com.atmob.common.runtime.ContextUtil;
+import com.datarecovery.master.utils.SystemUtil;
 import com.datarecovery.master.utils.filedetect.DetectFile;
 import com.datarecovery.master.utils.filedetect.FileScanHelper;
 import com.datarecovery.master.utils.xfile.XFile;
+import com.datarecovery.master.utils.xfile.XSAFFile;
 
 import org.reactivestreams.Subscription;
 
@@ -21,7 +23,8 @@ import atmob.reactivex.rxjava3.core.FlowableSubscriber;
 public class FileScanRepository {
 
     private static final String TAG = "FileScanRepository";
-
+    long l;
+    int size = 0;
     @Inject
     public FileScanRepository() {
 
@@ -32,11 +35,13 @@ public class FileScanRepository {
                 .subscribe(new FlowableSubscriber<List<DetectFile>>() {
                     @Override
                     public void onSubscribe(@NonNull Subscription s) {
-
+                        l = System.currentTimeMillis();
+                        size = 0;
                     }
 
                     @Override
                     public void onNext(List<DetectFile> fileList) {
+                        size += fileList.size();
                         for (DetectFile file : fileList) {
                             AtmobLog.d(TAG, file.getPath());
                         }
@@ -49,7 +54,7 @@ public class FileScanRepository {
 
                     @Override
                     public void onComplete() {
-
+                        AtmobLog.d(TAG, "refreshImageDetect time: " + (System.currentTimeMillis() - l) + "---数量:" + size);
                     }
                 });
     }

+ 4 - 0
app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverViewModel.java

@@ -16,6 +16,7 @@ import androidx.lifecycle.Transformations;
 
 import com.atmob.app.lib.base.BaseViewModel;
 import com.atmob.app.lib.livedata.SingleLiveEvent;
+import com.atmob.common.logging.AtmobLog;
 import com.atmob.common.runtime.ActivityUtil;
 import com.atmob.common.runtime.ContextUtil;
 import com.datarecovery.master.R;
@@ -99,6 +100,7 @@ public class ImageRecoverViewModel extends BaseViewModel {
     //是否会员试用
     private boolean isTrial;
 
+    private long detectTime;
 
     @Inject
     public ImageRecoverViewModel(DeviceFuncRepository deviceFuncRepository) {
@@ -281,6 +283,7 @@ public class ImageRecoverViewModel extends BaseViewModel {
                         checkAll.setValue(false);
                         totalCount = 0;
                         totalDetectedCount.setValue(0);
+                        detectTime = System.currentTimeMillis();
                     }
 
                     @Override
@@ -317,6 +320,7 @@ public class ImageRecoverViewModel extends BaseViewModel {
                     @Override
                     public void onComplete() {
                         setFreeExport();
+                        AtmobLog.d("ImageRecoverViewModel", System.currentTimeMillis() - detectTime + "ms - " + totalCount);
                         if (isTrial) {
                             showTrialFinishDialog.call();
                         }

+ 15 - 0
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.ImageType;
 import com.datarecovery.master.utils.xfile.XFile;
 import com.datarecovery.master.utils.xfile.XFileSearch;
 import com.datarecovery.master.utils.xfile.XPathFile;
@@ -313,6 +314,14 @@ public class ImageDeepDetector {
         } catch (Exception ignore) {
         }
         try {
+            if (file.getMineType() != null && file.getMineType().startsWith("image/")) {
+                file.setTag(IMAGE_SUFFIX);
+                return true;
+            }
+        } catch (Exception ignore) {
+
+        }
+        try {
             String name = file.getName();
             if (isImageSuffix(name)) {
                 file.setTag(IMAGE_SUFFIX);
@@ -356,6 +365,12 @@ public class ImageDeepDetector {
     }
 
     private static boolean hasImgMagic(XFile file) {
+        try {
+            if (file.getMineType() != null && !file.getMineType().equals("application/octet-stream")) {
+                return false;
+            }
+        } catch (Exception ignore) {
+        }
         try (InputStream inputStream = file.newInputStream()) {
             byte[] bytes = new byte[8];
             if (inputStream.read(bytes) != 8) {

+ 61 - 49
app/src/main/java/com/datarecovery/master/utils/filedetect/FileScanHelper.java

@@ -5,6 +5,7 @@ import static android.content.Context.POWER_SERVICE;
 import android.content.Context;
 import android.os.CancellationSignal;
 import android.os.PowerManager;
+import android.provider.DocumentsContract;
 import android.text.TextUtils;
 
 import androidx.annotation.IntDef;
@@ -76,12 +77,9 @@ public class FileScanHelper {
      * 需要能单扫某个文件夹(某个app)
      */
 
-    @IntDef({RefreshScanType.GALLERY, RefreshScanType.WEIXIN, RefreshScanType.QQ})
+    @IntDef({FileType.IMAGE_GALLERY, FileType.IMAGE_WEIXIN, FileType.IMAGE_QQ})
     @Retention(RetentionPolicy.SOURCE)
     public @interface RefreshScanType {
-        int GALLERY = 1;
-        int WEIXIN = 2;
-        int QQ = 3;
     }
 
 
@@ -96,12 +94,12 @@ public class FileScanHelper {
 
                             @Override
                             public boolean acceptFile(XFile file) {
-                                return isAcceptImageFile(file);
+                                return isAcceptImageFile(scanType, file);
                             }
 
                             @Override
                             public boolean acceptDirectory(XFile file) {
-                                return isAcceptImageDirectory(file);
+                                return isAcceptImageDirectory(scanType, file);
                             }
 
                             @Override
@@ -135,7 +133,8 @@ public class FileScanHelper {
                     switch (tag) {
                         case ImageType.IMG_MAGIC:
                         case ImageType.IMAGE_SUFFIX:
-                            return Flowable.just(new DetectFile(xFile, FileType.IMAGE_OTHER));
+                        case ImageType.IMG_DATA:
+                            return Flowable.just(new DetectFile(xFile, scanType));
                         case ImageType.XIAOMI_GALLERY_CACHE:
                             return Flowable.just(new DetectFile(xFile, FileType.IMAGE_GALLERY));
                         case ImageType.WECHAT_CACHE:
@@ -165,7 +164,7 @@ public class FileScanHelper {
                 .doOnTerminate(() -> releaseWakeLock(context));
     }
 
-    private static boolean isAcceptImageFile(XFile file) {
+    private static boolean isAcceptImageFile(int scanType, XFile file) {
         try {
             if (file.length() == 0) {
                 return false;
@@ -173,6 +172,14 @@ public class FileScanHelper {
         } catch (Exception ignore) {
         }
         try {
+            if (file.getMineType() != null && file.getMineType().startsWith("image/")) {
+                file.setTag(ImageType.IMG_DATA);
+                return true;
+            }
+        } catch (Exception ignore) {
+
+        }
+        try {
             String name = file.getName();
             if (ImageCacheUtil.isImageSuffix(name)) {
                 file.setTag(ImageType.IMAGE_SUFFIX);
@@ -180,37 +187,40 @@ public class FileScanHelper {
             }
         } catch (Exception ignore) {
         }
-        try {
-            String path = file.getPath();
-            int brand = BrandUtil.getBrand();
-            switch (brand) {
-                case BrandUtil.Oppo:
-                    if (ImageCacheUtil.isOppoGalleryCacheFile(path)) {
-                        file.setTag(ImageType.OPPO_GALLERY_CACHE);
-                    }
-                    return true;
-                case BrandUtil.Vivo:
-                    if (ImageCacheUtil.isVivoGalleryCacheFile(path)) {
-                        file.setTag(ImageType.VIVO_GALLERY_CACHE);
-                    }
-                    return true;
-                case BrandUtil.XiaoMi:
-                    if (ImageCacheUtil.isXiaomiGalleryCacheFile(path)) {
-                        file.setTag(ImageType.XIAOMI_GALLERY_CACHE);
-                    }
-                    return true;
-                case BrandUtil.Meizu:
-                    if (ImageCacheUtil.isMeizuGalleryCacheFile(path)) {
-                        file.setTag(ImageType.MEIZU_GALLERY_CACHE);
-                    }
-                    return true;
-                case BrandUtil.HuaWei:
-                    if (ImageCacheUtil.isHuaweiGalleryCacheFile(path)) {
-                        file.setTag(ImageType.HUAWEI_GALLERY_CACHE);
-                    }
-                    return true;
+
+        if (scanType == FileType.IMAGE_GALLERY) {
+            try {
+                String path = file.getPath();
+                int brand = BrandUtil.getBrand();
+                switch (brand) {
+                    case BrandUtil.Oppo:
+                        if (ImageCacheUtil.isOppoGalleryCacheFile(path)) {
+                            file.setTag(ImageType.OPPO_GALLERY_CACHE);
+                        }
+                        return true;
+                    case BrandUtil.Vivo:
+                        if (ImageCacheUtil.isVivoGalleryCacheFile(path)) {
+                            file.setTag(ImageType.VIVO_GALLERY_CACHE);
+                        }
+                        return true;
+                    case BrandUtil.XiaoMi:
+                        if (ImageCacheUtil.isXiaomiGalleryCacheFile(path)) {
+                            file.setTag(ImageType.XIAOMI_GALLERY_CACHE);
+                        }
+                        return true;
+                    case BrandUtil.Meizu:
+                        if (ImageCacheUtil.isMeizuGalleryCacheFile(path)) {
+                            file.setTag(ImageType.MEIZU_GALLERY_CACHE);
+                        }
+                        return true;
+                    case BrandUtil.HuaWei:
+                        if (ImageCacheUtil.isHuaweiGalleryCacheFile(path)) {
+                            file.setTag(ImageType.HUAWEI_GALLERY_CACHE);
+                        }
+                        return true;
+                }
+            } catch (Exception ignore) {
             }
-        } catch (Exception ignore) {
         }
         if (ImageCacheUtil.hasImgMagic(file)) {
             file.setTag(ImageType.IMG_MAGIC);
@@ -220,14 +230,16 @@ public class FileScanHelper {
     }
 
 
-    public static boolean isAcceptImageDirectory(XFile file) {
-        try {
-            String path = file.getPath();
-            if (isGalleryCacheDirectory(path)) {
-                file.setTag(ImageType.GALLERY_CACHE);
-                return true;
+    public static boolean isAcceptImageDirectory(int scanType, XFile file) {
+        if (scanType == FileType.IMAGE_GALLERY) {
+            try {
+                String path = file.getPath();
+                if (isGalleryCacheDirectory(path)) {
+                    file.setTag(ImageType.GALLERY_CACHE);
+                    return true;
+                }
+            } catch (Exception ignore) {
             }
-        } catch (Exception ignore) {
         }
         return false;
     }
@@ -247,7 +259,7 @@ public class FileScanHelper {
             if (TextUtils.isEmpty(path)) {
                 return true;
             }
-            if (RefreshScanType.GALLERY == scanType) {
+            if (FileType.IMAGE_GALLERY == scanType) {
                 if (path.endsWith("Pictures/QQ") || path.endsWith("Pictures%2FQQ") ||
                         path.endsWith("DCIM/WeixinWork") || path.endsWith("DCIM%2FWeixinWork") ||
                         path.endsWith("Pictures/WeiXin") || path.endsWith("Pictures%2FWeiXin")
@@ -362,11 +374,11 @@ public class FileScanHelper {
 
     private static List<String[]> getImageScanDirectory(@RefreshScanType int scanType) {
         switch (scanType) {
-            case RefreshScanType.GALLERY:
+            case FileType.IMAGE_GALLERY:
                 return getGallery();
-            case RefreshScanType.WEIXIN:
+            case FileType.IMAGE_WEIXIN:
                 return getWeiXin();
-            case RefreshScanType.QQ:
+            case FileType.IMAGE_QQ:
                 return getQQ();
         }
         return null;

+ 1 - 1
app/src/main/java/com/datarecovery/master/utils/filedetect/FileType.java

@@ -18,7 +18,7 @@ import java.lang.annotation.RetentionPolicy;
         FileType.AUDIO
 })
 @Retention(RetentionPolicy.SOURCE)
-@interface FileType {
+public @interface FileType {
     int IMAGE_GALLERY = 1;
     int IMAGE_WEIXIN = 2;
     int IMAGE_QQ = 3;

+ 6 - 0
app/src/main/java/com/datarecovery/master/utils/filedetect/ImageCacheUtil.java

@@ -108,6 +108,12 @@ public class ImageCacheUtil {
     }
 
     public static boolean hasImgMagic(XFile file) {
+        try {
+            if (file.getMineType() != null && !file.getMineType().equals("application/octet-stream")) {
+                return false;
+            }
+        } catch (Exception ignore) {
+        }
         try (InputStream inputStream = file.newInputStream()) {
             byte[] bytes = new byte[8];
             if (inputStream.read(bytes) != 8) {

+ 8 - 6
app/src/main/java/com/datarecovery/master/utils/filedetect/ImageType.java

@@ -11,6 +11,7 @@ import java.lang.annotation.RetentionPolicy;
         ImageType.WECHAT_CACHE,
         ImageType.GALLERY_CACHE,
         ImageType.IMG_MAGIC,
+        ImageType.IMG_DATA,
         ImageType.OPPO_GALLERY_CACHE,
         ImageType.VIVO_GALLERY_CACHE,
         ImageType.XIAOMI_GALLERY_CACHE,
@@ -22,10 +23,11 @@ public @interface ImageType {
     int IMAGE_SUFFIX = 1;
     int WECHAT_CACHE = 2;
     int GALLERY_CACHE = 3;
-    int IMG_MAGIC = 4;
-    int OPPO_GALLERY_CACHE = 5;
-    int VIVO_GALLERY_CACHE = 6;
-    int XIAOMI_GALLERY_CACHE = 7;
-    int MEIZU_GALLERY_CACHE = 8;
-    int HUAWEI_GALLERY_CACHE = 9;
+    int IMG_DATA = 4;
+    int IMG_MAGIC = 5;
+    int OPPO_GALLERY_CACHE = 6;
+    int VIVO_GALLERY_CACHE = 7;
+    int XIAOMI_GALLERY_CACHE = 8;
+    int MEIZU_GALLERY_CACHE = 9;
+    int HUAWEI_GALLERY_CACHE = 10;
 }

+ 2 - 0
app/src/main/java/com/datarecovery/master/utils/xfile/XFile.java

@@ -9,6 +9,8 @@ public interface XFile {
 
     String getPath() throws Exception;
 
+    String getMineType() throws Exception;
+
     Uri getUri() throws Exception;
 
     boolean isDirectory() throws Exception;

+ 7 - 0
app/src/main/java/com/datarecovery/master/utils/xfile/XPathFile.java

@@ -7,6 +7,7 @@ import android.os.Build;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
+import java.net.URLConnection;
 import java.nio.file.Files;
 
 public class XPathFile extends BaseXFile {
@@ -38,10 +39,16 @@ public class XPathFile extends BaseXFile {
     }
 
     @Override
+    public String getMineType() {
+        return URLConnection.guessContentTypeFromName(file.getName());
+    }
+
+    @Override
     public Uri getUri() throws Exception {
         return Uri.fromFile(file);
     }
 
+
     @Override
     public boolean isDirectory() {
         return file.isDirectory();

+ 71 - 12
app/src/main/java/com/datarecovery/master/utils/xfile/XSAFFile.java

@@ -5,8 +5,6 @@ import android.database.Cursor;
 import android.net.Uri;
 import android.provider.DocumentsContract;
 
-import com.datarecovery.master.utils.FileUtil;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
@@ -21,6 +19,20 @@ public class XSAFFile extends BaseXFile {
     private final Uri pathUri;
     private final String path;
 
+    private String mimeType;
+    private String name;
+    private boolean exist;
+    private long size;
+    private long lastModified;
+
+
+    static String[] queryIds = {
+            DocumentsContract.Document.COLUMN_MIME_TYPE,
+            DocumentsContract.Document.COLUMN_DISPLAY_NAME,
+            DocumentsContract.Document.COLUMN_DOCUMENT_ID,
+            DocumentsContract.Document.COLUMN_SIZE,
+            DocumentsContract.Document.COLUMN_LAST_MODIFIED
+    };
 
     public XSAFFile(Context context, Uri treeRoot, String[] segments) {
         this.context = context;
@@ -60,8 +72,10 @@ public class XSAFFile extends BaseXFile {
             documentId = DocumentsContract.getTreeDocumentId(pathUri);
         }
         this.documentUri = DocumentsContract.buildDocumentUriUsingTree(androidDataUri, documentId);
+        queryData();
     }
 
+
     public XSAFFile(Context context, Uri treeRoot, List<String> segments) {
         this.context = context;
 
@@ -99,6 +113,7 @@ public class XSAFFile extends BaseXFile {
             documentId = DocumentsContract.getTreeDocumentId(pathUri);
         }
         this.documentUri = DocumentsContract.buildDocumentUriUsingTree(pathUri, documentId);
+        queryData();
     }
 
     public XSAFFile(Context context, Uri documentUri) {
@@ -117,11 +132,51 @@ public class XSAFFile extends BaseXFile {
         }
         this.path = pathBuilder.toString();
         this.pathUri = treeRootUri;
+        queryData();
+    }
+
+
+    private void queryData() {
+        try (Cursor cursor = context.getContentResolver().query(documentUri, queryIds,
+                null, null, null)) {
+            if (cursor != null && cursor.moveToFirst()) {
+                for (int i = 0; i < queryIds.length; i++) {
+                    if (DocumentsContract.Document.COLUMN_MIME_TYPE.equals(queryIds[i])) {
+                        try {
+                            mimeType = cursor.getString(i);
+                        } catch (Exception ignore) {
+                        }
+                    } else if (DocumentsContract.Document.COLUMN_DISPLAY_NAME.equals(queryIds[i])) {
+                        try {
+                            name = cursor.getString(i);
+                        } catch (Exception ignore) {
+                        }
+                    } else if (DocumentsContract.Document.COLUMN_DOCUMENT_ID.equals(queryIds[i])) {
+                        try {
+                            exist = cursor.getString(i) != null;
+                        } catch (Exception ignore) {
+                        }
+                    } else if (DocumentsContract.Document.COLUMN_SIZE.equals(queryIds[i])) {
+                        try {
+                            size = cursor.getLong(i);
+                        } catch (Exception ignore) {
+                        }
+                    } else if (DocumentsContract.Document.COLUMN_LAST_MODIFIED.equals(queryIds[i])) {
+                        try {
+                            lastModified = cursor.getLong(i);
+                        } catch (Exception ignore) {
+                        }
+                    }
+                }
+            }
+        } catch (Exception ignore) {
+
+        }
     }
 
     @Override
-    public String getName() throws Exception {
-        return queryForString(DocumentsContract.Document.COLUMN_DISPLAY_NAME);
+    public String getName() {
+        return name;
     }
 
     @Override
@@ -130,13 +185,17 @@ public class XSAFFile extends BaseXFile {
     }
 
     @Override
+    public String getMineType() {
+        return mimeType;
+    }
+
+    @Override
     public Uri getUri() throws Exception {
         return documentUri;
     }
 
     @Override
-    public boolean isDirectory() throws Exception {
-        String mimeType = queryForString(DocumentsContract.Document.COLUMN_MIME_TYPE);
+    public boolean isDirectory() {
         return Objects.equals(mimeType, DocumentsContract.Document.MIME_TYPE_DIR);
     }
 
@@ -161,8 +220,8 @@ public class XSAFFile extends BaseXFile {
     }
 
     @Override
-    public boolean exists() throws Exception {
-        return queryForString(DocumentsContract.Document.COLUMN_DOCUMENT_ID) != null;
+    public boolean exists() {
+        return exist;
     }
 
     @Override
@@ -177,13 +236,13 @@ public class XSAFFile extends BaseXFile {
     }
 
     @Override
-    public long length() throws Exception {
-        return queryForLong(DocumentsContract.Document.COLUMN_SIZE);
+    public long length() {
+        return size;
     }
 
     @Override
-    public long lastModified() throws Exception {
-        return queryForLong(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
+    public long lastModified() {
+        return lastModified;
     }
 
     @Override