Android 5.0 动态权限申请的基本流程和套路

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tctaccount/article/details/84892228

注:本文主要是梳理一下Android动态权限申请的一个基本套路。

需要有一定的Android编码经验,对于完全的新手来说,可能还有些技术细节没有做具体解释。

Android动态权限申请有效保证了用户的的安全,但是对开发者来说需要写跟多的代码逻辑来跟用户确认权限。

先不考虑代码,我们通过官方文档的描述来梳理一下整个权限处理的流程,如下图:

从上图可以看出,整个过程始于“权限检查”,归集于“授权回调”。

也就是说,除非本身就具备了相关权限,否则我们所有的后续操作都需要从授权回调开始往下走。

只是从授权回调往下走的时候,需要根据前面流程所形成的的条件,进行不同的操作。

从图中可以看出总共有三类分支(分别用红、黄、绿三色标注):

1、用户允许授权。

2、用户禁止授权,且点击了“不再提示”复选框。

3、用户禁止授权,但是没有点击“不再提示”复选框。

那么接下来我们就从这三种情况着手,将授权回调的流程继续梳理下去,如下图:

按照谷歌的设计意图,如果用户拒绝了权限,但是没有选择“不再提示”,我们就需要通过对话框等方式向用户解释为什么需要授予权限,然后再次申请权限,弹出授权对话框。

如果用户拒绝了权限,而且选择了“不再提示”,系统就不不会再弹出授权对话框。但是很多权限都是APP运行的基本保证,所以我们还是得想办法解释为什么需要授权,然后引导用户去授权。

我们可以看到,在授权回调函数中时,只要是用户用户已经拒绝了权限,我们都需要弹框向用户进行权限说明。

简洁起见,我们完全可以把上图中两个自定义对话框的形态做到完全一样,只是用户点击授权后的授权不方式不一样而已。

基于以上的完整流程分析,我们就可以设计出相应的代码。

此处以拨电话为例,先回顾一下上图中谷歌的API:

1、检测是否有权限。

        // BEGIN 动态权限申请代码段
        int hasCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
        if (hasCallPhonePermission == PackageManager.PERMISSION_GRANTED) {
            // 有权限,执行相关操作
            callPhone();
        } else {
            // 无权限,需要请求权限
            ...
        }
        // END

2、请求权限

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQ);

3、授权回调

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == CALL_PHONE_REQ) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户在授权对话框中授予了权限,执行相关操作
                callPhone();
            } else {
                // 没有授权
                if (ActivityCompat.shouldShowRequestPermissionRationale(
                        MainActivity.this, Manifest.permission.CALL_PHONE)) {
                    // 没有点选“不再提示”
                    showPermissionDialog(FLAG_REQUEST_PERMISSION);
                } else {
                    // 点选了“不再提示”
                    showPermissionDialog(FLAG_SETTINGS_PERMISSION);
                }
            }
        }
    }

4、弹出包含说明的授权对话框。

    private void showPermissionDialog(final int flag) {
        new AlertDialog.Builder(this).setTitle("授权提示")
                .setMessage("需要授予拨打电话权限才能打电话。")
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // 用户取消了授权,整个路程结束,不执行任何操作。
                        Toast.makeText(MainActivity.this, "取消拨打电话", Toast.LENGTH_SHORT).show();
                    }
                })
                .setPositiveButton("去授权", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        switch (flag) {
                            case FLAG_REQUEST_PERMISSION:
                                // 用户之前没有点击“不再提示”,但是此处选在继续授权的分支
                                // 请求系统授权对话框
                                ActivityCompat.requestPermissions(MainActivity.this,
                                        new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQ);
                                break;
                            case FLAG_SETTINGS_PERMISSION:
                                // 用户之前点击过“不再提示”,此处选择继续授权的分支
                                // 到APP的详情页手动授权。
                                startActivity(getAppDetailSettingIntent());
                                break;
                        }

                    }
                }).create().show();
    }

5、跳转到当前APP的应用详情页的Intent构造。

    private Intent getAppDetailSettingIntent() {
        Intent localIntent = new Intent();
        localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
        localIntent.setData(Uri.fromParts("package", getPackageName(), null));
        return localIntent;
    }

以上,与大家分享,希望能帮不太熟悉的朋友更清晰的梳理动态权限申请的整个流程。

猜你喜欢

转载自blog.csdn.net/tctaccount/article/details/84892228