首页 > 代码库 > 关于Android6.0权限的学习

关于Android6.0权限的学习

一,序言

从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予。此方法可以简化应用安装过程,因为用户在安装或更新应用时不需要授予权限。它还让用户可以对应用的功能进行更多控制;例如,用户可以选择为相机应用提供相机访问权限,而不提供设备位置的访问权限。

二、权限的分类

系统权限分为两类:正常权限和危险权限:

1、正常权限:涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域。

例如,设置时区的权限就是正常权限。如果应用声明其需要正常权限,系统会自动向应用授予该权限。

技术分享
 1 ACCESS_LOCATION_EXTRA_COMMANDS
 2 ACCESS_NETWORK_STATE
 3 ACCESS_NOTIFICATION_POLICY
 4 ACCESS_WIFI_STATE
 5 BLUETOOTH
 6 BLUETOOTH_ADMIN
 7 BROADCAST_STICKY
 8 CHANGE_NETWORK_STATE
 9 CHANGE_WIFI_MULTICAST_STATE
10 CHANGE_WIFI_STATE
11 DISABLE_KEYGUARD
12 EXPAND_STATUS_BAR
13 GET_PACKAGE_SIZE
14 INSTALL_SHORTCUT
15 INTERNET
16 KILL_BACKGROUND_PROCESSES
17 MODIFY_AUDIO_SETTINGS
18 NFC
19 READ_SYNC_SETTINGS
20 READ_SYNC_STATS
21 RECEIVE_BOOT_COMPLETED
22 REORDER_TASKS
23 REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
24 REQUEST_INSTALL_PACKAGES
25 SET_ALARM
26 SET_TIME_ZONE
27 SET_WALLPAPER
28 SET_WALLPAPER_HINTS
29 TRANSMIT_IR
30 UNINSTALL_SHORTCUT
31 USE_FINGERPRINT
32 VIBRATE
33 WAKE_LOCK
34 WRITE_SYNC_SETTINGS
正常权限

2、危险权限:涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域。

例如,能够读取用户的联系人属于危险权限。如果应用声明其需要危险权限,则用户必须明确向应用授予该权限。

3、权限组

所有危险的 Android 系统权限都属于权限组。

I、如果应用请求其清单中列出的危险权限,而应用目前在权限组中没有任何权限,则系统会向用户显示一个对话框,描述应用要访问的权限组。对话框不描述该组内的具体权限。例如,如果应用请求 READ_CONTACTS 权限,系统对话框只说明该应用需要访问设备的联系信息。如果用户批准,系统将向应用授予其请求的权限。

II、如果应用请求其清单中列出的危险权限,而应用在同一权限组中已有另一项危险权限,则系统会立即授予该权限,而无需与用户进行任何交互。例如,如果某应用已经请求并且被授予了 READ_CONTACTS 权限,然后它又请求 WRITE_CONTACTS,系统将立即授予该权限。

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

技术分享
 1 group:android.permission-group.CONTACTS
 2     permission:android.permission.WRITE_CONTACTS
 3     permission:android.permission.GET_ACCOUNTS    
 4     permission:android.permission.READ_CONTACTS
 5 
 6   group:android.permission-group.PHONE
 7     permission:android.permission.READ_CALL_LOG
 8     permission:android.permission.READ_PHONE_STATE 
 9     permission:android.permission.CALL_PHONE
10     permission:android.permission.WRITE_CALL_LOG
11     permission:android.permission.USE_SIP
12     permission:android.permission.PROCESS_OUTGOING_CALLS
13     permission:com.android.voicemail.permission.ADD_VOICEMAIL
14 
15   group:android.permission-group.CALENDAR
16     permission:android.permission.READ_CALENDAR
17     permission:android.permission.WRITE_CALENDAR
18 
19   group:android.permission-group.CAMERA
20     permission:android.permission.CAMERA
21 
22   group:android.permission-group.SENSORS
23     permission:android.permission.BODY_SENSORS
24 
25   group:android.permission-group.LOCATION
26     permission:android.permission.ACCESS_FINE_LOCATION
27     permission:android.permission.ACCESS_COARSE_LOCATION
28 
29   group:android.permission-group.STORAGE
30     permission:android.permission.READ_EXTERNAL_STORAGE
31     permission:android.permission.WRITE_EXTERNAL_STORAGE
32 
33   group:android.permission-group.MICROPHONE
34     permission:android.permission.RECORD_AUDIO
35 
36   group:android.permission-group.SMS
37     permission:android.permission.READ_SMS
38     permission:android.permission.RECEIVE_WAP_PUSH
39     permission:android.permission.RECEIVE_MMS
40     permission:android.permission.RECEIVE_SMS
41     permission:android.permission.SEND_SMS
42     permission:android.permission.READ_CELL_BROADCASTS
权限组

四、检查权限

如果您的应用需要危险权限,则每次执行需要这一权限的操作时您都必须检查自己是否具有该权限。用户始终可以自由调用此权限,因此,即使应用昨天使用了相机,它不能假设自己今天仍具有该权限。

要检查您是否具有某项权限,请调用 ContextCompat.checkSelfPermission() 方法。例如,以下代码段显示了如何检查 Activity 是否具有在日历中进行写入的权限:

int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.WRITE_CALENDAR);

如果应用具有此权限,方法将返回 PackageManager.PERMISSION_GRANTED,并且应用可以继续操作。

如果应用不具有此权限,方法将返回 PERMISSION_DENIED,且应用必须明确向用户要求权限。

五、解释为什么需要权限

例如,如果用户启动一个摄影应用,用户对应用要求使用相机的权限可能不会感到吃惊,但用户可能无法理解为什么此应用想要访问用户的位置或联系人。在请求权限之前,不妨为用户提供一个解释。

为了帮助查找用户可能需要解释的情形,Android 提供了一个实用程序方法,即 shouldShowRequestPermissionRationale()。如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。

注:如果用户在过去拒绝了权限请求,并在权限请求系统对话框中选择了 Don‘t ask again 选项,此方法将返回 false。

如果设备规范禁止应用具有该权限,此方法也会返回 false。

六、请求权限

如果应用尚无所需的权限,则应用必须调用一个 requestPermissions() 方法,以请求适当的权限。应用将传递其所需的权限,以及您指定用于识别此权限请求的整型请求代码。此方法异步运行:它会立即返回,并且在用户响应对话框之后,系统会使用结果调用应用的回调方法,将应用传递的相同请求代码传递到 requestPermissions()。

以下代码可以检查应用是否具备读取用户联系人的权限,并根据需要请求该权限:

if (ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {//显示为啥需要权限的理由

    } else {//不需要解释,直接请求
        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);
    }
}

七、处理权限请求的响应

当应用请求权限时,系统将向用户显示一个对话框。当用户响应时,系统将调用应用的 onRequestPermissionsResult() 方法,向其传递用户响应。您的应用必须替换该方法,以了解是否已获得相应权限。回调会将您传递的相同请求代码传递给 requestPermissions()。例如,如果应用请求 READ_CONTACTS 访问权限,则它可能采用以下回调方法:

@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {//授权成功
            } else {//授权被拒
            }
            return;
        }
    }
}

 

关于Android6.0权限的学习