官网连接:

https://developer.android.google.cn/guide/topics/permissions/overview#normal-dangerous

 

从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予。 Android 6.0系统6.0以前,所有的权限,访问网络的权限,读取SD卡的权限,访问通讯录,拨打电话的权限都在安装的时候系统授予了要安装的应用。在系统运行的时候不需要对权限做任何的处理。用户在安装的时候一般都不知道这些权限用在了什么地方,这样做很不安全。一个应用很容易在一个Service中读取用户所有的通讯录信息发送到服务器上。Android 6.0后的动态权限让我们的系统更加安全,牺牲了用户的方便性,得到的是安全。下图是Android 6.0系统对相机权限的使用。

android update app权限 android6.0权限申请_xml

 

2. 正常权限 和 危险权限

Android系统权限分为几个保护级别。需要了解的两个最重要保护级别是 正常权限 和 危险权限:

(1)正常权限:

涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域。这些权限在应用安装时授予,运行时不再询问用户。例如: 网络访问、WIFI状态、音量设置等。

所有的普通权限: 

- ACCESS_LOCATION_EXTRA_COMMANDS 
 - ACCESS_NETWORK_STATE 
 - ACCESS_NOTIFICATION_POLICY 
 - ACCESS_WIFI_STATE 
 - BLUETOOTH 
 - BLUETOOTH_ADMIN 
 - BROADCAST_STICKY 
 - CHANGE_NETWORK_STATE 
 - CHANGE_WIFI_MULTICAST_STATE 
 - CHANGE_WIFI_STATE 
 - DISABLE_KEYGUARD 
 - EXPAND_STATUS_BAR 
 - GET_PACKAGE_SIZE 
 - INSTALL_SHORTCUT 
 - INTERNET 
 - KILL_BACKGROUND_PROCESSES 
 - MODIFY_AUDIO_SETTINGS 
 - NFC 
 - READ_SYNC_SETTINGS 
 - READ_SYNC_STATS 
 - RECEIVE_BOOT_COMPLETED 
 - REORDER_TASKS 
 - REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 
 - REQUEST_INSTALL_PACKAGES 
 - SET_ALARM 
 - SET_TIME_ZONE 
 - SET_WALLPAPER 
 - SET_WALLPAPER_HINTS 
 - TRANSMIT_IR 
 - UNINSTALL_SHORTCUT 
 - USE_FINGERPRINT 
 - VIBRATE 
 - WAKE_LOCK 
 - WRITE_SYNC_SETTINGS

(2)危险权限:

涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域。例如: 读取通讯录、读写存储器数据、获取用户位置等。如果应用声明需要这些危险权限,则必须在运行时明确告诉用户,让用户手动授予。

3. 权限组

Android系统对所有的危险权限进行了分组,称为 权限组 。属于同一组的危险权限将自动合并授予,用户授予应用某个权限组的权限,则应用将获得该权限组下的所有权限(前提是相关权限在 AndroidManifest.xml 中有声明)。

危险权限 和 权限组 列表如下:

android update app权限 android6.0权限申请_数据_02

 

二、Android 6.0+危险权限的动态处理

设备系统是 Android 6.0 (API 23) 或更高版本,并且应用的 targetSdkVersion 是 23 或更高版本,则针对在 AndroidManifest.xml 中声明的危险权限,在运行时还需要动态请求用户授权。

//申请权限

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if(this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
        // 申请一个(或多个)权限,并提供用于回调返回的获取码(用户定义)
        requestPermissions( new String[]{Manifest.permission.CALL_PHONE },CALL_REQUEST_CODE);
    }else{
        callPhone();
    }
}else{
    callPhone();
}

 

/**
 * 申请权限的回调
 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions,grantResults);

    switch(requestCode) {
        // requestCode即所声明的权限获取码,在checkSelfPermission时传入
        case CALL_REQUEST_CODE:

            if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // 获取到权限,作相应处理(调用定位SDK应当确保相关权限均被授权,否则可能引起定位失败)
                callPhone();
            } else{
                ShowToast.showToast(R.string.please_get_call_phone_permission,context);
            }
            break;


    }
}