文章来源:http://blog.csdn.net/zhuwentao2150/article/details/53449711
Android6.0的SDK,对权限的申请机制发生了一些变化。
在Android6.0之前,用户安装APP时就要为其授予对应的权限,不然程序就无法安装,而6.0之后,我们可以直接安装,并可对应用的权限进行管理,这样极大的保护了用户的隐私,但也给我们开发人员造成了些小麻烦(测试人员经常提单反映说某个功能未实现,其实是把权限关闭造成的)
可以看看Google官方文档,申请权限的最佳做法:https://developer.android.com/training/permissions/best-practices.html#perms-vs-intents
一、权限分类
Google将应用的权限分为两类
- Normal Permissions:不需要用户授予,可直接申请,如访问网络、手机传感器等权限,此类权限一般不涉及用户隐私。
- Dangerous Permission:需要用户授予,需要动态申请,如拨打电话、访问SD卡、获取地理位置等权限,此类权限一般都涉及到了用户隐私。
Normal Permissions列表
- 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
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 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
- 27
- 28
- 29
- 30
- 31
- 32
- 33
Dangerous Permission列表
- 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
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 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
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
可以发现,Dangerous Permission中,所有危险的 Android 系统权限都是一个个权限组,当我们在申请一组权限中的其中一个权限时,会对应申请整个权限组,具体可以查看Google的官方文档,描述的很详细:
https://developer.android.com/guide/topics/security/permissions.html#defining
二、申请步骤
请求权限的步骤,为了兼容性,建议使用SDK 23版本或以上的v4包,这里介绍的是v4包中的API
1、checkSelfPermission(Context context, String permission):
检查用户是否允许该权限,有则返回0,无则返回-1,该方法在API 23版本才提供,为了兼容性低版本,建议使用v4包中ContextCompat
类提供的checkSelfPermission()
方法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2、requestPermissions(Activity activity, String[] permissions, int requestCode):
申请权限,会弹出一个系统对话框向用户申请权限,String[] permissions
传入一个或一组权限,int requestCode
为请求码,用于在回调监听中标识权限申请的结果。
- 1
- 1
3、onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults):
监听权限请求的结果,int requestCode
对应requestPermissions()
方法中的requestCode
请求码,int[] grantResults
表示对应权限申请的结果,成功返回0,失败返回-1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
4、shouldShowRequestPermissionRationale(Activity activity, String permission):
申请权限的解释,该方法只在大于等于6.0的版本起作用,在6.0前的版本只返回false,它的返回结果有以下几种情况
- 当申请对应权限时被用户拒绝了一次,再次申请对应权限时该方法就会返回true
- 如果用户在第二次时选择了“不再提醒”,则再次请求权限时该方法只会返回false
- 用户在手机权限管理中设置为“禁止”,则该方法返回false
- 1
- 2
- 3
- 1
- 2
- 3
三、常见问题:
1、onRequestPermissionsResult回调失效:
不管权限申请结果成功还是失败,都没有回调onRequestPermissionsResult()方法
需要明白以下几点,这个问题就好解决了:
-
如果你在一个Fragment页面调用
requestPermissions()
方法,那么当前Fragment页面的onRequestPermissionsResult()
就会被回调。 -
如果你是通过
ActivityCompat.requestPermissions()
方法调用的,那么Activity页面的onRequestPermissionsResult()
就会被回调。
所以,一般出现onRequestPermissionsResult()
没有被回调的情况,很可能是由于在Fragment页面中使用ActivityCompat.requestPermissions()
方法请求权限造成的,如果要在Fragment中申请权限,应该使用当前Fragment页面本身来申请。
StackOverFlow里也有相关的解答:
http://stackoverflow.com/questions/33169455/onrequestpermissionsresult-not-being-called-in-dialog-fragment
2、checkSelfPermission返回始终为PackageManager.PERMISSION_GRANTED:
把应用运行在6.0系统时,不管用户是否拒绝了这个权限,checkSelfPermission返回的结果一直是PackageManager.PERMISSION_GRANTED。
如果碰到了这样的问题,需要检查你的App目标SDK是否是23以下,也就是targetSdkVersion < 23的时候,但APP却运行在6.0以上的机器时,就会出现这样的情况,对于targetSdkVersion < 23的应用,在6.0的机器运行时,我们需要使用PermissionChecker
类中的checkSelfPermission()
方法,才能正常获取,所以我们在检查用户是否授予权限时,需要进行两套处理。
解决方法:
检查应用的targetSdkVersion是否小于23的方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
使用以下方法检查是否有权限:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
通过自定义的checkHavePermissions()
方法,即可解决checkSelfPermission()
返回失效的问题,用户授予了权限时返回true,未授予时返回false。