Explorar el Código

调整先跳转会员后授予权限

zk hace 2 años
padre
commit
491571eb3d

+ 13 - 12
app/src/main/java/com/datarecovery/master/data/repositories/DeviceFuncRepository.java

@@ -42,17 +42,16 @@ public class DeviceFuncRepository {
 
 
     public boolean isHaveAuth(@MemberType String auth) {
-        return true;
-//        if (TextUtils.isEmpty(auth) || authsList.size() == 0) {
-//            return false;
-//        }
-//        if (!Objects.equals(auth, MemberType.APP_IMAGE_CLEAN) && authsList.contains(MemberType.APP_SUPER_RECOVER)) {
-//            return true;
-//        }
-//        if (Objects.equals(auth, MemberType.APP_WX_MESSAGE_RECOVER) || Objects.equals(auth, MemberType.APP_WX_FRIEND_RECOVER)) {
-//            return authsList.contains(MemberType.APP_WX_MESSAGE_RECOVER) || authsList.contains(MemberType.APP_WX_FRIEND_RECOVER);
-//        }
-//        return authsList.contains(auth);
+        if (TextUtils.isEmpty(auth) || authsList.size() == 0) {
+            return false;
+        }
+        if (!Objects.equals(auth, MemberType.APP_IMAGE_CLEAN) && authsList.contains(MemberType.APP_SUPER_RECOVER)) {
+            return true;
+        }
+        if (Objects.equals(auth, MemberType.APP_WX_MESSAGE_RECOVER) || Objects.equals(auth, MemberType.APP_WX_FRIEND_RECOVER)) {
+            return authsList.contains(MemberType.APP_WX_MESSAGE_RECOVER) || authsList.contains(MemberType.APP_WX_FRIEND_RECOVER);
+        }
+        return authsList.contains(auth);
     }
 
     public void refreshFuncAuths() {
@@ -72,7 +71,9 @@ public class DeviceFuncRepository {
                     public void onSuccess(@NonNull FuncAuthsResponse funcAuthsResponse) {
                         refreshFunAuthsFlag = false;
                         authsList.clear();
-                        authsList.addAll(funcAuthsResponse.getAuths());
+                        if (!TextUtils.isEmpty(AccountRepository.token)) {
+                            authsList.addAll(funcAuthsResponse.getAuths());
+                        }
                     }
 
                     @Override

+ 9 - 1
app/src/main/java/com/datarecovery/master/data/repositories/PayRepository.java

@@ -1,6 +1,8 @@
 package com.datarecovery.master.data.repositories;
 
 
+import android.text.TextUtils;
+
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 
@@ -47,7 +49,13 @@ public class PayRepository {
         return atmobApi.orderPage(new OrderPageRequest(limit, offset))
                 .compose(RxHttpHandler.handle(true))
                 .compose(RxJavaUtil.SingleSchedule.io2Main())
-                .doOnSuccess(orderPageResponse -> orderList.setValue(orderPageResponse.getList()));
+                .doOnSuccess(orderPageResponse -> {
+                    if (TextUtils.isEmpty(AccountRepository.token)) {
+                        orderList.setValue(null);
+                    } else {
+                        orderList.setValue(orderPageResponse.getList());
+                    }
+                });
 
     }
 

+ 72 - 0
app/src/main/java/com/datarecovery/master/dialog/PermissionDialog.java

@@ -0,0 +1,72 @@
+package com.datarecovery.master.dialog;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+
+import com.atmob.app.lib.base.BaseDialog;
+import com.datarecovery.master.R;
+import com.datarecovery.master.databinding.DialogCommonSureBinding;
+
+@BaseDialog.FullScreen(height = false)
+public class PermissionDialog extends BaseDialog<DialogCommonSureBinding> {
+
+
+    private OnDialogClickListener onDialogClickListener;
+
+    public PermissionDialog(@NonNull Context context) {
+        super(context, R.style.Theme_Common_Dialog);
+        setCancelable(false);
+        binding.setOnClickSure(v -> {
+            if (onDialogClickListener != null) {
+                onDialogClickListener.onClickSure();
+            }
+        });
+        binding.setOnClickCancel(v -> {
+            dismiss();
+            if (onDialogClickListener != null)
+                onDialogClickListener.onClickCancel();
+        });
+    }
+
+    public void setOnDialogClickListener(OnDialogClickListener onDialogClickListener) {
+        this.onDialogClickListener = onDialogClickListener;
+    }
+
+    public PermissionDialog setDialogTitle(@StringRes int tips) {
+        binding.tvDialogTitle.setText(tips);
+        return this;
+    }
+
+    public PermissionDialog setTitleGravity(int gravity) {
+        binding.tvDialogTitle.setGravity(gravity);
+        return this;
+    }
+
+    public PermissionDialog setDialogContent(@StringRes int content) {
+        binding.tvContent.setText(content);
+        return this;
+    }
+
+    public PermissionDialog setContentGravity(int gravity) {
+        binding.tvContent.setGravity(gravity);
+        return this;
+    }
+
+    public PermissionDialog setSureText(@StringRes int sureText) {
+        binding.tvSure.setText(sureText);
+        return this;
+    }
+
+    public PermissionDialog setCancelText(@StringRes int cancelText) {
+        binding.tvCancel.setText(cancelText);
+        return this;
+    }
+
+    public interface OnDialogClickListener {
+        void onClickSure();
+
+        void onClickCancel();
+    }
+}

+ 16 - 0
app/src/main/java/com/datarecovery/master/module/audiorecover/AudioRecoverActivity.java

@@ -26,6 +26,7 @@ import com.datarecovery.master.dialog.CommonSureDialog;
 import com.datarecovery.master.dialog.ScanProgressDialog;
 import com.datarecovery.master.module.preview.PreviewActivity;
 import com.datarecovery.master.utils.BoxingUtil;
+import com.datarecovery.master.utils.FilePermissionHelper;
 import com.datarecovery.master.utils.FilesSearch;
 import com.gyf.immersionbar.ImmersionBar;
 
@@ -63,6 +64,21 @@ public class AudioRecoverActivity extends BaseActivity<ActivityAudioRecoverBindi
         super.onCreate(savedInstanceState);
         initView();
         initObserver();
+        initPermission();
+    }
+
+    private void initPermission() {
+        FilePermissionHelper.requestDataFilePermission(this, new FilePermissionHelper.NextStepCallback() {
+            @Override
+            public void onNextStep() {
+                audioRecoverViewModel.startAudioScanning();
+            }
+
+            @Override
+            public void onCancel() {
+                finish();
+            }
+        });
     }
 
     private void initView() {

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

@@ -77,7 +77,6 @@ public class AudioRecoverViewModel extends BaseViewModel {
             }
             return ContextUtil.getContext().getString(R.string.export_count, list.size());
         });
-        startAudioScanning();
     }
 
 
