Android应用权限简要介绍

一个Android应用默认情况下是不拥有任何权限的, 这即是说, 在默认情况下, 一个应用是没有权利去进行一些可能会造成不好影响的操作的. 这些不好的影响可能是对其它应用,操作系统,或者是用户.
如果应用需要一些额外的能力,则它需要在AndroidManifest.xml中静态地声明相应的权限.
 
如果应用没有在manifest中声明权限, 却使用了相应的功能, 在调用到相应功能的时候, 将会抛出异常.
比如程序要发送一个请求,却忘记加Internet权限, 那么在发送这个请求的时候程序就会抛出异常,一般不会catch这个异常,所以程序直接就崩溃了:
Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)
 
 
Android 6.0 (API 23) 发布之前, 所有的权限都在安装应用的时候显示给用户,用户选择安装则表示全部接受这些权限, 之后无法撤销对这些权限的授权.
Android 6.0开始, 一部分比较危险的权限需要在程序运行时显式弹框,请求用户授权.
至于什么时候弹这个框,由应用程序自己决定.
对于其他权限,认为不是很危险,所以仍然保持原来的做法,在用户安装应用程序时就予以授权.
还需要注意的是,在设置中,对于应用的危险权限,用户可以选择性地进行授权或者关闭.
 

Permission的保护等级

permission的保护等级通过protectionLevel属性设置, 共有4种: normal,dangerous,signature,signatureOrSystem.
 
签名相关的比较不常用, 剩下的两种是normaldangerous.
Guides里面对这两种类型进行了讨论: 官网Guides: https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
总结下来就是: 所有的权限仍然在manifest中静态声明, normal权限的在安装的时候自动授权, 而dangerous的权限需要应用明确地请求用户授权.
当然对于Android 6.0以下的手机,或者以前开发的旧应用来说, dangerous权限也是安装时授权的, 具体看下一节的讨论.
 
Dangerous Permissions: 
 
 
想要查看所有dangerous的权限, 也可以用命令:
adb shell pm list permissions -g -d
  

手机版本和程序版本的不同处理

这里引用一段Guildes里面的原文:
  • If the device is running Android 6.0 (API level 23) or higher, and the app's targetSdkVersion is 23 or higher, the app requests permissions from the user at run-time. The user can revoke the permissions at any time, so the app needs to check whether it has the permissions every time it runs. For more information about requesting permissions in your app, see the Working with System Permissions training guide.
  • If the device is running Android 5.1 (API level 22) or lower, or the app's targetSdkVersion is 22 or lower, the system asks the user to grant the permissions when the user installs the app. If you add a new permission to an updated version of the app, the system asks the user to grant that permission when the user updates the app. Once the user installs the app, the only way they can revoke the permission is by uninstalling the app.
这里头要注意and和or的使用,说明了只有满足targetSdkVersion和实际使用设备的版本都在23及以上的时候,才会采用新的动态权限机制. 其他情况, 跟之前一样, 在安装和升级应用的时候就授权了所有的权限.
 
可以总结为:
1.所有的权限都在manifest中声明.
2.如果(1)你的app的targetSdkVersion是23及以上,并且(2)app运行在Android 6.0及以上的设备,危险权限必须动态请求.
当权限被拒绝,app理应还是能够使用的,只不过权限相关的部分功能不能用.
3.上一条中的两个条件(1)(2)没有同时满足,即属于其他情况, 所有权限在安装时请求,如果用户不接受,则不安装.
 
特别注意这种情况: 旧应用新系统.
如果targetSdkVersion小于23,即被认为是Android 6.0发布之前开发的应用, 还没有兼容6.0.
这种应用即便是被装在Android 6.0的机器上,也是采用原来的安装即授予权限逻辑, 所有权限在应用安装时全部被授权.
在Android 6.0的设备上安装targetSdkVersion小于23的应用之后, 可以在应用的设置中查看,发现所有的dangerous权限状态都是打开. 
所以不用担心老的应用在Android 6.0上会各种乱崩.
 
但是用户仍然可以在系统设置中禁用权限:
在模拟器上点击授权开关的时候弹出了以下提示:
如果用户执意要取消授权, 应用虽然不会直接崩溃,但是功能变为默默无作为状态, 返回值可能变为null或者0,进而引起无法预料的行为或者崩溃. 
 

为什么要及时升级targetSdkVersion

这是因为每一个版本的API有可能会产生新的权限,这些新增的权限, 对于targetSdkVersion比该API低的应用是自动获取的.
所以targetSdkVersion最好是能及时写到最新,这样避免应用自动获取到新API新增的权限.
 
结论: 对targetSdkVersion还不存在的权限是自动获取到的.
 
其中”Automatic permission adjustments”那段.
 

Permission group

所有的权限都有自己的permission group.
系统弹框请求某一个permission时也是只说明了它的类别,当用户同意,系统会给予它该条permission.(只有这一条).
但是如果app已经有了该group下的另一条permission,系统将会自动授予权限(也即请求权限的callback直接返回),这过程中不与用户交互.
 

