Android权限管理

前言

农历腊月二十五,年味也愈加浓重了,在新年到来之前争取再多更新几篇博客。此文讲解安卓的权限管理,主要是针对Android 6.0新增加的动态权限获取的使用方法。

两种权限管理

什么是权限管理大家也一定都知道,想必不需要笔者多说了,笔者在此只提一下目前的两种权限管理机制:

  • 安装时权限管理:
    这是在安卓5.1及以下采用的方案,指的是安装应用完成时,应用可以获得系统权限
  • 运行时权限管理:
    安卓6.0之后增加了这种方案,使得应用可以在运行过程中动态地获取和释放系统权限
    安卓6.0动态权限获取

Manifest声明权限的使用

对于安卓5.1及以下的版本,不能采用运行时动态获取权限,所以只能够在Manifest中配置权限,这个大家一定都会使用,就不做过多讲解,贴上代码即可。

1
2
3
4
5
6
7
8
9
10
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.snazzyapp">


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


<application ...>
...
</application>

</manifest>

动态获取权限的使用

在讲解之前,先说明一下系统权限的分类。

系统权限分为常规权限和敏感权限:

  • 常规权限: 常规权限不涉及用户隐私,在Manifest中声明这些权限,系统默认许可
  • 敏感权限: 敏感权限会涉及到用户个人数据,这些权限的决定权则必须交付给用户

所以,这样一来,在安卓5.1及一下,只有用户在安装应用时同意了该应用需要的敏感权限,该应用才能被安装,否则直接退出安装; 在安卓6.0以上,应用可以在运行过程中获取权限,请求用户的许可,便于用户自由地选择可以许可的权限。

此文使用SupportLibrary来操作,以便略去判断系统版本的繁琐过程。

第一步: 检查权限状态

调用 ContextCompat.checkSelfPermission()方法,返回 PackageManager.PERMISSION_GRANTED说明已有权限, PERMISSION_DENIED说明权限失效。

1
2
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);

第二步: 请求权限

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
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {

// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {

// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.

} else {

// No explanation needed, we can request the permission.

ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);

// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}

第三步: 处理回应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults)
{

switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {

// permission was granted, yay! Do the
// contacts-related task you need to do.

} else {

// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}

// other 'case' lines to check for other
// permissions this app might request
}
}

注意: 当在Manifest中声明一系列权限后,仍然需要再次单独申请每个该权限。

权限使用的最佳实践

  1. 使用 Intent调用系统资源代替获取系统权限
  2. 每次请求权限时请求最少的权限
  3. 在合适的时机请求权限,尽量让用户明白为什么需要这些权限
  4. 测试应用的权限是否正常工作