Android复习(四)权限—>请求应用权限
每款 Android 应用都在访问受限的沙盒中运行。如果应用需要使用其自己的沙盒外的资源或信息,则必须请求相应权限。 要声明您的应用需要某项权限,您可以在应用清单中列出该权限,然后在运行时请求用户批准每项权限(适用于 Android 6.0 及更高版本)。
本页介绍如何使用 Android 支持库来检查和请求权限。Android 框架从 Android 6.0(API 级别 23)开始提供类似的方法,但如果使用支持库,将会更容易与较低的 Android 版本实现兼容性。
对于所有 Android 版本,要声明应用需要某项权限,请在应用清单中添加 <uses-permission> 元素,作为顶级 <manifest> 元素的子项。例如,需要访问互联网的应用需在清单中添加以下代码行:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.snazzyapp"> <uses-permission android:name="android.permission.INTERNET"/>
<!-- other permissions go here --> <application ...>
...
</application>
</manifest>
系统在您声明权限之后的行为取决于权限的敏感程度。有些权限被视为“常规”权限,因此系统会在安装应用时立即授予这些权限。还有些则被视为“危险”权限,因此需要用户明确向您的应用授予相应访问权限。如需详细了解不同类型的权限,请参阅保护级别。
检查权限
如果应用需要一项危险权限,那么每次执行需要该权限的操作时,您都必须检查自己是否具有该权限。从 Android 6.0(API 级别 23)开始,用户可随时从任何应用撤消权限,即使应用以较低的 API 级别为目标平台也是如此。因此,即使应用昨天使用了相机,也不能认为它今天仍具有该权限。
要检查您是否具有某项权限,请调用 ContextCompat.checkSelfPermission() 方法。例如,以下代码段展示了如何检查 Activity 是否具有向日历写入数据的权限:
java代码:
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
}
kotlin代码:
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
}
如果应用具有此权限,该方法将返回 PERMISSION_GRANTED,并且应用可以继续操作。如果应用不具备此权限,该方法将返回 PERMISSION_DENIED,且应用必须明确要求用户授予权限。
请求权限
当您的应用从 checkSelfPermission() 收到 PERMISSION_DENIED 时,您需要提示用户授予该权限。Android 为您提供了几种可用来请求权限的方法(如 requestPermissions()),如下面的代码段所示。调用这些方法时,会显示一个无法自定义的标准 Android 对话框。
如何向用户显示此内容取决于设备的 Android 版本以及应用的目标版本,如权限概览中所述。
解释为什么应用需要权限
在某些情况下,您需要帮助用户理解为什么您的应用需要某项权限。例如,如果用户启动一款摄影应用,用户或许不会对该应用请求使用相机的权限感到惊讶,但用户可能不理解为什么该应用想要访问用户的位置或联系人。在您的应用请求权限之前,不妨考虑向用户提供解释。请注意,您肯定不希望您的解释让用户不胜其烦;如果您提供太多解释,用户可能会觉得这款应用很麻烦,因而将其移除。
您可以使用的一种方法是只在用户之前拒绝过该权限请求的情况下才提供解释。Android 提供了一种实用程序方法,即 shouldShowRequestPermissionRationale()。如果用户之前拒绝了该请求,该方法将返回 true;如果用户之前拒绝了某项权限并且选中了权限请求对话框中的不再询问选项,或者如果设备政策禁止该权限,该方法将返回 false。
如果用户不断尝试使用需要某项权限的功能,但一直拒绝权限请求,这或许意味着,用户不理解为什么应用需要该权限才能提供这项功能。在这种情况下,显示解释或许是不错的做法。
应用权限最佳做法中提供了更多建议,指导您如何在请求权限时创造良好的用户体验。
在必要时请求成为默认处理程序
有些应用依赖于访问与通话记录和短信有关的敏感用户信息。如果您想请求特定于通话记录和短信的权限,并将应用发布到 Play 商店,则必须在请求这些运行时权限之前提示用户将应用设置为“默认处理程序”以获得核心系统功能。
如需详细了解默认处理程序(包括有关如何向用户显示默认处理程序提示的指南),请参阅有关仅在默认处理程序中使用的权限的指南。
请求您需要的权限
如果您的应用还不具备它需要的权限,那么它必须调用一个 requestPermissions() 方法来请求相应权限。您的应用将传递它想要的权限,以及您指定用于识别此权限请求的整数请求代码。此方法异步运行。它会立即返回结果,并且在用户响应提示后,系统会利用相应结果来调用应用的回调方法,在调用过程中传递的请求代码与应用传递给 requestPermissions() 的请求代码相同。
以下代码将检查应用是否具有读取用户联系人的权限。如果没有该权限,它会检查是否应显示需要该权限的解释,如果不需要解释,它会请求该权限:
java代码:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
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.
} else {
// No explanation needed; 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.
}
} else {
// Permission has already been granted
}
kotlin代码:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
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.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
arrayOf(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.
}
} else {
// Permission has already been granted
}
系统显示的提示说明了您的应用需要访问的权限组,而不是具体权限。
注意:当您的应用调用 requestPermissions() 时,系统会向用户显示一个标准对话框。您的应用无法配置或更改该对话框。如果您需要向用户提供任何信息或解释,您应该在调用 requestPermissions() 之前这样做,如解释为什么应用需要权限中所述。
处理权限请求响应
当用户响应您应用的权限请求时,系统会调用您应用的 onRequestPermissionsResult() 方法,在调用过程中向其传递用户响应。您的应用必须替换该方法,以查明是否已向其授予相应权限。在回调过程中传递的请求代码与传递给 requestPermissions() 的请求代码相同。例如,如果应用请求 READ_CONTACTS 访问权限,则它可能采用以下回调方法:
java代码:
@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.
}
}
kotlin代码:
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
MY_PERMISSIONS_REQUEST_READ_CONTACTS -> {
// If request is cancelled, the result arrays are empty.
if ((grantResults.isNotEmpty() && 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
}
// Add other 'when' lines to check for other
// permissions this app might request.
else -> {
// Ignore all other requests.
}
}
}
系统显示的对话框说明了您的应用需要访问的权限组,它不会列出具体权限。例如,如果请求 READ_CONTACTS 权限,系统对话框只会说明您的应用需要访问设备的联系人。用户只需要针对每个权限组授予一次权限。如果您的应用请求该组中的其他任何权限(已在您的应用清单中列出),系统会自动授予这些权限。当您请求权限时,系统会调用您的 onRequestPermissionsResult() 回调方法并传递 PERMISSION_GRANTED,就像用户通过系统对话框明确同意了您的请求时的处理方式一样。
注意:您的应用仍需要明确请求它需要的每项权限,即使用户已授予同一组中的其他权限。此外,权限分组在将来的 Android 版本中可能会发生变化。您的代码不应依赖于特定权限属于或不属于同一组的假设。
例如,假设您在应用清单中同时列出了 READ_CONTACTS 和 WRITE_CONTACTS。如果您请求 READ_CONTACTS 且用户授予了该权限,那么当您随后又请求 WRITE_CONTACTS 时,系统会立即授予您该权限,而无需与用户交互。
如果用户拒绝了权限请求,您的应用应采取适当的措施。例如,您的应用可能会显示一个对话框,解释它为什么无法执行用户请求的需要该权限的操作。
当系统要求用户授予某项权限时,用户可以选择告知系统不要再次请求该权限。在这种情况下,只要应用使用 requestPermissions() 再次请求该权限,系统就会立即拒绝请求。系统会调用您的 onRequestPermissionsResult() 回调方法并传递 PERMISSION_DENIED,就像用户再次明确拒绝了您的请求时的处理方式一样。如果设备政策禁止应用具有该权限,该方法也会返回 false。这意味着,当您调用 requestPermissions() 时,您不能假定已经发生与用户的任何直接交互。
要在请求应用权限时提供最佳用户体验,另请参阅应用权限最佳做法。
按 API 级别声明权限
要仅在支持运行时权限的设备(即运行 Android 6.0(API 级别 23)或更高版本的设备)上声明某项权限,请添加 uses- permission-sdk-23 标记,而不是 uses-permission 标记。
使用这些标记中的任意一个时,您均可设置 maxSdkVersion 属性,以指定在运行更高版本的设备上不需要特定权限。
Android复习(四)权限—>请求应用权限的更多相关文章
- Xamarin Android权限请求
Xamarin Android权限请求 Android权限规定了App是否可以访问特定的资源,如网络.电话和短信.在原有API 6.0之前,App在安全的时候,会请求一次权限.一旦安装后,App就 ...
- android 学习十四 探索安全性和权限
1.部署安全性:应用程序必须使用数字证书才能安装到设备上. 2.执行期间的安全性: 2.1 使用独立进程 2.2 使用固定唯一用户ID 2.3 申明性权限模型 3数字证书 ...
- Android 6.0 权限请求
在申请权限之前一定要在清单配置文件中添加该权限private static final int MY_PERMISSIONS_REQUEST_RECORD_AUDIO = 1; //随便定义 publ ...
- android请求root权限
应用获取Root权限的原理:让应用的代码执行目录获取最高权限.在Linux中通过chmod 777 [代码执行目录] //请求root权限 public static boolean upgra ...
- 【朝花夕拾】Android安全之(一)权限篇
前言 从Android6.0开始,Android系统对权限的处理产生了很大的变化.如果APP运行的设备系统版本为Android6.0或更高,并且target在23或更高,那么danger ...
- 运行时权限请求框架easypermissions
前言 之前使用过AndPermission权限申请库,当开发者执行有权限的代码发生异常时,AndPermission会抓到异常并回调到失败中,这里要注意的是会抓到任何异常,不仅仅是没有权限时的异常. ...
- Android自定义权限和使用权限
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 自定义权限,主要用于保护被赋予权限的组件.如无权限与有权限,正如public与private的对类保 ...
- Android M新的运行时权限开发者需要知道的一切
android M 的名字官方刚发布不久,最终正式版即将来临!android在不断发展,最近的更新 M 非常不同,一些主要的变化例如运行时权限将有颠覆性影响.惊讶的是android社区鲜有谈论这事儿, ...
- Android 6.0的运行时权限
原文 http://droidyue.com/blog/2016/01/17/understanding-marshmallow-runtime-permission/ 主题 安卓开发 Andr ...
- Android 开发技巧 - Android 6.0 以上权限大坑和权限检查基类封装
简单介绍 关于运行时权限的说法,早在Google发布android 6.0的时候,大家也听得蛮多的.从用户的角度来讲,用户是受益方,更好的保护用户的意思,而对于开发者来说,无疑增加了工作量. 对于6. ...
随机推荐
- 【CentOS】rpm包安装Jdk
1.系统环境检查 前提情要:[如果是使用虚拟机的Linux系统,强烈建议先打个快照备份一下,以免操作失误无法重来] 首先查看系统是否存在java环境 java -version 因为点选了环境工具,这 ...
- 两个 RTX2070 super 显卡 可不可以通过 nvlink交换机 进行P2P通信 呢? (答案: 可以)
以前转载了一篇文章: https://www.cnblogs.com/devilmaycry812839668/p/12370685.html 对于里面的结果总感觉有所怀疑,于是斥巨资购入两个 ...
- oracle利用job实现存储过程异步执行
1.背景 在实际开发中,我们可能会利用存储过程批量处理业务, 对应有些存储过程可能会执行很长时间,这时我们需要客户端点操作后,存储过程异步执行 具体实现如下 1.创建处理业务的存储过程:sp_test ...
- [python] Python并行计算库Joblib使用指北
Joblib是用于高效并行计算的Python开源库,其提供了简单易用的内存映射和并行计算的工具,以将任务分发到多个工作进程中.Joblib库特别适合用于需要进行重复计算或大规模数据处理的任务.Jobl ...
- java增量发布工具
有些公司由于没有使用maven作为构建工具,全量发布时没问题,而修改bug增量发布往往是将改动的代码手动编译后,从classes目录下拷贝到jar中然后再放到tomcat目录下发布,这种方法准确度不高 ...
- mmdetection使用未定义backbone训练
首先找到你需要用到的 backbone,一般有名的backbone 都会在github有相应的代码开源和预训练权重提供 本文以mobilenetv3 + fastercnn 作为举例,在mmdetec ...
- NYX靶机笔记
NYX靶机笔记 概述 VulnHub里的简单靶机 靶机地址:https://download.vulnhub.com/nyx/nyxvm.zip 1.nmap扫描 1)主机发现 # -sn 只做pin ...
- B 端产品未来几年的发展趋势
在当今数字化高速发展的时代,B 端产品经理作为企业数字化转型的关键推动者,肩负着重大的责任.不仅要深入了解企业的业务需求,还要紧跟技术发展的步伐,为企业提供高效.创新的解决方案.那么,未来几年,B 端 ...
- 深入理解Argo CD工作原理
1. ArgoCD 的架构 ArgoCD 是一个 Kubernetes 原生的持续交付工具,它通过监控 Git 仓库中的应用定义来自动部署应用到 Kubernetes 集群.其核心架构由以下几个关键组 ...
- C++17新特性探索:拥抱std::optional,让代码更优雅、更安全
std::optional 背景 在编程时,我们经常会遇到可能会返回/传递/使用一个确定类型对象的场景.也就是说,这个对象可能有一个确定类型的值也可能没有任何值.因此,我们需要一种方法来模拟类似指针的 ...