Those pitfalls I fall into…
Conditon
- 危险权限
- Android 版本 >= 6.0
- targetSdkVersion >= 23
如果项目的targetSdkVersion < 23, 在Android 6.0+的手机上,会默认给予所有在AndroidManifest.xml中申请的权限。
是不是觉得这样就完事大吉了?
如果用户在应用的权限页面手动收回权限,将会导致应用Crash.💔
稳妥的处理当然是遵循Google的权限申请机制。
API
为方便开发者实现权限管理,Google提供了4个API:
- checkSelfPermission( ) 判断权限是否具有某项权限
- requestPermissions( ) 申请权限
- onRequestPermissionsResult( ) 申请权限回调方法
- shouldShowRequestPermissionRationale( ) 是否要提示用户申请该权限的缘由
Pitfall
如果用户任性的勾选了“不再询问”,那么在执行requestPermissions( )后,onRequestPermissionsResult( )会永远返回PERMISSION_DENIED,这样应用原本的操作将永远无法执行。
Right way
shouldShowRequestPermissionRationale( )
如果返回为true,一般情况下,应用应该弹出Dialog说明申请该权限的缘由
shouldShowRequestPermissionRationale( )只会在一种情况下返回true
用户上一次拒绝申请权限,但是并未勾选“不再询问”
如何判断用户勾选了“不再询问”?
从上面的表格可以看出,如果上次shouldShowRequestPermissionRationale( )返回了true,而这次调用该方法返回了false,则说明用户在上次勾选了“不再询问”。此时,我们需要引导用户进入设置界面进行权限授予。
由于涉及到上一次调用shouldShowRequestPermissionRationale( )的结果,所以需要将其持久化保存,SharedPreferences或者数据库均可。
|
|
流程图
Best Practice
Process Step
上面的解决方案是可行的,但是每次申请权限需要依赖于上一次调用shouldShowRequestPermissionRationale( )方法的返回值,如果SharedPreferences被修改或者被删除,会影响正常的申请流程。
Google提供了一个非常好的思路,详见EasyPermissions .
EasyPermissions并没有存储上一次shouldShowRequestPermissionRationale( )的返回值,而是在申请权限被拒后调用shouldShowRequestPermissionRationale( )方法,如果此时返回false则说明用户勾选了“不再询问”。
简化判断“不再询问”的条件
1.未获得授权
2.shouldShowRequestPermissionRationale( )返回false
Reference
[]Android M 权限最佳实践
[2]android permission权限与安全机制解析(上)
[3]android permission权限与安全机制解析(下)
[4]第三方库PermissionsDispatcher
[5]EasyPermissions
[6]Android权限最佳实践
[7]Android如何获取判断是否有悬浮窗权限
Android悬浮窗实现 使用WindowManager
突破小米悬浮窗权限控制 – 不需要权限的悬浮窗
Android无需权限显示悬浮窗, 兼谈逆向分析app