@@ -133,7 +132,10 @@ public class AudioRecoverViewModel extends BaseViewModel {
         return showScanDialogEvent;
     }
 
-    private void startAudioScanning() {
+    public void startAudioScanning() {
+        if (scanDisposable != null && !scanDisposable.isDisposed()) {
+            return;
+        }
         FilesSearch.search(ContextUtil.getContext(), FilesSearch.DocumentFile.AUDIO)
                 .take(SCANNING_COUNTDOWN, TimeUnit.MILLISECONDS)
                 .observeOn(AndroidSchedulers.mainThread())

+ 16 - 0
app/src/main/java/com/datarecovery/master/module/filerecover/FileRecoverActivity.java

@@ -18,6 +18,7 @@ import com.datarecovery.master.dialog.CommonLoadingDialog;
 import com.datarecovery.master.dialog.CommonSureDialog;
 import com.datarecovery.master.dialog.ScanProgressDialog;
 import com.datarecovery.master.utils.BoxingUtil;
+import com.datarecovery.master.utils.FilePermissionHelper;
 import com.google.android.material.tabs.TabLayout;
 import com.google.android.material.tabs.TabLayoutMediator;
 
@@ -52,6 +53,21 @@ public class FileRecoverActivity extends BaseActivity<ActivityFileRecoverBinding
         super.onCreate(savedInstanceState);
         initView();
         initObserver();
+        initPermission();
+    }
+
+    private void initPermission() {
+        FilePermissionHelper.requestDataFilePermission(this, new FilePermissionHelper.NextStepCallback() {
+            @Override
+            public void onNextStep() {
+                fileRecoverViewModel.startFileScanning();
+            }
+
+            @Override
+            public void onCancel() {
+                finish();
+            }
+        });
     }
 
     private void initObserver() {

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

@@ -64,7 +64,6 @@ public class FileRecoverViewModel extends BaseViewModel {
             }
             return ContextUtil.getContext().getString(R.string.export_count, list.size());
         });
