Browse Source

优化图片清除流程

zk 1 year ago
parent
commit
ef925828ea

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

@@ -2,11 +2,18 @@ package com.datarecovery.master.module.imgrecover;
 
 import android.annotation.SuppressLint;
 import android.app.Activity;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentSender;
+import android.net.Uri;
 import android.os.Bundle;
+import android.provider.MediaStore;
 import android.view.KeyEvent;
 
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.IntentSenderRequest;
+import androidx.activity.result.contract.ActivityResultContracts;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.ConcatAdapter;
@@ -14,6 +21,8 @@ import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.atmob.app.lib.base.BaseActivity;
+import com.atmob.common.runtime.ActivityUtil;
+import com.atmob.common.runtime.ContextUtil;
 import com.datarecovery.master.R;
 import com.datarecovery.master.databinding.ActivityImageRecoverBinding;
 import com.datarecovery.master.databinding.ItemTabImageRecoverBinding;
@@ -22,6 +31,7 @@ import com.datarecovery.master.dialog.CommonSureDialog;
 import com.datarecovery.master.dialog.ScanProgressDialog;
 import com.datarecovery.master.module.member.MemberType;
 import com.datarecovery.master.module.preview.PreviewActivity;
+import com.datarecovery.master.utils.ActivityForResultUtil;
 import com.datarecovery.master.utils.BoxingUtil;
 import com.datarecovery.master.utils.FilePermissionHelper;
 import com.datarecovery.master.utils.GridRecoverItemDecoration;