动态权限请求的实现

因为权限动态检查相关的API是Android 6.0才加入的, 所以minSdkVersion不是23时,推荐使用SupportLibrary来实现,好处是: 程序里不必加if来判断当前设备的版本.

1.检查权限状态

如果执行的操作需要一个dangerous permission, 那么每次在执行操作的地方都必须check你是否有这个permission, 因为用户可以在应用设置里随意地更改授权情况, 所以必须每次在使用前都检查是否有权限.
 
检查权限的方法: ContextCompat.checkSelfPermission()两个参数分别是Context和权限名.
返回值是:PERMISSION_GRANTED if you have the permission, or PERMISSION_DENIED if not.
 
比如:
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_CONTACTS)) {
//has permission, do operation directly
ContactsUtils.readPhoneContacts(this);
Log.i(DEBUG_TAG, "user has the permission already!");
} else {
//do not have permission
 

2.动态请求权限

如果上面权限检查的结果是DENIED, 那么就需要显式地向用户请求这个权限了.
Android提供了几个方法来动态请求权限, 调用这些方法会显示出一个标准的Dialog, 这个Dialog目前是不能被定制的.
 
2.1有时候可能需要解释为什么需要这个权限
有时候你可能会需要跟用户解释一下权限的用途.
注意不是每条权限都需要解释,显而易见的那种可以不解释,太多的解释会降低用户体验.
 
一种方式是,当用户拒绝过这个权限,但是又用到了这个功能, 那么很可能用户不是很明白为什么app需要这个权限, 这时候就可以先向用户解释一下.
为了发现这种用户可能需要解释的情形, Android提供了一个工具类方法: shouldShowRequestPermissionRationale()
如果app之前请求过该权限,被用户拒绝, 这个方法就会返回true.
如果用户之前拒绝权限的时候勾选了对话框中”Don’t ask again”的选项,那么这个方法会返回false.
如果设备策略禁止应用拥有这条权限, 这个方法也返回false.
 
注意具体解释原因的这个dialog需要自己实现, 系统没有提供.
 
2.2请求权限
请求权限的方法是: requestPermissions() 传入一个Activity, 一个permission名字的数组, 和一个整型的request code.
这个方法是异步的,它会立即返回, 当用户和dialog交互完成之后,系统会调用回调方法,传回用户的选择结果和对应的request code.
代码:
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_CONTACTS)) {
//has permission, do operation directly
ContactsUtils.readPhoneContacts(this);
Log.i(DEBUG_TAG, "user has the permission already!");
} else {
//do not have permission
Log.i(DEBUG_TAG, "user do not have this permission!"); // Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.READ_CONTACTS)) { // Show an explanation 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.
Log.i(DEBUG_TAG, "we should explain why we need this permission!");
} else { // No explanation needed, we can request the permission.
Log.i(DEBUG_TAG, "==request the permission=="); ActivityCompat.requestPermissions(MainActivity.this,
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.
}
}
 
这个对话框是系统的,不能自定义.
经验证, 请求权限对话框中的”Don’t ask again”的选项, 只有该条权限之前的状态是Denied的时候,才会出现.
以前从未授权(即第一次弹框), 或者之前的状态是Granted(当然这种情况一般不会弹框询问), 出现的弹框都是不带该不再询问的选项的.
 
2.3处理请求权限的响应
当用户对请求权限的dialog做出响应之后,系统会调用onRequestPermissionsResult() 方法,传回用户的响应.
这个回调中request code即为调用requestPermissions()时传入的参数,是app自定义的一个整型值.
如果请求取消,返回的数组将会为空.
 
代码:
@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.
ContactsUtils.readPhoneContacts(this);
Log.i(DEBUG_TAG, "user granted the permission!"); } else { // permission denied, boo! Disable the
// functionality that depends on this permission.
Log.i(DEBUG_TAG, "user denied the permission!");
}
return;
} // other 'case' lines to check for other
// permissions this app might request
}
}
 
 
系统自动回调的情况: 
有一些情形下,调用
1.自动授权: 如果用户已经允许了permission group中的一条A权限,那么当下次调用requestPermissions()方法请求同一个group中的B权限时, 系统会直接调用onRequestPermissionsResult() 回调方法, 并传回PERMISSION_GRANTED的结果.
2.自动拒绝: 如果用户选择了不再询问此条权限,那么app再次调用requestPermissions()方法来请求同一条权限的时候,系统会直接调用onRequestPermissionsResult()回调,返回PERMISSION_DENIED.
 
 
 

Best Practices

Best Practices 总结:
1.用Intent启动其他应用来完成功能.
2.只用真的需要的权限.
3.不要一次请求多个权限来烦用户,有的权限可以等到要用的时候再请求.
4.向用户解释为什么需要这个权限.
5.从Android 6.0开始,每一条权限,都需要测试开关两种状态下是不是都能让应用正常运行,而不是崩溃.
并且相关的权限可能会需要测试不同的组合.
 

ADB命令

