前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android6.0运行时权限处理

Android6.0运行时权限处理

作者头像
用户1205080
发布2018-12-17 11:09:14
1.1K0
发布2018-12-17 11:09:14
举报
文章被收录于专栏:编码前线

概述

从Android6.0(API23)开始,用户可以在应用运行时向其授予权限,而不是在应用安装时授予。 在Android6.0以前,应用安装会给出应用声明的权限列表,用户如果要继续安装,就得接受全部的权限,让用户很无奈; 从Android6.0开始的运行时权限,让用户可以对应用的功能进行更多的控制,例如,用户可以选择为相机应用提供相机的访问权限,而不提供设备位置的访问权限。用户可以随时进入应用的“Settings”开关权限。

兼容性

  • 如果设备的系统版本是Android5.1或者更低的版本,或者应用的 targetSdkVersion为22或更低:如果您在清单中列出了危险权限,则用户必须在安装应用时授予此权限;如果用户不授予此权限,系统根本不会安装应用。
  • 如果设备的系统版本是Android6.0或者更高的版本,或者应用的 targetSdkVersion为23或更高:应用必须在清单中列出权限,并且它必须在运行时请求其需要的每项危险权限。用户可以授权或拒绝每项权限,且即使用户拒绝权限请求,应用仍可以继续运行有限的功能。

权限分类

系统权限分为两类:正常权限和危险权限

Normal Permissions

正常权限,不会直接给用户隐私权带来风险。如果您的应用在其清单列出了正常权限,系统将自动授予该权限。

  • ACCESSLOCATIONEXTRA_COMMANDS
  • ACCESSNETWORKSTATE
  • ACCESSNOTIFICATIONPOLICY
  • ACCESSWIFISTATE
  • BLUETOOTH
  • BLUETOOTH_ADMIN
  • BROADCAST_STICKY
  • CHANGENETWORKSTATE
  • CHANGEWIFIMULTICAST_STATE
  • CHANGEWIFISTATE
  • DISABLE_KEYGUARD
  • EXPANDSTATUSBAR
  • FOREGROUND_SERVICE
  • GETPACKAGESIZE
  • INSTALL_SHORTCUT
  • INTERNET
  • KILLBACKGROUNDPROCESSES
  • MANAGEOWNCALLS
  • MODIFYAUDIOSETTINGS
  • NFC
  • READSYNCSETTINGS
  • READSYNCSTATS
  • RECEIVEBOOTCOMPLETED
  • REORDER_TASKS
  • REQUESTCOMPANIONRUNINBACKGROUND
  • REQUESTCOMPANIONUSEDATAIN_BACKGROUND
  • REQUESTDELETEPACKAGES
  • REQUESTIGNOREBATTERY_OPTIMIZATIONS
  • SET_ALARM
  • SET_WALLPAPER
  • SETWALLPAPERHINTS
  • TRANSMIT_IR
  • USE_FINGERPRINT
  • VIBRATE
  • WAKE_LOCK
  • WRITESYNCSETTINGS
Dangerous Permissions

危险权限,会授予应用访问用户机密数据的权限。如果您的应用在清单中列出了危险权限,则用户必须明确批准您的应用使用这些权限。 危险权限是按权限组来划分,如果你申请某个危险的权限,假设你的app早已被用户授权了 同一组的某个危险权限,那么系统会立即授权,而不需要用户去点击授权。 例如,你的app对 READ_CONTACTS已经授权了,当你的app申请 WRITE_CONTACTS时,系统会直接授权通过。 NOTE:对应申请时弹出的Dialog上面的文本说明也是对整个权限组的说明,而不是单个权限。

权限组

权限

CALENDAR

READCALENDARWRITECALENDAR

CALL_LOG

READCALLLOGWRITECALLLOGPROCESSOUTGOINGCALLS

CAMERA

CAMERA

CONTACTS

READCONTACTSWRITECONTACTSGET_ACCOUNTS

LOCATION

ACCESSFINELOCATIONACESSCOARSELOCATION

MICROPHONE

RECORD_AUDIO

PHONE

READPHONESTATEREADPHONENUMBERSCALLPHONEADDVOICEMAILUSE_SIP

SENSORS

BODY_SENSORS

SMS

SENDSMSRECEIVESMSREADSMSRECEIVEWAPPUSHRECEIVEMMS

STORAGE

READEXTERNALSTORAGEWRITEEXTERNALSTORAGE

运行时权限处理

检查权限

如果你的应用需要危险权限,则每次执行需要这一权限的操作时都必须检查自己是否具有该权限。因为用户可以自由的开关此权限,所以,即使应用昨天使用了相机,它不能假设自己今天仍具有该权限。