-        startFileScanning();
         for (int i = 0; i < tabTitle.length; i++) checkList.add(new MutableLiveData<>(false));
     }
 
@@ -123,7 +122,10 @@ public class FileRecoverViewModel extends BaseViewModel {
         this.checkPosition.setValue(position);
     }
 
-    private void startFileScanning() {
+    public void startFileScanning() {
+        if (scanDisposable != null && !scanDisposable.isDisposed()) {
+            return;
+        }
         FilesSearch.search(ContextUtil.getContext(), FilesSearch.DocumentFile.WORD, FilesSearch.DocumentFile.EXCEL, FilesSearch.DocumentFile.PPT, FilesSearch.DocumentFile.PDF)
                 .take(SCANNING_COUNTDOWN, TimeUnit.MILLISECONDS)
                 .observeOn(AndroidSchedulers.mainThread())

+ 5 - 64
app/src/main/java/com/datarecovery/master/module/homepage/HomePageViewModel.java

@@ -3,7 +3,6 @@ package com.datarecovery.master.module.homepage;
 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.repositories.DeviceFuncRepository;
 import com.datarecovery.master.module.audiorecover.AudioRecoverActivity;
@@ -13,22 +12,14 @@ import com.datarecovery.master.module.member.MemberActivity;
 import com.datarecovery.master.module.member.MemberType;
 import com.datarecovery.master.module.videorecover.VideoRecoverActivity;
 import com.datarecovery.master.module.wxrecover.WeChatRecoverActivity;
-import com.datarecovery.master.utils.PermissionUtil;
-import com.datarecovery.master.utils.xfile.XFilePermission;
 
 import java.util.ArrayList;
 import java.util.List;
 
 import javax.inject.Inject;
 
-import atmob.reactivex.rxjava3.annotations.NonNull;
-import atmob.reactivex.rxjava3.core.Single;
-import atmob.reactivex.rxjava3.core.SingleObserver;
-import atmob.reactivex.rxjava3.disposables.Disposable;
-import atmob.rxjava.utils.RxJavaUtil;
 import dagger.hilt.android.lifecycle.HiltViewModel;
 
-import android.os.Build;
 import android.util.Pair;
 
 import androidx.lifecycle.LiveData;
@@ -91,7 +82,7 @@ public class HomePageViewModel extends BaseViewModel {
     }
 
     public void onImgRecoveryClick() {
-        isHaveAuths(MemberType.APP_IMAGE_RECOVER, () -> isCheckPermission(() -> ImageRecoverActivity.start(ActivityUtil.getTopActivity(), ImageRecoverActivity.Type.RECOVER)));
+        isHaveAuths(MemberType.APP_IMAGE_RECOVER, () -> ImageRecoverActivity.start(ActivityUtil.getTopActivity(), ImageRecoverActivity.Type.RECOVER));
     }
 
     public void isHaveAuths(@MemberType String type, NextStepCallback stepCallback) {
@@ -102,51 +93,6 @@ public class HomePageViewModel extends BaseViewModel {
         }
     }
 
-    /**
-     * 判断是否有所需的存储权限
-     *
-     * @param stepCallback 有权限的回调
-     */
-    public void isCheckPermission(NextStepCallback stepCallback) {
-        Single.just(Build.VERSION.SDK_INT).map(sdkInt -> {
-                    //判断是否有所有文件权限
-                    boolean result = PermissionUtil.hasFilePermission();
-                    if (!result) {
-                        throw new RequestManageExternalException();
-                    }
-                    return sdkInt;
-                }).map(sdkInt -> {
-                    if (sdkInt >= Build.VERSION_CODES.TIRAMISU) {
-                        return true;
-                    }
-                    boolean dataFolder = XFilePermission.hasAndroidDataPermission(ContextUtil.getContext());
-                    if (!dataFolder) {
-                        throw new RequestDataFolderException();
-                    }
-                    return true;
-                })
-                .compose(RxJavaUtil.SingleSchedule.io2Main())
-                .subscribe(new SingleObserver<Boolean>() {
-                    @Override
-                    public void onSubscribe(@NonNull Disposable d) {
-                        addDisposable(d);
-                    }
-
-                    @Override
-                    public void onSuccess(@NonNull Boolean aBoolean) {
-                        if (stepCallback != null) stepCallback.onNextStep();
-                    }
-
-                    @Override
-                    public void onError(@NonNull Throwable e) {
-                        if (e instanceof RequestManageExternalException) {
-                            requestManagePermission.call();
-                        } else if (e instanceof RequestDataFolderException) {
-                            requestAndroidDataPermission.call();
-                        }
-                    }
-                });
-    }
 
     public void clickItemFunction(FunctionBean bean) {
         if (bean == null) {
@@ -154,16 +100,16 @@ public class HomePageViewModel extends BaseViewModel {
         }
         switch (bean.getFunctionId()) {
             case FunctionBean.AUDIO_RECOVERY:
-                isHaveAuths(MemberType.APP_AUDIO_RECOVER, () -> isCheckPermission(() -> AudioRecoverActivity.start(ActivityUtil.getTopActivity())));
+                isHaveAuths(MemberType.APP_AUDIO_RECOVER, () -> AudioRecoverActivity.start(ActivityUtil.getTopActivity()));
                 break;
             case FunctionBean.FILE_RECOVERY:
-                isHaveAuths(MemberType.APP_FILE_RECOVER, () -> isCheckPermission(() -> FileRecoverActivity.start(ActivityUtil.getTopActivity())));
+                isHaveAuths(MemberType.APP_FILE_RECOVER, () -> FileRecoverActivity.start(ActivityUtil.getTopActivity()));
                 break;
             case FunctionBean.IMG_CLEARING:
-                isHaveAuths(MemberType.APP_IMAGE_CLEAN, () -> isCheckPermission(() -> ImageRecoverActivity.start(ActivityUtil.getTopActivity(), ImageRecoverActivity.Type.DELETE)));
+                isHaveAuths(MemberType.APP_IMAGE_CLEAN, () -> ImageRecoverActivity.start(ActivityUtil.getTopActivity(), ImageRecoverActivity.Type.DELETE));
                 break;
             case FunctionBean.VIDEO_RECOVERY:
-                isHaveAuths(MemberType.APP_VIDEO_RECOVER, () -> isCheckPermission(() -> VideoRecoverActivity.start(ActivityUtil.getTopActivity())));
+                isHaveAuths(MemberType.APP_VIDEO_RECOVER, () -> VideoRecoverActivity.start(ActivityUtil.getTopActivity()));
                 break;
         }
 
@@ -173,11 +119,6 @@ public class HomePageViewModel extends BaseViewModel {
         void onNextStep();
     }
 
-    public static class RequestManageExternalException extends Exception {
-    }
-
-    public static class RequestDataFolderException extends Exception {
-    }
 
 
 }

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

@@ -23,6 +23,7 @@ import com.datarecovery.master.dialog.CommonSureDialog;
 import com.datarecovery.master.dialog.ScanProgressDialog;
 import com.datarecovery.master.module.preview.PreviewActivity;
 import com.datarecovery.master.utils.BoxingUtil;
+import com.datarecovery.master.utils.FilePermissionHelper;
 import com.datarecovery.master.utils.GridRecoverItemDecoration;
 import com.datarecovery.master.utils.ImageDeepDetector;
 import com.google.android.material.tabs.TabLayout;
@@ -78,6 +79,21 @@ public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBindi
         initData();
         initView();
         initObserver();
+        initPermission();
+    }
+
+    private void initPermission() {
+        FilePermissionHelper.requestDataFilePermission(this, new FilePermissionHelper.NextStepCallback() {
+            @Override
+            public void onNextStep() {
+                imageRecoverViewModel.startImageScanning();
+            }
+
+            @Override
+            public void onCancel() {
+                finish();
+            }
+        });
     }
 
     private void initData() {

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

@@ -68,7 +68,6 @@ public class ImageRecoverViewModel extends BaseViewModel {
     public ImageRecoverViewModel(DeviceFuncRepository deviceFuncRepository) {
         this.deviceFuncRepository = deviceFuncRepository;
         barTitle.setValue(ContextUtil.getContext().getString(R.string.iamge_recover_all));
-        startImageScanning();
         initLiveData();
     }
 
@@ -201,7 +200,10 @@ public class ImageRecoverViewModel extends BaseViewModel {
         return selectList;
     }
 
-    private void startImageScanning() {
+    public void startImageScanning() {
+        if (scanDisposable != null && !scanDisposable.isDisposed()) {
+            return;
+        }
         ImageDeepDetector.detect(ContextUtil.getContext())
                 .take(SCANNING_COUNTDOWN, TimeUnit.MILLISECONDS)
                 .observeOn(AndroidSchedulers.mainThread())

+ 1 - 1
app/src/main/java/com/datarecovery/master/module/order/OrderViewModel.java

@@ -46,7 +46,7 @@ public class OrderViewModel extends BaseViewModel {
         payRepository.orderPage(0, 200).subscribe(new SingleObserver<OrderPageResponse>() {
             @Override
             public void onSubscribe(@NonNull Disposable d) {
-
+                addDisposable(d);
             }
 
             @Override

+ 16 - 0
app/src/main/java/com/datarecovery/master/module/videorecover/VideoRecoverActivity.java

@@ -18,6 +18,7 @@ import com.datarecovery.master.dialog.CommonSureDialog;
 import com.datarecovery.master.dialog.ScanProgressDialog;
 import com.datarecovery.master.module.preview.PreviewActivity;
 import com.datarecovery.master.utils.BoxingUtil;
+import com.datarecovery.master.utils.FilePermissionHelper;
 import com.datarecovery.master.utils.FilesSearch;
 import com.datarecovery.master.utils.GridRecoverItemDecoration;
 import com.gyf.immersionbar.ImmersionBar;
@@ -49,6 +50,21 @@ public class VideoRecoverActivity extends BaseActivity<ActivityVideoRecoverBindi
         super.onCreate(savedInstanceState);
         initView();
         initObserver();
+        initPermission();
+    }
+
+    private void initPermission() {
+        FilePermissionHelper.requestDataFilePermission(this, new FilePermissionHelper.NextStepCallback() {
+            @Override
+            public void onNextStep() {
+                videoRecoverViewModel.startVideoScanning();
+            }
+
+            @Override
+            public void onCancel() {
+                finish();
+            }
+        });
     }
 
     private void initObserver() {

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

@@ -55,7 +55,6 @@ public class VideoRecoverViewModel extends BaseViewModel {
     @Inject
     public VideoRecoverViewModel(DeviceFuncRepository deviceFuncRepository) {
         this.deviceFuncRepository = deviceFuncRepository;
-        startVideoScanning();
         selectedCountTxt = Transformations.map(selectedList, list -> {
             if (list == null || list.isEmpty()) {
                 return ContextUtil.getContext().getString(R.string.export);
@@ -104,7 +103,10 @@ public class VideoRecoverViewModel extends BaseViewModel {
         return showLoadingEvent;
     }
 
-    private void startVideoScanning() {
+    public void startVideoScanning() {
+        if (scanDisposable != null && !scanDisposable.isDisposed()) {
+            return;
+        }
         FilesSearch.search(ContextUtil.getContext(), FilesSearch.DocumentFile.VIDEO)
                 .take(SCANNING_COUNTDOWN, TimeUnit.MILLISECONDS)
                 .observeOn(AndroidSchedulers.mainThread())

+ 158 - 0
app/src/main/java/com/datarecovery/master/utils/FilePermissionHelper.java

@@ -0,0 +1,158 @@
+package com.datarecovery.master.utils;
+
+import android.os.Build;
+import android.view.Gravity;
+
+import androidx.activity.ComponentActivity;
+
+import com.atmob.app.lib.livedata.SingleLiveEvent;
+import com.atmob.common.runtime.ContextUtil;
+import com.datarecovery.master.R;
+import com.datarecovery.master.dialog.CommonSureDialog;
+import com.datarecovery.master.dialog.PermissionDialog;
+import com.datarecovery.master.module.homepage.HomePageViewModel;
+import com.datarecovery.master.utils.xfile.XFilePermission;
+
+import atmob.reactivex.rxjava3.annotations.NonNull;
+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;
+
+public class FilePermissionHelper {
+
+    public static void requestDataFilePermission(ComponentActivity activity, NextStepCallback stepCallback) {
+
+        Single.just(Build.VERSION.SDK_INT).flatMap((Function<Integer, SingleSource<Integer>>) sdkInt -> {
+                    //判断是否有所有文件权限
+                    boolean result = PermissionUtil.hasFilePermission();
+                    if (!result) {
+                        return (SingleSource<Integer>) observer -> {
+                            if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
+                                return;
+                            }
+                            activity.runOnUiThread(() -> {
+                                PermissionDialog requestManageDialog = new PermissionDialog(activity);
+                                requestManageDialog.setDialogTitle(R.string.request_manage_permission_title)
+                                        .setDialogContent(R.string.request_manage_permission_content)
+                                        .setTitleGravity(Gravity.START)
+                                        .setContentGravity(Gravity.START)
+                                        .setSureText(R.string.teaching_limit)
+                                        .setOnDialogClickListener(new PermissionDialog.OnDialogClickListener() {
+                                            @Override
+                                            public void onClickSure() {
+                                                PermissionUtil.requestWriteStoragePermission(activity, new PermissionUtil.PermissionCallback() {
+                                                    @Override
+                                                    public void onPermissionGranted() {
+                                                        if (activity.isFinishing() || activity.isDestroyed()) {
+                                                            return;
+                                                        }
+                                                        requestManageDialog.dismiss();
+                                                        observer.onSuccess(sdkInt);
+                                                    }
+
+                                                    @Override
+                                                    public void onPermissionDenied() {
+
+                                                    }
+                                                });
+                                            }
+
+                                            @Override
+                                            public void onClickCancel() {
+                                                if (activity.isFinishing() || activity.isDestroyed()) {
+                                                    return;
+                                                }
+                                                observer.onError(new CancelException());
+                                            }
+                                        });
+                                requestManageDialog.show();
+                            });
+                        };
+                    } else {
+                        return Single.just(sdkInt);
+                    }
+                })
+                .flatMap((Function<Integer, SingleSource<Integer>>) sdkInt -> {
+                    if (sdkInt >= Build.VERSION_CODES.TIRAMISU) {
+                        return Single.just(sdkInt);
+                    }
+                    boolean dataFolder = XFilePermission.hasAndroidDataPermission(ContextUtil.getContext());
+                    if (!dataFolder) {
+                        return observer -> {
+                            if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
+                                return;
+                            }
+                            activity.runOnUiThread(() -> {
+                                PermissionDialog requestAndroidDataDialog = new PermissionDialog(activity);
+                                requestAndroidDataDialog.setDialogTitle(R.string.request_android_data_permission_title)
+                                        .setDialogContent(R.string.request_android_data_permission_content)
+                                        .setCancelText(R.string.wait_moment)
+                                        .setSureText(R.string.teaching_limit)
+                                        .setOnDialogClickListener(new PermissionDialog.OnDialogClickListener() {
+                                            @Override
+                                            public void onClickSure() {
+                                                XFilePermission.requestAndroidDataPermission(activity, new XFilePermission.PermissionCallback() {
+                                                    @Override
+                                                    public void onPermissionGranted() {
+                                                        if (activity.isFinishing() || activity.isDestroyed()) {
+                                                            return;
+                                                        }
+                                                        requestAndroidDataDialog.dismiss();
+                                                        observer.onSuccess(sdkInt);
+                                                    }
+
+                                                    @Override
+                                                    public void onPermissionDenied() {
+
+                                                    }
+                                                });
+                                            }
+
+                                            @Override
+                                            public void onClickCancel() {
+                                                if (activity.isFinishing() || activity.isDestroyed()) {
+                                                    return;
+                                                }
+                                                observer.onError(new CancelException());
+                                            }
+                                        });
+                                requestAndroidDataDialog.show();
+                            });
+                        };
+                    } else {
+                        return Single.just(sdkInt);
+                    }
+                })
+                .compose(RxJavaUtil.SingleSchedule.io2Main())
+                .subscribe(new SingleObserver<Integer>() {
+                    @Override
+                    public void onSubscribe(@NonNull Disposable d) {
+
+                    }
+
+                    @Override
+                    public void onSuccess(@NonNull Integer sdkInt) {
+                        if (stepCallback != null) stepCallback.onNextStep();
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+                        if (e instanceof CancelException) {
+                            if (stepCallback != null) stepCallback.onCancel();
+                        }
+                    }
+                });
+    }
+
+    public interface NextStepCallback {
+        void onNextStep();
+
+        void onCancel();
+    }
+
+    private static class CancelException extends Exception {
+    }
+}