|
|
@@ -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);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|