热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

解读Android官方开发指导运行时权限

系统权限简介Android出于系统稳定性以及用户隐私方面的考虑,将应用程序访问权限限制在各自的沙盒内。程序可以随意访问所在沙盒内部的资源或者信息,访问沙

封面

系统权限简介

Android出于系统稳定性以及用户隐私方面的考虑,将应用程序访问权限限制在各自的沙盒内。程序可以随意访问所在沙盒内部的资源或者信息,访问沙盒外部的则必须明确的申请相关访问权限。应用程序所需要的权限需要在AndroidManifest.xml文件中申明。如:

...

(本文出处:http://www.jianshu.com/p/0beb...

系统权限根据敏感程度分为普通权限和危险权限两类。两类权限都需要在AndroidManifest.xml文件中申明。在Android 5.1 (API level 22) 及其以下版本上,系统在APP安装时要求用户授权所有权限,否则APP不能安装;而在Android 6.0及其以上版本上,系统在APP安装时授权所有普通权限,危险权限需要在使用时动态让用户授权。这使得Android的权限管理更加灵活,用户可以根据需要在设置应用中对应用的各个危险权限授予不同的权限。Android系统的权限管理不知道被多少人吐槽过,这一改进无疑是加分项。

危险权限

权限申请官方开发指导

Android 6.0上使用在AndroidManifest.xml中已经申明的危险权限时需要用户授权。针对权限请求相关操作系统提供了三个API。下面结合Android官方的开发指导对这几个API做下说明。

  1. checkSelfPermission() 检查是否已经具有了相关权限。任何时候APP都要在执行需要危险权限的操作前去检查是否具有相关权限,即使刚刚执行过这项操作,因为用户很有可能去设置应用中关闭了相关权限。

  2. shouldShowRequestPermissionRationale() 判断是否需要向用户解释,为什么需要这些权限。有时候用户会不理解应用程序为什么需要这些权限。如,相机应用申请摄像头使用权限用户容易理解,但是相机应用申请地理位置使用权限可能会让用户产生疑惑,因为用户很有能不知道相机需要保存每张照片的拍摄地点。这时候我们就需要做适当的解释说明了。这个方法只有在APP请求过某一权限且用户禁止APP使用该权限的时候返回true。在用户授权了权限和禁止权限时勾选了“Don't ask again”选项的情况下都会返回false。Android官方开发指导还提到一点,为避免给用户带来糟糕的用户体验,这里的解释说明应该是异步的,不要阻塞用户的操作。时下很多适配了6.0的APP在这点上处理的都不尽如人意,有的根本没有解释说明,有的是弹出对话框,用户体验都不是很好。下文会给出了一个完美的解决方案。

  3. requestPermissions() 申请相关权限。调用这个方法后会弹出一个系统对话框来向用户申请权限,APP不能自定义这个对话框的内容,这也就增加了上面提到的解释说明的必要性。这里还有一点也需要交代一下。从上面危险权限列表中也可以看出,这些权限都是有分组的。如,READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE权限就是属于STORAGE组的。分门别类不仅仅是为了方便容易阅读,组内权限在申请上也是有关联的。

    • 在申请组内某个权限时,弹出的系统对话框会显示组名,而不是指明所申请的权限名。如,申请READ_EXTERNAL_STORAGE权限时,系统对话框提示请求“访问sd卡”权限,但不会说明是请求的sd卡读权限;

    • 申请权限时,如果组内有别的权限已经获得了用户授权,系统不再弹出询问对话框,而是自动授权该权限。如,在申请WRITE_EXTERNAL_STORAGE权限时用户已经授权了READ_EXTERNAL_STORAGE权限,系统则会自动授权WRITE_EXTERNAL_STORAGE权限,不再询问用户;

    • 即使有前一条规则存在,在使用每一条权限时都必须(不是应该)调用requestPermissions()方法来申请权限。如,在已经获取了READ_EXTERNAL_STORAGE权限的情况下,使用WRITE_EXTERNAL_STORAGE权限时依然需要调用requestPermissions()方法来申请,否则就会因为权限问题导致写sd卡失败。

注意:危险权限在AndroidManifest.xml文件中也必须申明,否则动态申请会失败。

下面代码是Android官方开发指导中权限申请大致框架。它使用了Android Support Library中的方法。虽然Android 6.0以后的framework中都有这些方法,但是对于开发者来说使用Android Support Library中的方法更简单,不用检查sdk版本可以兼容低版本。

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_EXTERNAL_STORAGE)) { // Show an expanation to the user *asynchronously* -- don't blockthis 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_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); // MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is anapp-defined int constant. // The callback method gets the result of the request. }
}

