热门标签 | 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权限申请流程图



推荐阅读
  • 本文探讨了Android系统中支持的图像格式及其在不同版本中的兼容性问题,重点涵盖了存储、HTTP传输、相机功能以及SparseArray的应用。文章详细分析了从Android 10 (API 29) 到Android 11 的存储规范变化,并讨论了这些变化对图像处理的影响。此外,还介绍了如何通过系统升级和代码优化来解决版本兼容性问题,以确保应用程序在不同Android版本中稳定运行。 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 卓盟科技:动态资源加载技术的兼容性优化与升级 | Android 开发者案例分享
    随着游戏内容日益复杂,资源加载过程已不仅仅是简单的进度显示,而是连接玩家与开发者的桥梁。玩家对快速加载的需求越来越高,这意味着开发者需要不断优化和提升动态资源加载技术的兼容性和性能。卓盟科技通过一系列的技术创新,不仅提高了加载速度,还确保了不同设备和系统的兼容性,为用户提供更加流畅的游戏体验。 ... [详细]
  • 本文探讨了资源访问的学习路径与方法,旨在帮助学习者更高效地获取和利用各类资源。通过分析不同资源的特点和应用场景,提出了多种实用的学习策略和技术手段,为学习者提供了系统的指导和建议。 ... [详细]
  • Flutter 2.* 路由管理详解
    本文详细介绍了 Flutter 2.* 中的路由管理机制,包括路由的基本概念、MaterialPageRoute 的使用、Navigator 的操作方法、路由传值、命名路由及其注册、路由钩子等。 ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 在Android应用开发中,实现与MySQL数据库的连接是一项重要的技术任务。本文详细介绍了Android连接MySQL数据库的操作流程和技术要点。首先,Android平台提供了SQLiteOpenHelper类作为数据库辅助工具,用于创建或打开数据库。开发者可以通过继承并扩展该类,实现对数据库的初始化和版本管理。此外,文章还探讨了使用第三方库如Retrofit或Volley进行网络请求,以及如何通过JSON格式交换数据,确保与MySQL服务器的高效通信。 ... [详细]
  • 本文介绍了如何在iOS平台上使用GLSL着色器将YV12格式的视频帧数据转换为RGB格式,并展示了转换后的图像效果。通过详细的技术实现步骤和代码示例,读者可以轻松掌握这一过程,适用于需要进行视频处理的应用开发。 ... [详细]
  • 本文探讨了在Android应用中实现动态滚动文本显示控件的优化方法。通过详细分析焦点管理机制,特别是通过设置返回值为`true`来确保焦点不会被其他控件抢占,从而提升滚动文本的流畅性和用户体验。具体实现中,对`MarqueeText.java`进行了代码层面的优化,增强了控件的稳定性和兼容性。 ... [详细]
  • 为了优化直播应用底部聊天框的弹出机制,确保在不同设备上的布局稳定性和兼容性,特别是在配备虚拟按键的设备上,我们对用户交互流程进行了调整。首次打开应用时,需先点击首个输入框以准确获取键盘高度,避免直接点击第二个输入框导致的整体布局挤压问题。此优化通过调整 `activity_main.xml` 布局文件实现,确保了更好的用户体验和界面适配。 ... [详细]
  • Android ListView 自定义 CheckBox 实现列表项多选功能详解
    本文详细介绍了在Android开发中如何在ListView的每一行添加CheckBox,以实现列表项的多选功能。用户不仅可以通过点击复选框来选择项目,还可以通过点击列表的任意一行来完成选中操作,提升了用户体验和操作便捷性。同时,文章还探讨了相关的事件处理机制和布局优化技巧,帮助开发者更好地实现这一功能。 ... [详细]
  • 在本文中,我们将探讨如何使用 UniApp 封装小程序 API 请求接口的最佳实践。通过创建 `request.js` 文件,定义基础 URL 并传入后端提供的 URL 作为请求参数。同时,配置请求方法(如 GET、POST)和请求头(例如包含 token 的认证信息),以实现高效、安全的 API 调用。此外,我们还将介绍如何处理请求和响应的错误,以及如何优化请求性能,确保应用在不同平台上的兼容性和稳定性。 ... [详细]
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社区 版权所有