EasyPermissions替换默认Dialog

本文介绍如何替换EasyPermissions库中的默认对话框以匹配应用程序的设计风格。主要包括两部分内容:一是替换拒绝权限后出现的提示对话框;二是针对权限被永久拒绝的情况自定义对话框。

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()
       }
   }

在这里插入图片描述
2. 提示框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)
    }

成功:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值