EasyPermissions替换默认Dialog


前言

EasyPermissions是检查和申请Android动态权限的库,简化了原生权限逻辑。
使用方法参照官方文档


一、需求

需要对库里面封装了2个提示弹框替换成app内部统一的设计式样,分别是:

  • 提示框1: 用户拒绝权限后提示。

  • 提示框2: 用户拒绝权限且选择以后都不再询问时提示,在收到拒绝回调时show出内置的AppSettingsDialog。
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
  Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());

  // (Optional) Check whether the user denied any permissions and checked "NEVER ASK AGAIN."
  // This will display a dialog directing them to enable the permission in app settings.
  if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
      new AppSettingsDialog.Builder(this).build().show();
  }
}
复制代码

点击确定键会跳转到设置中的应用信息方便更改权限

public void onClick(DialogInterface dialog, int which) {
        if (which == Dialog.BUTTON_POSITIVE) {
            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                    .setData(Uri.fromParts("package", getPackageName(), null));
            intent.addFlags(mIntentFlags);
            startActivityForResult(intent, APP_SETTINGS_RC);
        } else if (which == Dialog.BUTTON_NEGATIVE) {
            setResult(Activity.RESULT_CANCELED);
            finish();
        } else {
            throw new IllegalStateException("Unknown button type: " + which);
        }
    }
复制代码

二、实现

  1. 提示框2很好替换,把AppSettingsDialog替换成自己的Dialog就可以了。
override fun onPermissionsDenied(requestCode: Int, perms: List<String>) {
       if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
           CommonDialog.Builder(this).build().show()
       }
   }
复制代码

  1. 提示框1没找到公开能替换的方法。

请求权限时的调用:

private fun requestPermission(vararg perms: String) {
       val request = PermissionRequest.Builder(this, REQUEST_CODE_PERMISSIONS, *perms)
           .setRationale("This app may not work correctly without the requested permissions.")
           .setPositiveButtonText("确定")
           .setNegativeButtonText("取消")
           .build()
       EasyPermissions.requestPermissions(request)
   }
复制代码

先看一下源码,通过PermissionRequest的getHelper()取到PermissionHelper,然后调用的requestPermissions方法申请权限

public static void requestPermissions(PermissionRequest request) {

        // Check for permissions before dispatching the request
        if (hasPermissions(request.getHelper().getContext(), request.getPerms())) {
            notifyAlreadyHasPermissions(
                    request.getHelper().getHost(), request.getRequestCode(), request.getPerms());
            return;
        }

        // Request permissions
        request.getHelper().requestPermissions(
                request.getRationale(),
                request.getPositiveButtonText(),
                request.getNegativeButtonText(),
                request.getTheme(),
                request.getRequestCode(),
                request.getPerms());
    }
复制代码

PermissionHelper是在创建PermissionRequest时创建的

 public Builder(@NonNull Activity activity, int requestCode,
                       @NonNull @Size(min = 1) String... perms) {
            mHelper = PermissionHelper.newInstance(activity);
            mRequestCode = requestCode;
            mPerms = perms;
        }
        
public Builder(@NonNull Fragment fragment, int requestCode,
                       @NonNull @Size(min = 1) String... perms) {
            mHelper = PermissionHelper.newInstance(fragment);
            mRequestCode = requestCode;
            mPerms = perms;
        }
复制代码

PermissionHelper调用showRequestPermissionRationale显示弹框

public void requestPermissions(@NonNull String rationale,
                                   @NonNull String positiveButton,
                                   @NonNull String negativeButton,
                                   @StyleRes int theme,
                                   int requestCode,
                                   @NonNull String... perms) {
        if (shouldShowRationale(perms)) {
            showRequestPermissionRationale(
                    rationale, positiveButton, negativeButton, theme, requestCode, perms);
        } else {
            directRequestPermissions(requestCode, perms);
        }
    }
复制代码

PermissionHelper是个抽象类,继承关系如下

找个BaseSupportPermissionsHelper的showRequestPermissionRationale方法看一下