ContextCompat.checkSelfPermission:用于检测某个权限是否已经被授予

代码语言:javascript
复制
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);

说明:如果应用具有此权限,方法将返回 PackageManager.PERMISSION_GRANTED,并且允许应用可以继续操作。如果应用不具有此权限,方法将返回 PackageManager.PERMISSION_DENIED,且应用必须明确向用户要求权限。

请求权限

如果应用尚无所需的权限,则应用必须调用 requestPermissions()方法,来请求适当的权限。

代码语言:javascript
复制
ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);

说明:从第二个参数可以看出,支持一次性请求多个权限,系统会通过对话框逐一询问用户是否授权。

处理权限请求响应

当应用请求权限时,系统将向用户显示一个对话框。当用户响应时,系统将调用应用的 onRequestPermissionsResult()方法。

代码语言:javascript
复制
@Override
public 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) {
                // permission was granted, yay! Do the
                // contacts-related task you need to do.
            } else {
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }
        // other 'case' lines to check for other
        // permissions this app might request
    }
}
解释权限的用途

如果用户继续尝试使用需要某项权限的功能,但拒绝权限请求,则可能表明用户不理解应用为什么需要此权限才能提供相关的功能,这时就可以显示解释给用户。 shouldShowRequestPermissionRationale(): 如果应用之前请求过此权限但用户拒绝了请求,此方法返回 true; 如果用户过去拒绝了权限请求,并在权限请求系统对话框选择了 Don't ask again选项,此方法返回 false

代码语言:javascript
复制
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_CONTACTS)) {
        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.
    } else {
        // No explanation needed, we can request the permission.
        ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);
        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

AndPermission的使用

AndPermission是严格按照 Android系统的 运行时权限设计的,并最大限度上兼容了国产手机。 库地址:https://github.com/yanzhenjie/AndPermission

导入
代码语言:javascript
复制
implementation 'com.yanzhenjie:permission:2.0.0-rc12'
使用
申请权限
代码语言:javascript
复制
AndPermission.with(this)
  .runtime()
  .permission(Permission.Group.STORAGE)
  .onGranted(permissions -> {
    // Storage permission are allowed.
  })
  .onDenied(permissions -> {
    // Storage permission are not allowed.
  })
  .start();
权限被拒绝,说明权限用途
代码语言:javascript
复制
private Rationale mRationale = new Rationale() {
    @Override
    public void showRationale(Context context, List<String> permissions, 
            RequestExecutor executor) {
        // 这里使用一个Dialog询问用户是否继续授权。
        // 如果用户继续:
        executor.execute();
        // 如果用户中断:
        executor.cancel();
    }
};
AndPermission.with(this)
    .runtime()
    .permission(Permission.WRITE_EXTERNAL_STORAGE)
    .rationale(mRationale)
    .onGranted(...)
    .onDenied(...)
    .start();
权限总是被拒绝,前往设置页授权
代码语言:javascript
复制
AndPermission.with(this)
    .runtime()
    .permission(...)
    .rationale(...)
    .onGranted(...)
    .onDenied(new Action() {
        @Override
        public void onAction(List<String> permissions) {
            if (AndPermission.hasAlwaysDeniedPermission(context, permissions)) {
                // 这些权限被用户总是拒绝。
                // 这里使用一个Dialog展示没有这些权限应用程序无法继续运行,询问用户是否去设置中授权。
                AndPermission.with(this)
                    .runtime()
                    .setting()
                    .onComeback(new Setting.Action() {
                        @Override
                        public void onAction() {
                            // 用户从设置回来了。
                        }
                    })
                    .start();
            }
        }
    })
    .start();

参考链接

  1. https://blog.csdn.net/lmj623565791/article/details/50709663
  2. https://blog.csdn.net/yanzhenjie1003/article/details/52503533
  3. https://edu.csdn.net/course/play/3539
  4. https://developer.android.com/training/permissions/requesting?hl=zh-cn
  5. https://developer.android.com/about/versions/marshmallow/android-6.0-changes?hl=zh-cn
  6. https://developer.android.com/training/permissions/best-practices?hl=zh-cn#testing
  7. http://www.yanzhenjie.com/AndPermission/cn/runtime/
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-11-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编码前线 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 兼容性
  • 权限分类
    • Normal Permissions
      • Dangerous Permissions
      • 运行时权限处理
        • 检查权限
          • 请求权限
            • 处理权限请求响应
              • 解释权限的用途
              • AndPermission的使用
                • 导入
                  • 使用
                    • 申请权限
                    • 权限被拒绝,说明权限用途
                    • 权限总是被拒绝,前往设置页授权
                • 参考链接
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档