从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予。此方法可以简化应用安装过程,因为用户在安装或更新应用时不需要授予权限。它还让用户可以对应用的功能进行更多控制;

例如,用户可以选择为相机应用提供相机访问权限,而不提供设备位置的访问权限。用户可以随时进入应用的 “Settings” 屏幕调用权限。

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

  • 正常权限不会直接给用户隐私权带来风险。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。
  • 危险权限会授予应用访问用户机密数据的权限。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。如果您列出了危险权限,则用户必须明确批准您的应用使用这些权限。

  如需了解详细信息,请参阅正常权限和危险权限

在所有版本的 Android 中,您的应用都需要在其应用清单中同时声明它需要的正常权限和危险权限,如声明权限中所述。不过,该声明的影响因系统版本和应用的目标 SDK 级别的不同而有所差异:

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

:从 Android 6.0(API 级别 23)开始,用户可以随时从任意应用调用权限,即使应用面向较低的 API 级别也可以调用。

无论您的应用面向哪个 API 级别,您都应对应用进行测试,以验证它在缺少需要的权限时行为是否正常。

检查权限

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

要检查您是否具有某项权限,请调用 ContextCompat.checkSelfPermission() 方法。例如,以下代码段显示了如何检查 Activity 是否具有在日历中进行写入的权限:

 // 假设当前activity需要此权限
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);
if(permissionCheck == PackageManager.PERMISSION_GRANTED) {
// 具有该权限
} else {
// 不具有该权限
}

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

请求权限

如果您的应用需要应用清单中列出的危险权限,那么,它必须要求用户授予该权限。Android 为您提供了多种权限请求方式。调用这些方法将显示一个标准的 Android 对话框,不过,您不能对它们进行自定义。

解释应用为什么需要权限

在某些情况下,您可能需要帮助用户了解您的应用为什么需要某项权限。例如,如果用户启动一个摄影应用,用户对应用要求使用相机的权限可能不会感到吃惊,但用户可能无法理解为什么此应用想要访问用户的位置或联系人。在请求权限之前,不妨为用户提供一个解释。

您可以采用的一个方法是仅在用户已拒绝某项权限请求时提供解释。如果用户继续尝试使用需要某项权限的功能,但继续拒绝权限请求,则可能表明用户不理解应用为什么需要此权限才能提供相关功能。对于这种情况,比较好的做法是显示解释。

为了帮助查找用户可能需要解释的情形,Android 提供了一个实用程序方法,即 shouldShowRequestPermissionRationale() 。如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。

:如果用户在过去拒绝了权限请求,并在权限请求系统对话框中选择了 不在提示 选项,此方法将返回 false

如果设备规范禁止应用具有该权限,此方法也会返回 false

请求你需要的权限

如果应用尚无所需的权限,则应用必须调用一个 requestPermissions() 方法,以请求适当的权限。应用将传递其所需的权限,以及您指定用于识别此权限请求的整型请求代码。此方法异步运行:它会立即返回,并且在用户响应对话框之后,系统会使用结果调用应用的回调方法,将应用传递的相同请求代码传递到 requestPermissions() 。