可以用命令行来管理权限:
Use the adb tool to manage permssions from the command line:

  • List permissions and status by group:

    $ adb shell pm list permissions -d -g

  • Grant or revoke one or more permissions:
    $ adb shell pm [grant|revoke] <permission-name> ... 

参考资料:

 
 
 
第三方库: 
 
转自:http://www.cnblogs.com/mengdd/p/4892856.html

Android M Permission 学习笔记的更多相关文章

  1. Android安装器学习笔记(一)

    Android安装器学习笔记(一) 一.Android应用的四种安装方式: 1.通过系统应用PackageInstaller.apk进行安装,安装过程中会让用户确认 2.系统程序安装:在开机的时候自动 ...

  2. android cocos2d-x for Android安装和学习笔记(请用adt-bundle21.1或以上导入)

    引用:http://weimingtom.iteye.com/blog/1483566 (20121108)注意:这篇文章用cdt编译ndk工程的内容已过时(现在可以用adt-bundle,避免配置繁 ...

  3. Android Socket编程学习笔记

    http://blog.csdn.net/eyu8874521/article/details/8847173 度娘给出的描述:通常也称作"套接字",用于描述IP地址和端口,是一个 ...

  4. Android应用开发学习笔记之播放音频

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android支持常用音视频格式文件的播放,本文我们来学习怎样开发Android应用程序对音视频进行操作. Andr ...

  5. android 7.0 学习笔记(一)

    导读 增强的Doze模式 后台优化 Data Saver 一.增强的Doze模式 Android N对Android M引进的Doze模式进行了进一步的增强,变化体现在两个方面.一方面是降低了进入Do ...

  6. Android API Guides 学习笔记---Application Fundamentals(一)

    今天开始学习google官网上的API guides ,主要读了Application Fundamentals这一章节,此章节介绍了一个App的基本组成,共包括四大部分内容. 1.      App ...

  7. Android应用开发学习笔记之事件处理

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android提供的事件处理机制分为两类:一是基于监听的事件处理:二是基于回调的事件处理.对于基于监听的事件处理,主 ...

  8. Android应用开发学习笔记之Intent

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Intent是什么呢?来看Android官网上的定义: An intent is an abstractdescri ...

  9. Android应用开发学习笔记之AsyncTask

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 在上一篇文章中我们学习了多线程和Handler消息处理机制,如果有计算量比较大的任务,可以创建一个新线程执行计算工作 ...

随机推荐

  1. 一步一步搭建客服系统 (4) 客户列表 - JS($.ajax)调用WCF 遇到的各种坑

    本文以一个生成.获取“客户列表”的demo来介绍如何用js调用wcf,以及遇到的各种问题. 1 创建WCF服务 1.1 定义接口 创建一个接口,指定用json的格式:   [ServiceContra ...

  2. [ACM_水题] 不要62(hdu oj 2089, 不含62和4的数字统计)

    Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来, ...

  3. 高德地图iOS SDK限制地图的缩放比例

    问题 高德地图的iOS SDK 3D版中(v2.4.0), 显示范围在560m左右时建筑会呈现3D效果. 我们有没有办法可以限制地图最小缩放到这个比例, 从而保证建筑始终使用3D效果显示呢? 探索 高 ...

  4. SSL双向认证java实现(转)

    本文通过模拟场景,介绍SSL双向认证的java实现 默认的情况下,我认为读者已经对SSL原理有一定的了解,所以文章中对SSL的原理,不做详细的介绍. 如果有这个需要,那么通过GOOGLE,可以搜索到很 ...

  5. 转载:python原生态的输入窗口抖动+输入特效

    python原生态的输入窗口抖动+输入特效 出处:https://coding.net/u/acee/p/PythonPowerInput/git/blob/master/test_power_inp ...

  6. 使用socket.io开发简单群聊功能

    1.新建package.json文件: { "name": "socket-chat-example", "version": " ...

  7. iOS开发-Alpha,Hidden与Opaque区别

    UIView中的这三个属性用的比较多,尤其是Alpha和Opaque之间有的时候不是很好分别,稍微整理下: Alpha(不透明度) alpha是不透明度,属性为浮点类型的值,取值范围从0到1.0,表示 ...

  8. WizardDialog 进度条使用记录

    开发RCP的朋友们经常会使用到导航窗口, 先简单介绍一下wizardDialog,基本上他的使用方法是这样的 首先有一个WizardDialog,在dialog里面需要放一个Wizard来控制页面Wi ...

  9. (转)阴影锥(Shadow Volume)

    转自:http://blog.csdn.net/zjull/article/details/11819923 Shadow Map和Shadow Volume是当今比较流行的实时阴影渲染方法,跟Sha ...

  10. fine-uploader 5.11.8 (最新版) 使用感受

    以前测试和使用过 3.X 因为够用,所以一直没升级,今天闲来无聊测试了一下最新版.和3.X比性能上好了很多,但不支持了移动设备的多文件上传. 关于3.X版 可以看这里:http://www.cnblo ...