跟Google学写代码:Android运行时权限处理
系统权限
权限机制是Android提供的一种安全机制,每个App就好比一个封装好的盒子,每个盒子之间是封闭的不能直接互相访问,当我们开发的App想访问其他App的数据时,就需要申请一些权限,开发者可以在Mainfest文件中获得一些普通权限,在更高级别的Android版本中,比如Android6.0 ,就必须征求用户的决定来获取一些“危险”权限。
声明权限
每个Android App都可以在Manifest文件中声明开发者所需要的权限,例如,读取用户人信息,发送短信,打电话等
下面集合了一些普通的权限:
- 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
看起来有点晕,不过没关系,这里只是一个笔记,以后忘记的时候可以来这里查询
重点关注“危险”权限
Dangerous Permission Group | 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 |
Google 在发布Android 6.0版本的时候,增加运行时权限的概念,把“危险”的权限放在App运行的时候,提示用户去选择是否给予App指定的权限,意味着只有用户同意了,我们的App才能够获得该权限,并且,即时我们在Manifest文件声明那些危险的权限,Android系统也不会给予我们访问那些资源的能力(毕竟我们申请权限,是为了访问其他App中的资源)
那么问题来了,我们该如何做?
很简单,三部曲
检查App是否拥有某一项权限
如果没有,提示用户去选择
2.1 如果用户选择是,那么App就会拥有改权限,继续完成后面的业务逻辑
2.2 如果用户选择其他,那么App本次将不会获得该权限,那么后续的操作将不会被执行处理用户选择的结果
Google也提供了三部曲的标准实现:
Check For Permissions
通过ContextCompat类的checkSelfPermission接口获得一个返回值
```// thisActivity 指的是当前activityint permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);```
- 如果拥有权限,则返回PackageManager.PERMISSION_GRANTED,
- 反之如果没有,返回PERMISSION_DENIED
有这两个值有什么用呢?当然是根据返回值判断 当前App是否拥有该权限,来决定我们下一步操作如何进行:是,进行相关业务逻辑,处理联系人,读写数据,打开相机等;否,提示用户App没有相关权限,当前不做任何操作
Request Permissions
Android在ActivityCompat类中提供了shouldShowRequestPermissionRationale()和requestPermissions()接口,通过它来弹出一个dialog提示用户选择是否给予权限
比如这样:
直接上代码:
// Here, thisActivity is the current activityif (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { //以此判断我们是否需要向用户解释(解释当前App需要通过用户选择是或者否来获得一些权限) if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_CONTACTS)) { //我们可以通过Toast或者其他方式通知用户,让用户明白只有选择是的情况下,我们的App才能获得某些权限,正常执行下去;这里的解释说明,让用户下一次请求当前权限的时候可以做出合适的选择。 } else { //不提示用户,那么我们可以通过requestPermissions()直接请求权限w ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS); // MY_PERMISSIONS_REQUEST_READ_CONTACTS 是系统定义的变量,requestPermissions()可以回调请求的结果 }}
Handle the permissions request response
请求完毕权限,现在需要处理用户的决定,我们的应用是否拥有这个权限了呢?
答案是在activity的回调方法onRequestPermissionsResult()中,一旦在第二步操作中请求权限,就会回调这个方法
@Overridepublic void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // App已经获取该权限,我们可以进行下一步业务逻辑 } else { // permission 被拒绝,不能完成后续的业务操作, } return; } // 判断其他的权限请求结果 }}
开源库的应用
在研究知乎App源码的时候,看到知乎使用了开源框架 PermissionsDispatcher 来解决Android6.0权限的问题
好东西怎能不分享呢?
Download
在 project build.gradle
文件里:
buildscript { dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' }}
在r app module build.gradle
:
${latest.version}
is
apply plugin: 'android-apt'dependencies { compile 'com.github.hotchemi:permissionsdispatcher:${latest.version}' apt 'com.github.hotchemi:permissionsdispatcher-processor:${latest.version}'}
更多相关文章
- Android 2.2用户超过一半
- Android调用手机相机与手机图库选择用户头像
- Android记住用户
- 【Android教程】Android用户系统管理
- Android开发――记账App开发项目分享(一)之用户登录
- Android安卓系统提示应用程序未安装的解决方法
- Android 系列 6 图形用户界面 (GUI)