以下代码可以检查应用是否具备读取用户联系人的权限,并根据需要请求该权限:

 if (ContextCompat.checkSelfPermission(thisActivity, 
      Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { // 需要解释的权限许可
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_CONTACTS)) { // 显示一个解释给用户*asynchronously* -- 不要阻塞,采用异步形式等待用户的响应,用户看到说明后,再试一次请求权限。
} else { // 不需要解释的权限许可

ActivityCompat.requestPermissions(thisActivity,
          new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS(int)回调方法获取请求结果
}
}

系统显示的对话框说明了您的应用需要访问的权限组;它不会列出具体权限。例如,如果您请求 READ_CONTACTS 权限,系统对话框只显示您的应用需要访问设备的联系人。用户只需要为每个权限组授予一次权限。如果您的应用请求该组中的任何其他权限(已在您的应用清单中列出),系统将自动授予应用这些权限。当您请求此权限时,系统会调用您的 onRequestPermissionsResult() 回调方法,并传递 PERMISSION_GRANTED,如果用户已通过系统对话框明确同意您的权限请求,系统将采用相同方式操作。

:您的应用仍需要明确请求其需要的每项权限,即使用户已向应用授予该权限组中的其他权限。

此外,权限分组在将来的 Android 版本中可能会发生变化。您的代码不应依赖特定权限属于或不属于相同组这种假设。

例如,假设您在应用清单中列出了 READ_CONTACTS 和 WRITE_CONTACTS。如果您请求 READ_CONTACTS 且用户授予了此权限,那么,当您请求 WRITE_CONTACTS 时,系统将立即授予您该权限,不会与用户交互。

如果用户拒绝了某项权限请求,您的应用应采取适当的操作。例如,您的应用可能显示一个对话框,解释它为什么无法执行用户已经请求但需要该权限的操作。

当系统要求用户授予权限时,用户可以选择指示系统不再要求提供该权限。这种情况下,无论应用在什么时候使用 requestPermissions() 再次要求该权限,系统都会立即拒绝此请求。系统会调用您的 onRequestPermissionsResult() 回调方法,并传递 PERMISSION_DENIED,如果用户再次明确拒绝了您的请求,系统将采用相同方式操作。这意味着当您调用 requestPermissions() 时,您不能假设已经发生与用户的任何直接交互。

Android 权限管理的更多相关文章

  1. Android权限管理之RxPermission解决Android 6.0 适配问题

    前言: 上篇重点学习了Android 6.0的运行时权限,今天还是围绕着Android 6.0权限适配来总结学习,这里主要介绍一下我们公司解决Android 6.0权限适配的方案:RxJava+RxP ...

  2. Android权限管理之Android 6.0运行时权限及解决办法

    前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...

  3. Android权限管理之Permission权限机制及使用

    前言: 最近突然喜欢上一句诗:"宠辱不惊,看庭前花开花落:去留无意,望天空云卷云舒." 哈哈~,这个和今天的主题无关,最近只要不学习总觉得生活中少了点什么,所以想着围绕着最近面试过 ...

  4. android: Android 权限管理小结

    一. 概述 感谢郭神,自从Android6.0发布以来,在权限上做出了很大的变动,不再是之前的只要在manifest设置就可以任意获取权限,而是更加的注重用户的隐私和体验,不会再强迫用户因拒绝不该拥有 ...

  5. Android权限管理知识学习记录

    一.Android权限背景知识 在Android 6.0之前,所申请的权限只需要在AndroidManifest.xml列举就可以了,从而容易导致一些安全隐患,因此,在Android 6.0时,Goo ...

  6. Android权限管理PermissionsDispatcher2.3.2使用+原生6.0权限使用

    PermissionsDispatcher2.3.2使用 Android6.0权限官网https://developer.android.com/about/versions/marshmallow/ ...

  7. Android 权限管理(持续整理)

    1. Android 6.0之后,APP可以直接安装,运行时再询问用户授予相关权限,此时系统弹出一个对话框,(这个对话框不能由开发者定制) 同时用户也可以在手机的“设置”中对于某个App进行权限管理 ...

  8. android 权限管理和签名 实现静默卸载

    为了实现静默卸载, 学了下android的安全体系,记录如下 最近在做个东西,巧合碰到了sharedUserId的问题,所以收集了一些资料,存存档备份. 安装在设备中的每一个apk文件,Android ...

  9. Android权限管理

    使用系统权限 为了保护系统的完整性和用户隐私权,Android 在访问受限的沙盒中运行每款应用.如果应用需要使用其沙盒以外的资源或信息,则必须明确请求权限.根据应用请求的权限类型,系统可能会自动授予权 ...

随机推荐

  1. InstallShield集成安装MSDE2000最小版本(二) fishout特许授权发布

    原文:InstallShield集成安装MSDE2000最小版本(二) fishout特许授权发布 原帖地址:http://blog.csdn.net/fishout/archive/2009/10/ ...

  2. erlang mnesia数据库简单应用

    mnesia是erlang自带的分布式数据库,基于ets和dets实现的.mnesia兼顾了dets的持久性和ets的高性能,可以自动在多个erlang节点间同步数据库.最关键的是,mnesia实现了 ...

  3. 全新通用编程语言 Def 招募核心贡献者、文档作者、布道师 deflang.org

    先给出官网地址:deflang.org 一句话简介:可扩展编程语言 Def 的目标是将 C++ 的高效抽象和 Lisp 的强大表现力融为一体. 你可以通过阅读 入门教程 .源码 或 测试用例 来简要或 ...

  4. 安装Visual Studio 2010 - 初学者系列 - 学习者系列文章

    本文讲述如何安装Visual Studio 2010开发工具. 首先,通过下列地址获取Visual Studio 2010的副本 1.开始页面 2.欢迎页 3.这里选择 自定义 ,选择安装路径 4.这 ...

  5. Centos中如何配置Texlive2013中文字体的问题

    Centos中如何配置Texlive2013中文字体的问题: 第一步是下载你需要的字体,我从windows/fonts中拷贝的比较多,你只要复制你需要的字体即可. 注意只要文件扩展名为ttf的文件,t ...

  6. Toast,AlertDialog的误解

    在一般的软件开发中,子线程中是不能更改UI主线程中创建的UI控件的.之前的理解是Toast也不能在子线程中创建.事实上并不是这样子的. @Override protected void onCreat ...

  7. 玩转python之每次处理一个字符

    在Python中字符就是长度为1的字符串,所以可以循环遍历一个字符串,依次访问每一个字符,得到你想要的处理前提: 一个列表是个好主意,就像这样:thelist = list(thestring) 当然 ...

  8. MySQL中char和varchar有啥区别?优缺点是啥?

    在mysql教程中char与varchar的区别呢,都是用来存储字符串的,只是他们的保存方式不一样罢了,char有固定的长度,而varchar属于可变长的字符类型. char与varchar的区别 c ...

  9. W3C的CORS Specification

    W3C的CORS Specification 随着Web开放的程度越来越高,通过浏览器跨域获取资源的需求已经变得非常普遍.在我看来,如果Web API不能针对浏览器提供跨域资源共享的能力,它甚至就不应 ...

  10. 细节MARK

    在刷vijos1046的时候遇到了一些细节,MARK一下 1.哲学之前有告诫我说,输出long long的数的时候,最好用cout,不然容易出现编译器的问题,今天算是领教了 2.对于数组赋值问题 me ...