Android运行时权限的处理

前言

  Android运行时权限机制 是在 API 23(Android M) 中提出来的,今年已经发布了API 26、27(Android O),已经过去几个版本了,但是为什么我要写这个东西。首先,以前在开发的过程中,为了图方便,只是 简单的将build.gradle 中的 targetSdkVersion 设置为 22,所以基本上没有太多的和运行时权限打交道,但是随着这个人啊越来越老( ),觉得不应该躲避新的东西,而应该正视它,不然自己的技术永远都不会得到提高。所以最近打算将targetSdkVersion逐渐升上去,玩点新东西。

这是什么

  在 API 23 以前,如果用户在安装应用后,默认是同意了应用所需要的权限(但是Android厂商众多,也有很多手机会弹窗提示用户是否授予权限)。而运行时权限的加入,简化了应用的安装过程,因为用户在安装的过程中不需要授予权限,而在应用的运行过程中,可以选择是否授予应用相关的权限。举个简单的例子,用户可以为相机提供相机访问权限,但是不提供位置的访问权限。

权限分类

  系统权限分为两类:Normal PermissionDangerous Permission” ,前者 不会直接给用户的隐私带来风险 ,所以如果你的app在Manifest文件中列出了应用需要这些权限,系统会自动赋予该权限。后者 会赋予app访问用户隐私数据的权限,是有可能对用户隐私造成风险的 。所以如果你的app在Manifest文件中列出了这些权限,则这些 权限的授予是由用户决定的

如何使用

  接下来,我们就要开始来玩运行时权限了。

检测权限

  如果你的app需要 Dangerous Permission ,则每次执行需要这一权限操作的时候都应该检测自己是否具有该权限,因为用户始终可以自由的调用此权限。检测的方法有两种,但是源码是一样的,只是穿了个不同的外套而已。

1
2
3
4
5
6
7
8
int cameraPermissionState = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
cameraPermissionState = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
//判断权限是否授予
if (cameraPermissionState == PermissionChecker.PERMISSION_GRANTED) {
//...已经具有该权限,你可以做一些羞羞的事情了
} else {
//...没有权限,这个时候你需要获取该权限了
}

请求权限

  Android提供了多种权限请求方式,调用这些方法将会显示一个无法自定义的Android对话框。你可以调用 requestPermission() 方法来请求你所需要的权限。

1
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);

处理权限请求响应

  当用户响应权限弹窗的时候,系统将回调 onRequestPermissionsResult() 方法,告知用户的响应情况。所以我们必须重写这个方法,如下。

1
2
3
4
5
6
7
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults.length == 1 && grantResults[0] == PermissionChecker.PERMISSION_GRANTED) {
//...用户允许相机访问权限,你可以做一些羞羞的事情了
} else {
//...用户拒绝了相机访问权限
}
}

  注意,系统显示的权限弹窗是对于 权限组 而言的,它不会列出app需要的具体权限。比如,app想要READ_CONTACTS权限,系统会告诉用户app想要访问设备的联系人。同时,用户只需要为每个权限组授予一次权限,如果应用请求该权限组中的任何其他权限,系统将自动授予应用这些权限 。具体过程是你在 requestPermissions() 方法之后,系统会自动回调 onRequestPermissionsResult() 方法,并传入 PERMISSION_GRANTED

权限组

  你可能会询问权限组又是什么东西,是的,我也问过自己。所有的Dangerous Permission都属于权限组。

  1. 如果应用请求其清单中列出的危险权限,而应用目前在权限组中没有任何权限,则系统会向用户显示一个对话框,描述应用要访问的权限组。对话框不描述该组内的具体权限。例如,如果应用请求 READ_CONTACTS 权限,系统对话框只说明该应用需要访问设备的联系信息。如果用户批准,系统将向应用授予其请求的权限。
  2. 如果应用请求其清单中列出的危险权限,而应用在同一权限组中已有另一项危险权限,则系统会立即授予该权限,而无需与用户进行任何交互。例如,如果某应用已经请求并且被授予了 READ_CONTACTS 权限,然后它又请求 WRITE_CONTACTS,系统将立即授予该权限。

  任何权限都可属于一个权限组,包括正常权限和应用定义的权限。但权限组仅当权限危险时才影响用户体验。可以忽略正常权限的权限组。
任何权限都可属于一个权限组,包括正常权限和应用定义的权限。但权限组仅当权限危险时才影响用户体验。可以忽略正常权限的权限组。您可以查看官方文档

  我就知道你懒,给你截图了。如果你想看官方文档,就看看下面的图。
Dangerous Permission

告诉用户你为什么需要这个权限

  当用户选择单次拒绝权限的时候,你再次请求该权限,可以告知用户为什么你的app需要这些权限,以便让用户理解这些权限的作用。系统也提供了对应的方法 ActivityCompat.shouldShowRequestPermissionRationale() 。如果app之前请求过此权限,并且用户拒绝了请求这个方法就会返回true。如果app之前请求过此权限,并且用户勾选了”禁止后不再询问”,这个方法将返回false。

一次完整的权限请求

  动态权限的相关其实并没有多少,来看看一段完整的请求CAMERA权限的示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private void checkPermission(){
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PermissionChecker.PERMISSION_GRANTED) {
//...开始做羞羞的事情
} else {
requestCameraPermission();
}
}

private void requestCameraPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
new AlertDialog.Builder(this)
.setMessage("需要请求相机访问权限以便进行预览,拍摄")
.setPositiveButton("好的", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA);
}
})
.create()
.show();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
PERMISSION_REQUEST_CAMERA);
}
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CAMERA) {
if (grantResults.length == 1 && grantResults[0] == PermissionChecker.PERMISSION_GRANTED) {
//...又可以做羞羞的事情了
}
}
}

你该知道的

  1. 当系统要求用户授予权限时,用户可以选择指示系统不再要求提供该权限 。这种情况下,无论应用在什么时候使用 requestPermissions() 再次要求该权限,系统都会立即拒绝此请求。系统 会调用您的 onRequestPermissionsResult() 回调方法,并传递 PERMISSION_DENIED ,如果用户再次明确拒绝了您的请求,系统将采用相同方式操作。
  2. 要活用 shouldShowRequestPermissionRationale() 方法。这个方法是在用户拒绝过某个权限的请求(但不是禁止后不再询问)后会返回true,然后你可以在这个方法中做一些对该权限的解释,以便用户更了解为什么需要授予该权限。

本文标题:Android运行时权限的处理

文章作者:严方雄

发布时间:2017-12-14

最后更新:2018-09-13

原始链接:http://yanfangxiong.com/2017/12/14/Android运行时权限的处理/

0%