系统权限

权限机制是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中的资源)

那么问题来了,我们该如何做?

很简单,三部曲

  1. 检查App是否拥有某一项权限

  2. 如果没有,提示用户去选择
    2.1 如果用户选择是,那么App就会拥有改权限,继续完成后面的业务逻辑
    2.2 如果用户选择其他,那么App本次将不会获得该权限,那么后续的操作将不会被执行

  3. 处理用户选择的结果

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}'}

更多相关文章

  1. Android 2.2用户超过一半
  2. Android调用手机相机与手机图库选择用户头像
  3. Android记住用户
  4. 【Android教程】Android用户系统管理
  5. Android开发――记账App开发项目分享(一)之用户登录
  6. Android安卓系统提示应用程序未安装的解决方法
  7. Android 系列 6 图形用户界面 (GUI)

随机推荐

  1. 【DevOps进行时】基于iOS平台的集中构建
  2. 容器云平台No.4~kubernetes 服务暴露之In
  3. Linux系统安装
  4. 每天万次触发的持续交付工具链是这样炼成
  5. 容器云平台No.6~企业级分布式存储Ceph~v1
  6. 使用无服务器式的 Jenkins X:探索Prow,Jenk
  7. 特斯拉上海超级工厂监控遭“泄密”,究竟数
  8. DevOps 中高效测试基础架构的最佳实践
  9. 线性表之链式存储(二)
  10. 快又准! Facebook 研发效能提升方法实践