requestPermissions()申请有结果后会回调onRequestPermissionsResult()方法,这种方式对于Android开发者一定不会陌生,因为与startActivityForResult()结果回调onActivityResult()方法类似。如下重载onRequestPermissionsResult()方法即可。

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: { // 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 }
}

由于我们使用了AndroidSupport Library库记得在build.gradle文件中添加依赖。

dependencies { ...compile 'com.android.support:appcompat-v7:23.2.1'
}

动态权限申请封装类EasyPermissionsEx

以上就是Android官方开发指导关于动态权限申请的全部内容了。系统的API已经很简洁了,但是用在项目中时依然会出现很多重复代码,按惯例是要封装一下。在github上搜索"Android permissions"会有很多开源库。Google在github上也开源了一个关于动态权限的封装库easypermissions。看了几个库后,个人觉得easypermissions写的最好,但是也有不足的地方。如,解释为什么需要权限的地方这个库也弹出一个对话框阻塞了用户操作,不符合开发规范、还有用户禁止权限时勾选了“Don't ask again”后依然会弹出对话框请求权限,用户体验不好。所以我在easypermissions库的基础封装了一个EasyPermissionsEx库。说是一个库,其实只有一个300行左右的类,你可以直接拷贝到你的项目中使用。

前文也提到过在解释为什么需要权限或者在用户永久禁止权限后引导用户去设置应用开启权限时,使用对话框会给用户带来不好的体验。EasyPermissionsEx采用的解决方案是使用snackbar来提醒用户。整体效果如下。snackbar是一种轻量级的用户交互,它不会阻塞用户当前的操作,是从底部弹出一个bar来提示用户,类似toast,但是snackbar又有一个button允许用户操作。关于snackbar更多信息可以跳转到官方文档了解。

EasyPermissionsEx效果图

Snackbar在Android Design Support Library库中记得在build.gradle文件中添加依赖。

dependencies { ...compile 'com.android.support:design:23.4.0'
}

EasyPermissionsEx权限请求逻辑如下。关于EasyPermissionsEx更多详情可以去github查看wiki,也可以直接看代码,因为它总共也就300行代码。

EasyPermissionsEx权限申请流程图



推荐阅读
  • 先看看效果是不是自己想要的吧item及item内部控件点击事件不懂的可以先点击查看 ... [详细]
  • 1.安装cordovapluginaddcordova-plugin-file-transfercordovapluginaddcordova-plugin-fi ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 今天就跟大家聊聊有关怎么在Android应用中实现一个换肤功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根 ... [详细]
  • 如何通过Wifi将Android设备与PC连接
    什么是Appium?设置AppiumAppium基础知识Appium中级要知道的事情如何查找APK文件的appPackage和appActivity转移APK从手机到 ... [详细]
  • 如何理解MyBatis动态SQL
    本篇内容主要讲解“如何理解MyBatis动态SQL”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解M ... [详细]
  • apk简单介绍APK的组成apk安装流程app的启动过程apk打包流程AIDLAIDL介绍为什么要设计这门语言它有哪些语法?默认支持的数据类型包括什么是apk打包流程 ... [详细]
  • Smali代码注入
    以下的内容是对官方MIUIV4移植教程的补充,其中一些工具的使用就不在这里赘述,请大家参考官方教程。好的,话不多说,进入正题 ... [详细]
  • POI编程
    POI编程1简介在我们实际的开发中,表现层的解决方案虽然有多样,但是IE浏览器已成为最多人使用的浏览器,因为大家都用Windows。在企业办公系统中 ... [详细]
  • 一、EF的三种设计模型CodeFirst,ModelFirst,DBFirst三种在软件的实际开发中最常用的就是后两种。下面简单介绍两种设计模型的区别和两种更新的区别 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • 本文介绍了Android中的assets目录和raw目录的共同点和区别,包括获取资源的方法、目录结构的限制以及列出资源的能力。同时,还解释了raw目录中资源文件生成的ID,并说明了这些目录的使用方法。 ... [详细]
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
author-avatar
手机用户2602938575
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有