public void showRequestPermissionRationale(@NonNull String rationale,
                                               @NonNull String positiveButton,
                                               @NonNull String negativeButton,
                                               @StyleRes int theme,
                                               int requestCode,
                                               @NonNull String... perms) {

        FragmentManager fm = getSupportFragmentManager();

        // Check if fragment is already showing
        Fragment fragment = fm.findFragmentByTag(RationaleDialogFragmentCompat.TAG);
        if (fragment instanceof RationaleDialogFragmentCompat) {
            Log.d(TAG, "Found existing fragment, not showing rationale.");
            return;
        }

        RationaleDialogFragmentCompat
                .newInstance(rationale, positiveButton, negativeButton, theme, requestCode, perms)
                .showAllowingStateLoss(fm, RationaleDialogFragmentCompat.TAG);
    }
复制代码

RationaleDialogFragmentCompat继承自DialogFragment

@Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Rationale dialog should not be cancelable
        setCancelable(false);

        // Get config from arguments, create click listener
        RationaleDialogConfig config = new RationaleDialogConfig(getArguments());
        RationaleDialogClickListener clickListener =
                new RationaleDialogClickListener(this, config, mPermissionCallbacks, mRationaleCallbacks);

        // Create an AlertDialog
        return config.createSupportDialog(getContext(), clickListener);
    }
复制代码

RationaleDialogConfig:

AlertDialog createSupportDialog(Context context, Dialog.OnClickListener listener) {
        AlertDialog.Builder builder;
        if (theme > 0) {
            builder = new AlertDialog.Builder(context, theme);
        } else {
            builder = new AlertDialog.Builder(context);
        }
        return builder
                .setCancelable(false)
                .setPositiveButton(positiveButton, listener)
                .setNegativeButton(negativeButton, listener)
                .setMessage(rationaleMsg)
                .create();
    }
复制代码

从上面看是可以把源码下载一份替换默认的AlertDialog后打包使用的,这个就不多说了。这里采用了另外一个方案:可以hook替换PermissionRequest的mHelper

private final PermissionHelper mHelper;
复制代码

更改mHelper的showRequestPermissionRationale方法来弹出自己的Dialog,先定义一个代理类:

public class PermissionsHelperProxy<T>(
    private val permissionHelper: BaseSupportPermissionsHelper<T>
) : BaseSupportPermissionsHelper<T>(permissionHelper.host!!) {

    override fun directRequestPermissions(requestCode: Int, vararg perms: String?) {
        permissionHelper.directRequestPermissions(requestCode, *perms)
    }

    override fun shouldShowRequestPermissionRationale(perm: String): Boolean {
        return permissionHelper.shouldShowRequestPermissionRationale(perm)
    }

    override fun getContext(): Context {
        return permissionHelper.context
    }

    override fun getSupportFragmentManager(): FragmentManager {
        return permissionHelper.supportFragmentManager
    }

    override fun showRequestPermissionRationale(
        rationale: String,
        positiveButton: String,
        negativeButton: String,
        @StyleRes theme: Int,
        requestCode: Int,
        vararg perms: String
    ) {
        CommonDialog.Builder(context).build().show()
    }
复制代码

在请求权限时替换:

private fun requestPermission(vararg perms: String) {
        val request = PermissionRequest.Builder(this, REQUEST_CODE_PERMISSIONS, *perms)
            .setRationale("This app may not work correctly without the requested permissions.")
            .setPositiveButtonText("确定")
            .setNegativeButtonText("取消")
            .build()
        try {
            val clazz = request.javaClass
            val field = clazz.getDeclaredField("mHelper")
            field.isAccessible = true
            val permissionHelper =
                field.get(request) as BaseSupportPermissionsHelper<AppCompatActivity?>
            field.set(request, PermissionsHelperProxy(permissionHelper))
        } catch (e: Exception) {
        }
        EasyPermissions.requestPermissions(request)
    }
复制代码

成功:

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享