AndroidM权限机制

前言

android6.0引入了全新的权限系统,以往开发者需要权限只用在清单文件AndroidManifest.xml中进行声明,但现在不同了,特殊的权限除了需要在清单文件进行声明外,还需要在代码中向使用者进行请求授权的操作。


Permission分类

Android将系统权限分成了四个保护等级normal,dangerous,signature,signatureOrSystem,其中最常见的是normal permission和dangerous permission两类。

  • normal permissions

    normal permission涵盖的一系列权限的共同点是:App需要访问App运行沙盒以外的数据或资源,但是这些资源对用户的隐私或其他App的危险性较小,下面列举一下这些权限:
    INTERNET
    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
    FLASHLIGHT
    GET_PACKAGE_SIZE
    KILL_BACKGROUND_PROCESSES
    MODIFY_AUDIO_SETTINGS
    NFC
    READ_SYNC_SETTINGS
    READ_SYNC_STATS
    RECEIVE_BOOT_COMPLETED
    REORDER_TASKS
    REQUEST_INSTALL_PACKAGES
    SET_TIME_ZONE
    SET_WALLPAPER
    SET_WALLPAPER_HINTS
    TRANSMIT_IR
    USE_FINGERPRINT
    VIBRATE
    WAKE_LOCK
    WRITE_SYNC_SETTINGS
    SET_ALARM
    INSTALL_SHORTCUT

以上这些就是Android 6.0中所有的normal permissions了。

  • dangerous permissions

    dangerous的权限需要应用明确的请求用户授权,常见的dangerous permissions如下:
权限组 权限
CALENDAR READ_CALENDAR,WRITE_CALENDAR
CAMERA CAMERA
CONTACTS READ_CONTACTS,WRITE_CONTACTS,GET_ACCOUNTS
LOCATION ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION
MICROPHONE RECORD_AUDIO
PHONE READ_PHONE_STATE,CALL_PHONE,READ_CALL_LOG,WRITE_CALL_LOG,ADD_VOICEMAIL,USE_SIP,PROCESS_OUTGOING_CALLS
SENSORS BODY_SENSORS
SMS SEND_SMS,RECEIVE_SMS,READ_SMS,RECEIVE_WAP_PUSH,RECEIVE_MMS
STORAGE READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE

以上这些权限就是Android6.0中所有的dangerous permissions。

实战

  • 单个权限的申请

    下面我们以STORAGE的WRITE_EXTERNAL_STORAGE为例,申请权限,此权限具有代表性,当申请READ_EXTERNAL_STORAGE或是WRITE_EXTERNAL_STORAGE时,另一权限会被默认赋予,当然,一定要记得在AndroidManifest.xml中声明权限,不然会无法获取

    1.在AndroidManifest.xml中添加权限声明

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

    2.在MainActivity中添加以下代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //判断当前版本是否大于M
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    //判断当前Activity是否获得了该权限
    if (ContextCompat.checkSelfPermission(this,
    Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    //没有授权,判断权限申请是否曾经被拒绝过
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
    //拒绝过
    Toast.makeText(MainActivity.this, "你曾经拒绝过此权限", Toast.LENGTH_SHORT).show();
    } else {
    //没有拒绝过,当然还是要获取
    }
    //进行权限请求
    ActivityCompat.requestPermissions(this,
    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
    EXTERNAL_STORAGE_REQ_CODE);
    }
    }

    当进行权限申请,并且用户做出选择后会回调onRequestPermissionsResult这个方法,在这个方法中做相关处理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
    case EXTERNAL_STORAGE_REQ_CODE:
    // 如果请求被拒绝,那么通常grantResults数组为空
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults.length > 0) {
    //申请成功
    Toast.makeText(MainActivity.this, "申请成功", Toast.LENGTH_SHORT).show();
    } else {
    //申请失败,可以在这里做用户不授予权限的操作
    }
    break;
    }
    }
    • 多个权限的申请

方法类似,有空再填坑

demo: https://github.com/liompei/PermissionDemo