Browse Source

优化图片导出以及图片预览

zk 1 year ago
parent
commit
8e66ef9eb7

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/audiorecover/AudioRecoverViewModel.java

@@ -271,7 +271,7 @@ public class AudioRecoverViewModel extends BaseViewModel {
         showLoadingEvent.setValue(true);
         showLoadingEvent.setValue(true);
         RxJavaUtil.doInBackground(() -> {
         RxJavaUtil.doInBackground(() -> {
             for (FilesSearch.DocumentFile item : list) {
             for (FilesSearch.DocumentFile item : list) {
-                MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_AUDIO, item.newInputStream(), FileUtil.getCreateFileName(item.getName()));
+                MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_AUDIO, item.newInputStream(), FileUtil.getCreateFileName(MediaStoreHelper.TYPE_AUDIO, item.getName()));
                 item.setCheck(false);
                 item.setCheck(false);
             }
             }
             return true;
             return true;

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/filerecover/FileRecoverViewModel.java

@@ -307,7 +307,7 @@ public class FileRecoverViewModel extends BaseViewModel {
         showLoadingEvent.setValue(true);
         showLoadingEvent.setValue(true);
         RxJavaUtil.doInBackground(() -> {
         RxJavaUtil.doInBackground(() -> {
             for (FilesSearch.DocumentFile item : list) {
             for (FilesSearch.DocumentFile item : list) {
-                MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_FILES, item.newInputStream(), FileUtil.getCreateFileName(item.getName()));
+                MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_FILES, item.newInputStream(), FileUtil.getCreateFileName(MediaStoreHelper.TYPE_FILES, item.getName()));
                 item.setCheck(false);
                 item.setCheck(false);
             }
             }
             return true;
             return true;

+ 7 - 0
app/src/main/java/com/datarecovery/master/module/imgrecover/ImageItemAdapter.java

@@ -53,6 +53,13 @@ public class ImageItemAdapter extends RecyclerView.Adapter<ImageItemAdapter.View
         holder.bind(list.get(position));
         holder.bind(list.get(position));
     }
     }
 
 
+    public int getPosition(ImageDeepDetector.ImageFile imageFile) {
+        if (imageFile == null || list == null) {
+            return -1;
+        }
+        return list.indexOf(imageFile);
+    }
+
     public void submit(List<ImageDeepDetector.ImageFile> imageList) {
     public void submit(List<ImageDeepDetector.ImageFile> imageList) {
         if (imageList == null) {
         if (imageList == null) {
             return;
             return;

+ 26 - 0
app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverActivity.java

@@ -311,6 +311,32 @@ public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBindi
 
 
     @SuppressLint("NotifyDataSetChanged")
     @SuppressLint("NotifyDataSetChanged")
     private void initObserver() {
     private void initObserver() {
+        imageRecoverViewModel.getFailScrollPosition().observe(this, bean -> {
+            if (bean == null) {
+                return;
+            }
+            if (bean.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_GALLERY) {
+                int position = photoAdapter.getPosition(bean);
+                if (position != -1) {
+                    gridLayoutManager.scrollToPositionWithOffset(getPhotoPosition() + position, 0);
+                }
+            } else if (bean.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_WECHAT) {
+                int position = wxAdapter.getPosition(bean);
+                if (position != -1) {
+                    gridLayoutManager.scrollToPositionWithOffset(getWxPosition() + position, 0);
+                }
+            } else if (bean.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_QQ) {
+                int position = qqAdapter.getPosition(bean);
+                if (position != -1) {
+                    gridLayoutManager.scrollToPositionWithOffset(getQQPosition() + position, 0);
+                }
+            } else if (bean.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_OTHER) {
+                int position = otherAdapter.getPosition(bean);
+                if (position != -1) {
+                    gridLayoutManager.scrollToPositionWithOffset(getOtherPosition() + position, 0);
+                }
+            }
+        });
         imageRecoverViewModel.getScrollTop().observe(this, o -> binding.ryImageRecover.scrollToPosition(0));
         imageRecoverViewModel.getScrollTop().observe(this, o -> binding.ryImageRecover.scrollToPosition(0));
         imageRecoverViewModel.getShowTrialFinishDialog().observe(this, o -> showTrialFinishDialog());
         imageRecoverViewModel.getShowTrialFinishDialog().observe(this, o -> showTrialFinishDialog());
         imageRecoverViewModel.getShowTrialExportFailDialog().observe(this, o -> showTrialExportFailDialog());
         imageRecoverViewModel.getShowTrialExportFailDialog().observe(this, o -> showTrialExportFailDialog());

+ 63 - 23
app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverViewModel.java

@@ -39,6 +39,7 @@ import org.reactivestreams.Subscription;
 
 
 import java.io.File;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.List;
 import java.util.Objects;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
@@ -69,15 +70,16 @@ public class ImageRecoverViewModel extends BaseViewModel {
     private final List<ImageDeepDetector.ImageFile> detectedOtherList = new ReverseArrayList<>();
     private final List<ImageDeepDetector.ImageFile> detectedOtherList = new ReverseArrayList<>();
     private final List<ImageDeepDetector.ImageFile> selectList = new ReverseArrayList<>();
     private final List<ImageDeepDetector.ImageFile> selectList = new ReverseArrayList<>();
 
 
-    private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedPhotoImg = new MutableLiveData<>();
-    private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedWxImg = new MutableLiveData<>();
-    private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedQQImg = new MutableLiveData<>();
-    private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedOtherImg = new MutableLiveData<>();
+    private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedPhotoImg = new MutableLiveData<>(detectedPhotoList);
+    private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedWxImg = new MutableLiveData<>(detectedWxList);
+    private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedQQImg = new MutableLiveData<>(detectedQQList);
+    private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedOtherImg = new MutableLiveData<>(detectedOtherList);
     private final MutableLiveData<List<ImageDeepDetector.ImageFile>> selectedList = new MutableLiveData<>();
     private final MutableLiveData<List<ImageDeepDetector.ImageFile>> selectedList = new MutableLiveData<>();
 
 
     private final SingleLiveEvent<List<Uri>> deleteUriListSdk11 = new SingleLiveEvent<>();
     private final SingleLiveEvent<List<Uri>> deleteUriListSdk11 = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> showTrialFinishDialog = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> showTrialFinishDialog = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> showTrialExportFailDialog = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> showTrialExportFailDialog = new SingleLiveEvent<>();
+    private final SingleLiveEvent<ImageDeepDetector.ImageFile> failScrollPosition = new SingleLiveEvent<>();
     private final MutableLiveData<Boolean> showTrialView = new MutableLiveData<>();
     private final MutableLiveData<Boolean> showTrialView = new MutableLiveData<>();
     private final DeviceFuncRepository deviceFuncRepository;
     private final DeviceFuncRepository deviceFuncRepository;
     private LiveData<String> detectedPhotoTitle;
     private LiveData<String> detectedPhotoTitle;
@@ -113,6 +115,11 @@ public class ImageRecoverViewModel extends BaseViewModel {
         initLiveData();
         initLiveData();
     }
     }
 
 
+
+    public LiveData<ImageDeepDetector.ImageFile> getFailScrollPosition() {
+        return failScrollPosition;
+    }
+
     public LiveData<?> getScrollTop() {
     public LiveData<?> getScrollTop() {
         return scrollTop;
         return scrollTop;
     }
     }
@@ -557,29 +564,62 @@ public class ImageRecoverViewModel extends BaseViewModel {
                 return;
                 return;
             }
             }
         }
         }
-        showLoadingEvent.setValue(true);
-        RxJavaUtil.doInBackground(() -> {
-            for (ImageDeepDetector.ImageFile item : selectList) {
-                MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_IMAGE, item.newInputStream(), FileUtil.getExportImageFileName(item.getName()));
-                item.setCheck(false);
-            }
-            return true;
-        }, o -> {
-            checkAll.setValue(false);
-            showLoadingEvent.setValue(false);
-            ToastUtil.show(R.string.export_success, ToastUtil.LENGTH_SHORT);
-            selectList.clear();
-            selectedList.setValue(selectList);
-        }, throwable -> {
-            showLoadingEvent.setValue(false);
-            ToastUtil.show(throwable.getMessage(), ToastUtil.LENGTH_SHORT);
-            BuglyHelper.postCatchedException(new Exception("图片导出:", throwable));
-        });
+        Single.just(selectList.size())
+                .map(oldSize -> {
+                    Iterator<ImageDeepDetector.ImageFile> iterator = selectList.iterator();
+                    int errorCount = 0;
+                    int test = 0;
+                    Exception exception = null;
+                    while (iterator.hasNext()) {
+                        ImageDeepDetector.ImageFile item = iterator.next();
+                        try {
+                            MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_IMAGE, item.newInputStream(), FileUtil.getCreateFileName(MediaStoreHelper.TYPE_IMAGE, item.getName()));
+                            item.setCheck(false);
+                            iterator.remove();
+                        } catch (Exception throwable) {
+                            errorCount++;
+                            exception = throwable;
+                            BuglyHelper.postCatchedException(new Exception("图片导出:", throwable));
+                        }
+                    }
+                    if (errorCount == oldSize) {
+                        throw new Exception("导出失败" + (exception == null ? "" : ":" + exception.getMessage()));
+                    } else if (errorCount > 0) {
+                        throw new Exception("部分导出失败" + ":" + exception.getMessage());
+                    }
+                    return errorCount;
+                })
+                .compose(RxJavaUtil.SingleSchedule.io2Main())
+                .subscribe(new SingleObserver<Integer>() {
+                    @Override
+                    public void onSubscribe(@NonNull Disposable d) {
+                        addDisposable(d);
+                        showLoadingEvent.setValue(true);
+                    }
+
+                    @Override
+                    public void onSuccess(@NonNull Integer integer) {
+                        showLoadingEvent.setValue(false);
+                        selectedList.setValue(selectList);
+                        checkAll.setValue(false);
+                        ToastUtil.show(R.string.export_success, ToastUtil.LENGTH_SHORT);
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+                        showLoadingEvent.setValue(false);
+                        selectedList.setValue(selectList);
+                        ToastUtil.show(e.getMessage(), ToastUtil.LENGTH_SHORT);
+                        if (!selectList.isEmpty()) {
+                            failScrollPosition.setValue(selectList.get(0));
+                        }
+                    }
+                });
     }
     }
 
 
 
 
     public List<ImageDeepDetector.ImageFile> getAllDetectedList() {
     public List<ImageDeepDetector.ImageFile> getAllDetectedList() {
-        ArrayList<ImageDeepDetector.ImageFile> allList = new ArrayList<>();
+        List<ImageDeepDetector.ImageFile> allList = new ReverseArrayList<>();
         allList.addAll(detectedPhotoList);
         allList.addAll(detectedPhotoList);
         allList.addAll(detectedWxList);
         allList.addAll(detectedWxList);
         allList.addAll(detectedQQList);
         allList.addAll(detectedQQList);

+ 2 - 2
app/src/main/java/com/datarecovery/master/module/preview/PreviewViewModel.java

@@ -255,12 +255,12 @@ public class PreviewViewModel extends BaseViewModel {
                         if (value == null) {
                         if (value == null) {
                             return false;
                             return false;
                         }
                         }
-                        MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_IMAGE, value.newInputStream(), FileUtil.getExportImageFileName(value.getName()));
+                        MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_IMAGE, value.newInputStream(), FileUtil.getCreateFileName(MediaStoreHelper.TYPE_IMAGE, value.getName()));
                     } else if (type == PreviewActivity.TYPE_AUDIO) {
                     } else if (type == PreviewActivity.TYPE_AUDIO) {
                         if (currentFileFile == null) {
                         if (currentFileFile == null) {
                             return false;
                             return false;
                         }
                         }
-                        MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_AUDIO, currentFileFile.newInputStream(), FileUtil.getCreateFileName(currentFileFile.getName()));
+                        MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_AUDIO, currentFileFile.newInputStream(), FileUtil.getCreateFileName(MediaStoreHelper.TYPE_AUDIO, currentFileFile.getName()));
                     }
                     }
                     return true;
                     return true;
                 }
                 }

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/videorecover/VideoRecoverViewModel.java

