您的位置:首页 > 移动开发 > Android开发

Android 6.0运行时权限申请和一些坑

2017-12-27 20:11 363 查看

1.概述

大家知道在Android6.0(Api23)之前,用户权限的申请都是在AndroidManifest.xml 声明的,而在6.0之后,对某些涉及到用户隐私的权限可在运行时根据用户的需要动态授予。如果你的应用设置targetSdkVersion=>23,你不仅要在Mainifest正常申请外,还需要在运行时动态请求用户授权,否则可能会直接导致应用Crash。(为什么是可能?因为很多手机厂商对自己的手机底层系统做过修改,他们定制了一套自己的权限管理系统,这样的好处是我们的应用不会因为权限问题而直接崩溃,但也带了Android一直以来的痛点 适配问题)。

2.事例解析

权限管理主要涉及三个核心的Api,一般的申请流程分为三步走(注意这里讲得是一般通用情况,适用大部机型),为了方便讲解这里以读取联系人信息为例:

1.检查是否有权限

//检查用户是否有读取联系人权限
private void checkSelfPermission() {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.READ_CONTACTS) ==PackageManager.PERMISSION_GRANTED ) {
//有权限,直接做自己想做得,比如打开联系人列表

} else {
//无权限,这时需要去动态申请
requestContactsPermission();
}
}


第一个核心方法:ActivityCompat.checkSelfPermission(Context context,String permission);这个方法是检查用户是否拥有权限。若拥有该权限该方法返回0,无权限则不为0。在6.0及以上的设备,第一次安装时默认是没有该权限的,这就需要用户去动态授权。这里就需要用到第二个核心方法。

2.是否需要向用户弹框申请权限

//判断是否需要
private void requestContactsPermission() {

if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CONTACTS)) {
//申请权限,向用户弹出一个系统的权限申请对话框
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);
} else {
//用户拒绝过该权限,且点了不再提示。此时即使再发起权限申请也不会弹出申请对话框,这时我们需要提示用户
//发生了什么,并引导用户去权限管理页面手动打开。这里我只是简单的Toast提示用户无该权限
displayToast(getString(R.string.permission_contacts_granted_fail));
}

}


第二个核心方法:ActivityCompat.shouldShowRequestPermissionRationale(Context context,String permission);该方法用来检测是否需要向用户弹出系统权限申请框。应用在第一次安装时该方法会返回true,此时即可调用ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1),发起权限申请。

一般此时会弹一个系统对话框,有三个选项,允许,拒绝和不再提示。

1.选择允许即用户同意了授予该权限,且下次不需要再重复申请了(效果等于同时勾选了不再提示选项)。

2.选择拒绝,但是未勾选不再提示。此时用户拒绝了权限,ActivityCompat.shouldShowRequestPermissionRationale(Context context,String permission)还是会返回true,即下次申请时还是可以弹出权限申请框供用户选择是否授予。

3..选择拒绝,同时未勾选不再提示。用户拒绝,下次再检查权限调用ActivityCompat.shouldShowRequestPermissionRationale(Context context,String permission)就会返回false,此时即使继续调用 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);也不会在弹框。这里需要我们自己提示用户去权限管理界面手动打开。

注意:有的手机只有同意和拒绝选项没有不再提示。此时点击拒绝,效果同3.

3.申请结果回调

//申请结果回调
@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull String[] permissions,@NonNull int[] grantResults) {
if (requestCode == 1) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//授权成功,可以继续接下来的事情了
displayToast(getString(R.string.permission_contacts_granted_success));
} else {
//授权失败提示
displayToast(getString(R.string.permission_contacts_granted_fail));
}
}
}


第三个核心方法:方法很简单,就是对授权结果的回调, 没什么需要过多解读的。

以上三个步骤就是权限申请的一般步骤,适用于大部分的机型。

但是需要注意的是由于一些手机厂商对于自己系统的独特定制,以上方法在某些手机上会有问题,(条件所限目前发现的有小米Note和魅族Note5);

小米手机:在第一次安装后ActivityCompat.shouldShowRequestPermissionRationale(Context context,String permission)就会返回false;在设置页面不管选择拒绝还是询问都不会弹授权框,默认就是拒绝状态。当只有勾选允许时,才能授权成功。也就是说小米有一套自己的权限管理系统,无法在运行时进行动态授权。只有用户在安全中心手动设置。这样我们只能通过方法1判断是否有权限,没有的话就直接提示用户去手动开启。网上有人反映checkSelfPermission一直返回0(允许状态),我的做法是在进入通讯录之后如果不能拿到联系人信息就再次提示用户没有授予该权限。

魅族手机:checkSelfPermission一直返回0,做法同小米,没有拿到数据就提示用户可能未开启权限。其它权限问题也可类似处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: