Android 6.0运行时权限处理与封装(一)

Android 6.0运行时权限处理与封装

众所周知,在Android 6.0之后,Android对一些用户的敏感权限进行了进一步加强,需要用户去动态授予权限。


前言

在API23之前,只要在AndroidManifest.xml中注册过的权限,程序运行时都会自动获取到。但是到了23及更高,危险的权限就需要我们自己来动态的申请了,而此时用户也就有了拒绝我们需要的权限的权力,这当然会导致我们程序的运行不正常,甚至是造成程序的崩溃。所以我们就需要尽可能的提示用户同意我们的权限申请。

说明

系统权限分为几个保护级别。需要了解的两个最重要保护级别是正常权限和危险权限。 首先,你必须得知道哪些是需要动态申请的权限,也就是我前面所提到的危险权限,并且危险权限也分组,所以到底哪些是危险权限呢?

这里我们涉及到9大组危险权限,但是可喜可贺的是我们只需要申请每组中的一个权限,就能获取到全组权限的授权。

1、关于日历的权限:
 <uses-permission android:name="android.permission.READ_CALENDAR"/>
 <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
 2、关于相机的权限:
 <uses-permission android:name="android.permission.CAMERA"/>
 3、关于联系人的权限:
 <uses-permission android:name="android.permission.READ_CONTACTS"/>
 <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
 <uses-permission android:name="android.permission.GET_CONTACTS"/>
 4、关于位置的权限:
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
 5、关于电话的权限:
 <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
 <uses-permission android:name="android.permission.CALL_PHONE"/>
 <uses-permission android:name="android.permission.READ_CALL_LOG"/>
 <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
 <uses-permission android:name="android.permission.USE_SIP"/>
 <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
 6、关于传感器的权限:
 <uses-permission android:name="android.permission.BODY_SENSORS"/>
 7、关于短信的权限:
 <uses-permission android:name="android.permission.SEND_SMS"/>
 <uses-permission android:name="android.permission.RECEIVE_SMS"/>
 <uses-permission android:name="android.permission.READ_SMS"/>
 <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/>
 <uses-permission android:name="android.permission.RECEIVE_MMS"/>
 <uses-permission android:name="android.permission.READ_CELL_BROADCASTS"/>
 8、关于SD卡的权限
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 9、关于录音的权限
 <uses-permission android:name="android.permission.RECORD_AUDIO"/>

案例

这里我们通过一个打电话的案例进行说明

我们在6.0之前写打电话功能

第一步:在清单文件中申明打电话权限:

<uses-permission android:name="android.permission.CALL_PHONE"/>

第二步:

Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:" + mPhoneNumber);
        intent.setData(data);
        startActivity(intent);

之前这两步就可以实现一个打电话的功能,但是现在不行了,现在回程序运行会崩溃,因为你没有动态申请用户打电话权限。

我们在6.0之后写打电话功能

现在我们需要去检测该权限有没有背用户授予过,如果没有则需要申请打电话权限,如果有授予过可以直接拨打电话。

ContextCompat.checkSelfPermission:检测权限
ActivityCompat.requestPermissions:申请权限

第一步:检测用户用没有授权打电话,如果没有就需要申请权限

findViewById(R.id.btn_call).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission
                        .CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    // 没有该权限 申请打电话权限
                    //  Context ,
                    // 第二个参数是用户需要申请的权限字符串数组,
                    // 第三个参数是请求码 主要用来处理用户选择的返回结果
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUEST_CODE);
                } else {
                    callPhone();
                }
            }
        });

是的,就是这么简单。不过,如果你就这样子用在了你的项目里,会有坑!!!

如果你本身就是Android用户,细心的你一定会发现,App在向你申请权限的时候,你会有几个选项:

1.允许
2.拒绝
3.还可以拒绝并不再提示!(坑就出现在这里了)
如果按上面的代码,你会永远得到一个答案:用户拒绝!!(如果用户是不小心点错,或者出于好奇心尝试,那很容易就懵逼了)

所以我们还需要对第一步做个调整

findViewById(R.id.btn_call).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission
                        .CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    // 没有该权限 申请打电话权限
                    //  Context ,
                    // 第二个参数是用户需要申请的权限字符串数组,
                    // 第三个参数是请求码 主要用来处理用户选择的返回结果
                    // 1、此时还没有权限!
                    if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                            Manifest.permission.CALL_PHONE)) {
                        // 2、用户还没选择或选择了但没选择拒绝并不再提示
                        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUEST_CODE);
                    } else {
                        // 3、用户点选了不再提示
                        //(正经的告诉用户这个功能必须给权限啊,求权限啊!最好告诉他怎么去设置!)
                        showTipsDialog(MainActivity.this);
                    }
                } else {
                    // 有权限了,去做该做的事情吧!
                    callPhone();
                }
            }
        });

优化部分:还可以拒绝并不再提示!,我们添加了一个可以让用户设置的跳转

/**
     * 显示提示对话框(这个提示款适用于点击按钮请求权限的问题)
     * 如果需要强制获取权限,需要自定义对话框
     */
    public static void showTipsDialog(final Context context) {
        new AlertDialog.Builder(context)
                .setTitle("提示信息")
                .setMessage("当前应用缺少必要权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。")
                .setNegativeButton("取消", null)
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        startAppSettings(context);
                    }
                }).show();
    }
    /**
     * 启动当前应用设置页面
     */
    private static void startAppSettings(Context context) {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + context.getPackageName()));
        context.startActivity(intent);
    }

第二步: 处理回调 如果用户同意或是拒绝那么会回调onRequestPermissionsResult()

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(requestCode == CALL_PHONE_REQUEST_CODE){
            if (grantResults !=null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission Granted  通过  打电话
                callPhone();
            } else {
                // Permission Denied   被拒绝
                Toast.makeText(this,"权限被拒绝了",Toast.LENGTH_SHORT).show();
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

至此,这个功能算是可用了!!!但是,还不完美!!!必须稍微封装一下让自己用起来更方便嘛!那么接下来就带大家来一个更加完美的封装。

源码下载

你可能感兴趣的:(Android6.0权限问题,android,Android-6,运行时权限)