前言

拖了这么久,app逐渐接入android 新 api,这篇介绍 android M 运行时权限获取方面的知识。此文 展示一个权限申请的大致流程,不做细节深入讲解

官方介绍

Working with System Permissions

Permissions Best Practices

android M 指的就是 android 6.0 ,compileSdkVersion >= 23 采有运行时权限这一说。

permissions 时序图

android M 运行时权限申请流程_第1张图片

弹出权限—>允许 ,弹出权限—>拒绝,弹出权限(带说明文字)—>允许/拒绝,弹出权限—>不再提醒。

android M 运行时权限申请流程_第2张图片
android M 运行时权限申请流程_第3张图片

2.google 官网对用户权限分为两类,普通权限,用户隐私权限。

只要在清单文件中生命既可(普通权限)

 ACCESS_LOCATION_EXTRA_COMMANDSACCESS_NETWORK_STATEACCESS_NOTIFICATION_POLICYACCESS_WIFI_STATEBLUETOOTHBLUETOOTH_ADMINBROADCAST_STICKYCHANGE_NETWORK_STATECHANGE_WIFI_MULTICAST_STATECHANGE_WIFI_STATEDISABLE_KEYGUARDEXPAND_STATUS_BARGET_PACKAGE_SIZEINSTALL_SHORTCUTINTERNETKILL_BACKGROUND_PROCESSESMODIFY_AUDIO_SETTINGSNFCREAD_SYNC_SETTINGSREAD_SYNC_STATSRECEIVE_BOOT_COMPLETEDREORDER_TASKSREQUEST_IGNORE_BATTERY_OPTIMIZATIONSREQUEST_INSTALL_PACKAGESSET_ALARMSET_TIME_ZONESET_WALLPAPERSET_WALLPAPER_HINTSTRANSMIT_IRUNINSTALL_SHORTCUTUSE_FINGERPRINTVIBRATEWAKE_LOCKWRITE_SYNC_SETTINGS

需要运行时申请的权限

CALENDAR(日历)     READ_CALENDAR    WRITE_CALENDARCAMERA(相机)     CAMERACONTACTS(联系人)     READ_CONTACTS    WRITE_CONTACTS    GET_ACCOUNTSLOCATION(位置)     ACCESS_FINE_LOCATION    ACCESS_COARSE_LOCATIONMICROPHONE(麦克风)     RECORD_AUDIOPHONE(手机)     READ_PHONE_STATE    CALL_PHONE    READ_CALL_LOG    WRITE_CALL_LOG    ADD_VOICEMAIL    USE_SIPPROCESS_OUTGOING_CALLSSENSORS(传感器)     BODY_SENSORSSMS(短信)     SEND_SMS    RECEIVE_SMS    READ_SMS    RECEIVE_WAP_PUSH    RECEIVE_MMSSTORAGE(存储卡)     READ_EXTERNAL_STORAGE    WRITE_EXTERNAL_STORAGE

下面成组出现,你要做的就是选择申请权限时候的策略。是单个权限申请,还是一组申请。注意这里单个权限和组形式的不同。如果以组为单位进行批量权限请求,只要组中一个权限已经授权,其他权限自动获取授权信息,无需经过用户同意。

ok有了上面的权限组,就是开干了。

下面是几个运行时权限申请用到的几个系统api 介绍

几个重要的方法与常量解释

PackageManager中的两个常量:

PackageManager.PERMISSION_DENIED:该权限是被拒绝的。
PackageManager.PERMISSION_GRANTED:该权限是被授权的。
Activity中或者Fragment都会有以下几个方法:

int checkSelfPermission(String)void requestPermissions(int, String...)boolean shouldShowRequestPermissionRationale(String)void onRequestPermissionsResult()

上述四个方法中,前三个方法在support-v4的ActivityCompat中都有,建议使用兼容库中的方法。最后一个方法是用户授权或者拒绝某个权限组时系统会回调Activity或者Fragment中的方法。

checkSelfPermission() 检查权限

检查某一个权限的当前状态,你应该在请求某个权限时检查这个权限是否已经被用户授权,已经授权的权限重复申请可能会让用户产生厌烦。
该方法有一个参数是权限名称,有一个int的返回值,用这个值与上面提到的两个常量做比较可判断检查的权限当前的状态。
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// 没有权限,申请权限。
}else{
// 有权限了,去放肆吧。
}