@@ -241,7 +241,7 @@ public class VideoRecoverViewModel extends BaseViewModel {
         showLoadingEvent.setValue(true);
         showLoadingEvent.setValue(true);
         RxJavaUtil.doInBackground(() -> {
         RxJavaUtil.doInBackground(() -> {
             for (FilesSearch.DocumentFile item : list) {
             for (FilesSearch.DocumentFile item : list) {
-                MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_VIDEO, item.newInputStream(), FileUtil.getCreateFileName(item.getName()));
+                MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_VIDEO, item.newInputStream(), FileUtil.getCreateFileName(MediaStoreHelper.TYPE_VIDEO, item.getName()));
                 item.setCheck(false);
                 item.setCheck(false);
             }
             }
             return true;
             return true;

+ 29 - 45
app/src/main/java/com/datarecovery/master/utils/FileUtil.java

@@ -3,16 +3,15 @@ package com.datarecovery.master.utils;
 import android.annotation.SuppressLint;
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Drawable;
-import android.net.Uri;
 import android.text.TextUtils;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.text.format.Formatter;
 
 
 
 
+import androidx.annotation.NonNull;
+
 import com.atmob.common.runtime.ContextUtil;
 import com.atmob.common.runtime.ContextUtil;
 import com.datarecovery.master.R;
 import com.datarecovery.master.R;
 
 
-import java.util.Arrays;
-import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.UUID;
 import java.util.UUID;
 
 
@@ -22,6 +21,11 @@ public class FileUtil {
 
 
     }
     }
 
 
+    private static final String IMAGE_PREFIX = "recover_img_";
+    private static final String FILE_PREFIX = "recover_file_";
+    private static final String AUDIO_PREFIX = "recover_audio_";
+    private static final String VIDEO_PREFIX = "recover_video_";
+
     public static String getFilePath(String[] pathSegments) {
     public static String getFilePath(String[] pathSegments) {
         if (pathSegments == null) {
         if (pathSegments == null) {
             return null;
             return null;
@@ -45,48 +49,40 @@ public class FileUtil {
         return split[split.length - 1].toUpperCase(Locale.getDefault());
         return split[split.length - 1].toUpperCase(Locale.getDefault());
     }
     }
 
 
-    public static String isImageFile(String fileName) {
-        if (fileName == null || fileName.isEmpty()) {
-            return null;
-        }
-        String[] imageExtensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".tiff", ".tif", ".ico", ".svg"};
-        for (String extension : imageExtensions) {
-            if (fileName.toLowerCase().endsWith(extension)) {
-                return extension;
-            }
-        }
-        return null;
-    }
 
 
-    public static String getExportImageFileName(String fileName) {
-        String uuid = UUID.randomUUID().toString();
-        String fileType = isImageFile(fileName);
-        if (!TextUtils.isEmpty(fileType)) {
-            return uuid + fileType;
+    public static String getCreateFileName(@MediaStoreHelper.MediaType int mediaType, String fileName) {
+        if (mediaType == MediaStoreHelper.TYPE_IMAGE) {
+            return getExportFileName(IMAGE_PREFIX, ".png", fileName);
+        } else if (mediaType == MediaStoreHelper.TYPE_VIDEO) {
+            return getExportFileName(VIDEO_PREFIX, ".mp4", fileName);
+        } else if (mediaType == MediaStoreHelper.TYPE_AUDIO) {
+            return getExportFileName(AUDIO_PREFIX, ".mp3", fileName);
         } else {
         } else {
-            return uuid + ".png";
+            return getExportFileName(FILE_PREFIX, "", fileName);
         }
         }
     }
     }
 
 
-    public static String getExportAudioFileName(String fileName) {
-        return fileName + "_" + System.currentTimeMillis() + ".mp3";
-    }
-
-
-    public static String getCreateFileName(String fileName) {
-        String uuid = UUID.randomUUID().toString();
-        String time = DateUtil.formatNormalDate("yyyyMMddHHmmssSSS", System.currentTimeMillis());
-        if (fileName == null || fileName.isEmpty()) {
-            return uuid + "_" + time;
+    public static String getExportFileName(@NonNull String prefix, String defaultSuffix, String fileName) {
+        if (TextUtils.isEmpty(fileName)) {
+            return prefix + getNowTime() + defaultSuffix;
         }
         }
+        StringBuilder sb = new StringBuilder();
+        sb.append(prefix);
+        sb.append(getNowTime());
         int lastDot = fileName.lastIndexOf(".");
         int lastDot = fileName.lastIndexOf(".");
         if (lastDot == -1) {
         if (lastDot == -1) {
-            return uuid + "_" + time;
+            sb.append(defaultSuffix);
         } else {
         } else {
-            return fileName.substring(0, lastDot) + "_" + time + fileName.substring(lastDot);
+            sb.append(fileName.substring(lastDot));
         }
         }
+        return sb.toString();
     }
     }
 
 
+    private static String getNowTime() {
+        return DateUtil.formatNormalDate("yyyyMMddHHmmssSSS", System.currentTimeMillis());
+    }
+
+
     @SuppressLint("UseCompatLoadingForDrawables")
     @SuppressLint("UseCompatLoadingForDrawables")
     public static Drawable getFileRecoverIcon(int fileTypeId) {
     public static Drawable getFileRecoverIcon(int fileTypeId) {
         Context context = ContextUtil.getContext();
         Context context = ContextUtil.getContext();
@@ -102,17 +98,5 @@ public class FileUtil {
         return null;
         return null;
     }
     }
 
 
-    public static Exception getFileListFailException(List<?> list, String messageHeadTxt) {
-        if (list == null) {
-            return null;
-        }
-        StringBuilder sb = new StringBuilder();
-        sb.append("错误类型:");
-        sb.append(messageHeadTxt);
-        sb.append("==");
-        sb.append(Arrays.toString(list.toArray()));
-        sb.append("==");
-        return new Exception(sb.toString());
-    }
 
 
 }
 }

+ 10 - 0
app/src/main/java/com/datarecovery/master/utils/ReverseArrayList.java

@@ -1,6 +1,7 @@
 package com.datarecovery.master.utils;
 package com.datarecovery.master.utils;
 
 
 import androidx.annotation.NonNull;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collection;
@@ -24,4 +25,13 @@ public class ReverseArrayList<T> extends ArrayList<T> {
         index = size() - index - 1;
         index = size() - index - 1;
         return super.get(index);
         return super.get(index);
     }
     }
+
+    @Override
+    public int indexOf(@Nullable Object o) {
+        int index = super.indexOf(o);
+        if (index == -1) {
+            return index;
+        }
+        return size() - index - 1;
+    }
 }
 }