@@ -264,6 +274,15 @@ public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBindi
 
     @SuppressLint("NotifyDataSetChanged")
     private void initObserver() {
+        imageRecoverViewModel.getDeleteUriListSdk11().observe(this, list -> {
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
+                PendingIntent pi = MediaStore.createDeleteRequest(getBaseContext().getContentResolver(), list);
+                IntentSenderRequest request = new IntentSenderRequest.Builder(pi.getIntentSender()).build();
+                new ActivityForResultUtil<IntentSenderRequest, ActivityResult>().startActivityForResult(this, new ActivityResultContracts.StartIntentSenderForResult(), request, result -> {
+                    imageRecoverViewModel.callDealComplete(result.getResultCode() == Activity.RESULT_OK);
+                });
+            }
+        });
         imageRecoverViewModel.getNotifyList().observe(this, o -> {
             photoAdapter.notifyDataSetChanged();
             wxAdapter.notifyDataSetChanged();

+ 152 - 32
app/src/main/java/com/datarecovery/master/module/imgrecover/ImageRecoverViewModel.java

@@ -1,26 +1,45 @@
 package com.datarecovery.master.module.imgrecover;
 
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.IntentSender;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.MediaStore;
 import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
 
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.Observer;
 import androidx.lifecycle.Transformations;
 
 import com.atmob.app.lib.base.BaseViewModel;
 import com.atmob.app.lib.livedata.SingleLiveEvent;
+import com.atmob.common.runtime.ActivityUtil;
 import com.atmob.common.runtime.ContextUtil;
 import com.datarecovery.master.R;
 import com.datarecovery.master.data.consts.EventId;
 import com.datarecovery.master.data.repositories.DeviceFuncRepository;
 import com.datarecovery.master.handler.EventHelper;
 import com.datarecovery.master.module.member.MemberType;
+import com.datarecovery.master.utils.BoxingUtil;
 import com.datarecovery.master.utils.FileUtil;
 import com.datarecovery.master.utils.ImageDeepDetector;
 import com.datarecovery.master.utils.MediaStoreHelper;
 import com.datarecovery.master.utils.ToastUtil;
+import com.datarecovery.master.utils.xfile.XSAFFile;
 
 import org.reactivestreams.Subscription;
 
+import java.io.File;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -31,7 +50,11 @@ import javax.inject.Inject;
 import atmob.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
 import atmob.reactivex.rxjava3.annotations.NonNull;
 import atmob.reactivex.rxjava3.core.FlowableSubscriber;
+import atmob.reactivex.rxjava3.core.Single;
+import atmob.reactivex.rxjava3.core.SingleObserver;
+import atmob.reactivex.rxjava3.core.SingleSource;
 import atmob.reactivex.rxjava3.disposables.Disposable;
+import atmob.reactivex.rxjava3.functions.Function;
 import atmob.rxjava.utils.RxJavaUtil;
 import dagger.hilt.android.lifecycle.HiltViewModel;
 
@@ -46,6 +69,8 @@ public class ImageRecoverViewModel extends BaseViewModel {
     private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedWxImg = new MutableLiveData<>(new ArrayList<>());
     private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedQQImg = new MutableLiveData<>(new ArrayList<>());
     private final MutableLiveData<List<ImageDeepDetector.ImageFile>> detectedOtherImg = new MutableLiveData<>(new ArrayList<>());
+
+    private final SingleLiveEvent<List<Uri>> deleteUriListSdk11 = new SingleLiveEvent<>();
     private final DeviceFuncRepository deviceFuncRepository;
     private LiveData<String> detectedPhotoTitle;
     private LiveData<String> detectedWxTitle;
@@ -70,6 +95,8 @@ public class ImageRecoverViewModel extends BaseViewModel {
     @MemberType
     private String type;
 
+    private SingleObserver<? super Boolean> dealMediaObserver;
+
 
     @Inject
     public ImageRecoverViewModel(DeviceFuncRepository deviceFuncRepository) {
@@ -78,6 +105,10 @@ public class ImageRecoverViewModel extends BaseViewModel {
         initLiveData();
     }
 
+    public LiveData<List<Uri>> getDeleteUriListSdk11() {
+        return deleteUriListSdk11;
+    }
+
     public LiveData<?> getShowClearDialog() {
         return showClearDialog;
     }
@@ -302,39 +333,122 @@ public class ImageRecoverViewModel extends BaseViewModel {
         if (list.size() == 0) {
             return;
         }
-        showLoadingEvent.setValue(true);
-        RxJavaUtil.doInBackground(() -> {
-            for (ImageDeepDetector.ImageFile item : list) {
-                item.delete();
-                MutableLiveData<List<ImageDeepDetector.ImageFile>> liveData;
-                if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_GALLERY) {
-                    liveData = detectedPhotoImg;
-                } else if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_WECHAT) {
-                    liveData = detectedWxImg;
-                } else if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_QQ) {
-                    liveData = detectedQQImg;
-                } else {
-                    liveData = detectedOtherImg;
-                }
-                List<ImageDeepDetector.ImageFile> itemList = getList(liveData);
-                itemList.remove(item);
+        Single.just(Build.VERSION.SDK_INT)
+                .map(sdkInt -> sdkInt >= Build.VERSION_CODES.R)
+                .map(isSdk11 -> {
+                    List<ImageDeepDetector.ImageFile> safList = new ArrayList<>();
+                    List<Uri> uriList = new ArrayList<>();
+                    if (isSdk11) {
+                        for (ImageDeepDetector.ImageFile item : list) {
+                            File tempFile = new File(item.getPath());
+                            long mediaID = getFilePathToMediaID(tempFile.getAbsolutePath(), ContextUtil.getContext());
+                            if (mediaID > 0) {
+                                Uri Uri_one = ContentUris.withAppendedId(MediaStore.Images.Media.getContentUri("external"), mediaID);
+                                uriList.add(Uri_one);
+                            } else {
+                                safList.add(item);
+                            }
+                        }
+                    } else {
+                        safList.addAll(list);
+                    }
+                    return new Pair<>(safList, uriList);
+                })
+                .map(pair -> {
+                    if (pair.first != null && !pair.first.isEmpty()) {
+                        for (ImageDeepDetector.ImageFile item : pair.first) {
+                            item.delete();
+                            MutableLiveData<List<ImageDeepDetector.ImageFile>> liveData;
+                            if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_GALLERY) {
+                                liveData = detectedPhotoImg;
+                            } else if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_WECHAT) {
+                                liveData = detectedWxImg;
+                            } else if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_QQ) {
+                                liveData = detectedQQImg;
+                            } else {
+                                liveData = detectedOtherImg;
+                            }
+                            List<ImageDeepDetector.ImageFile> itemList = getList(liveData);
+                            itemList.remove(item);
+                        }
+                        detectedPhotoImg.postValue(getList(detectedPhotoImg));
+                        detectedWxImg.postValue(getList(detectedWxImg));
+                        detectedQQImg.postValue(getList(detectedQQImg));
+                        detectedOtherImg.postValue(getList(detectedOtherImg));
+                        list.removeAll(pair.first);
+                        selectedList.postValue(list);
+                    }
+                    return pair.second;
+                })
+                .map(uriList -> {
+                    if (uriList != null && !uriList.isEmpty()) {
+                        deleteUriListSdk11.postValue(uriList);
+                        return false;
+                    } else {
+                        return true;
+                    }
+                })
+                .flatMap(aBoolean -> {
+                    if (BoxingUtil.boxing(aBoolean)) {
+                        return Single.just(true);
+                    } else {
+                        return (SingleSource<Boolean>) observer -> this.dealMediaObserver = observer;
+                    }
+
+                })
+                .compose(RxJavaUtil.SingleSchedule.io2Main())
+                .subscribe(new SingleObserver<Boolean>() {
+
+                    @Override
+                    public void onSubscribe(@NonNull Disposable d) {
+                        showLoadingEvent.setValue(true);
+                    }
+
+                    @Override
+                    public void onSuccess(@NonNull Boolean result) {
+                        showLoadingEvent.setValue(false);
+                        detectedPhotoImg.setValue(getList(detectedPhotoImg));
+                        detectedWxImg.setValue(getList(detectedWxImg));
+                        detectedQQImg.setValue(getList(detectedQQImg));
+                        detectedOtherImg.setValue(getList(detectedOtherImg));
+                        ToastUtil.show(R.string.delete_success, ToastUtil.LENGTH_SHORT);
+                        checkAll.setValue(false);
+                        if (result) {
+                            list.clear();
+                            selectedList.setValue(list);
+                        }
+                        notifyList.call();
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+                        showLoadingEvent.setValue(false);
+                        ToastUtil.show(R.string.delete_fail, ToastUtil.LENGTH_SHORT);
+                    }
+                });
+    }
+
+
+    public long getFilePathToMediaID(String songPath, Context context) {
+        long id = 0;
+        ContentResolver cr = context.getContentResolver();
+
+        Uri uri = MediaStore.Files.getContentUri("external");
+        String selection = MediaStore.Audio.Media.DATA;
+        String[] selectionArgs = {songPath};
+        String[] projection = {MediaStore.Audio.Media._ID};
+        String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
+
+        Cursor cursor = cr.query(uri, projection, selection + "=?", selectionArgs, null);
+
+        if (cursor != null) {
+            while (cursor.moveToNext()) {
+                int idIndex = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
+                id = Long.parseLong(cursor.getString(idIndex));
             }
-            return true;
-        }, o -> {
-            detectedPhotoImg.setValue(getList(detectedPhotoImg));
-            detectedWxImg.setValue(getList(detectedWxImg));
-            detectedQQImg.setValue(getList(detectedQQImg));
-            detectedOtherImg.setValue(getList(detectedOtherImg));
-            checkAll.setValue(false);
-            showLoadingEvent.setValue(false);
-            ToastUtil.show(R.string.delete_success, ToastUtil.LENGTH_SHORT);
-            list.clear();
-            selectedList.setValue(list);
-            notifyList.call();
-        }, throwable -> {
-            showLoadingEvent.setValue(false);
-            ToastUtil.show(R.string.delete_fail, ToastUtil.LENGTH_SHORT);
-        });
+        }
+
+        return id;
     }
 
     public void onExportClick() {
@@ -422,4 +536,10 @@ public class ImageRecoverViewModel extends BaseViewModel {
                 break;
         }
     }
+
+    public void callDealComplete(boolean isDelete) {
+        if (dealMediaObserver != null) {
+            dealMediaObserver.onSuccess(isDelete);
+        }
+    }
 }

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

@@ -573,6 +573,10 @@ public class ImageDeepDetector {
             this.sizeDescribe = FileUtil.formatShortBytes(this.size);
         }
 
+        public String getPath() {
+            return path;
+        }
+
         public long getLastModified() {
             return lastModified;
         }