requestPermissions() 申请权限

请求用户授权几个权限,调用后系统会显示一个请求用户授权的提示对话框,App不能配置和修改这个对话框,如果需要提示用户这个权限相关的信息或说明,需要在调用 requestPermissions() 之前处理,该方法有两个参数:
int requestCode,会在回调onRequestPermissionsResult()时返回,用来判断是哪个授权申请的回调。
String[] permissions,权限数组,你需要申请的的权限的数组。
由于该方法是异步的,所以无返回值,当用户处理完授权操作时,会回调Activity或者Fragment的onRequestPermissionsResult()方法。
对于Activity我们直接调用requestPermissions(int, String[])即可,不过这个方法是在api leve 23以上,所以我们为了适配可以是使用兼容包提供的方法:

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

对于support包的Fragment就可以直接调用requestPermissions(int, String[]),对于app包的Fragment就需要做版本判断了,这样就显得比较麻烦。

onRequestPermissionsResult() 处理权限结果回调

该方法在Activity/Fragment中应该被重写,当用户处理完授权操作时,系统会自动回调该方法,该方法有三个参数:
int requestCode,在调用requestPermissions()时的第一个参数。
String[] permissions,权限数组,在调用requestPermissions()时的第二个参数。
int[] grantResults,授权结果数组,对应permissions,具体值和上方提到的PackageManager中的两个常量做比较。

@Overridepublic void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {    switch (requestCode) {        case MMM: {            if (grantResults.length > 0                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                // 权限被用户同意,可以去放肆了。            } else {                // 权限被用户拒绝了,洗洗睡吧。            }            return;        }    }}shouldShowRequestPermissionRationale()

望文生义,是否应该显示请求权限的说明。
第一次请求权限时,用户拒绝了,调用shouldShowRequestPermissionRationale()后返回true,应该显示一些为什么需要这个权限的说明。
用户在第一次拒绝某个权限后,下次再次申请时,授权的dialog中将会出现“不再提醒”选项,一旦选中勾选了,那么下次申请将不会提示用户。
第二次请求权限时,用户拒绝了,并选择了“不再提醒”的选项,调用shouldShowRequestPermissionRationale()后返回false。
设备的策略禁止当前应用获取这个权限的授权:shouldShowRequestPermissionRationale()返回false 。
加这个提醒的好处在于,用户拒绝过一次权限后我们再次申请时可以提醒该权限的重要性,免得再次申请时用户勾选“不再提醒”并决绝,导致下次申请权限直接失败。
综上所述,整合代码后:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {    // 没有权限。    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)) {            // 用户拒绝过这个权限了,应该提示用户,为什么需要这个权限。    } else {        // 申请授权。        ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MMM);    }}

@Overridepublic void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {    switch (requestCode) {        case MMM: {            if (grantResults.length > 0                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                // 权限被用户同意,可以去放肆了。            } else {                // 权限被用户拒绝了,洗洗睡吧。            }            return;        }    }}

推荐几个封装好的权限工具类,区别只是封装方式上。

引用
rxPermissions https://github.com/tbruyelle/RxPermissions.
类似Rx方式,用到一些Rx方面知识。Rxbinding库等一些外部库

AndPermissions http://blog.csdn.net/yanzhenjie1003/article/details/52503533/
封装的较完善,只是注解方式走授权回调。效率会打折

Android 6.0 运行时权限处理完全解析 http://blog.csdn.net/lmj623565791/article/details/50709663 解决了反射调用效率问题,采用编译时注解。

更多相关文章

  1. Android为什么会有65536的方法数量限制
  2. Android Studio ——Android 使用Pull方法解析XML文件的方法
  3. 记录关于Gradle : Build Running的解决方法
  4. Android 开机震动的调用位置以及打开关闭方法
  5. Android中计算text文字大小的几个方法
  6. Android的DialogFragment的基本使用方法
  7. Android 6.0权限使用详解

随机推荐

  1. Android之底部導航欄--RadioGroup、TabHo
  2. 性能优化(9)-Android ANR在线监控原理
  3. [置顶] Android ListView高度自适应和Scr
  4. Android命令行/c语言/java设置获取系统属
  5. android 自定义menu菜单按键功能
  6. Android应用程序项目结构
  7. android源码下载备注
  8. Android TextWatcher三个回调详解,监听Edi
  9. Android实现在ServiceManager中加入自定
  10. Android Settings 声音设置