首页 > 其他分享 >运行时权限

运行时权限

时间:2024-06-02 15:12:29浏览次数:19  
标签:permission image 用户 应用 权限 运行

运行时权限

https://developer.android.google.cn/guide/topics/permissions/overview#runtime

运行时权限不是新特性,但其具体流程还未细看过,这里大致走读下相关流程梳理下相关逻辑

要了解运行时权限最好先看下上面开发者网站上的介绍

在早期的时候,一般应用需要什么权限,只需要在AndroidManifest.xml中进行声明就行了,这里以读取外部存储权限为例:

image-20210915221106057

image-20210915221106057

以前的外部存储读取权限声明:

image-20210915221452179

image-20210915221452179

但后来该权限的级别变了

image-20210915221539087

image-20210915221539087

明显的,其protectionLevel从normal变为了dangerous,一般权限的级别为dangerous的就是运行时权限,对于运行时权限,若需要该权限,一般的应用只在AndroidManifest.xml中声明需要该权限在安装后是默认不会有该权限的,还需要代码申请权限(requestPermissions),然后会有弹框,用户选择允许后才会拥有该权限:

image-20210915222930197

image-20210915222930197

而如果拒绝后,再次调用代码申请权限,则会再次弹框:

image-20210915223410814

image-20210915223410814

这时,如果选择允许,则应用拥有该权限,如果选择“拒绝,不要再询问”,则应用无该权限,且再次调用代码申请该权限时不会弹框

开发者网站上推荐的申请运行时权限的流程(https://developer.android.google.cn/training/permissions/requesting)如下:

  1. 在应用的清单文件中,声明应用可能需要请求的权限
  2. 设计应用的用户体验,使应用中的特定操作与特定运行时权限相关联。应当让用户知道哪些操作可能会要求他们向您的应用授予访问其私人数据的权限。
  3. 等待用户调用应用中需要访问特定用户私人数据的任务或操作。届时,您的应用可以请求访问相应数据所需的运行时权限。
  4. 检查用户是否已授予应用所需的运行时权限。如果已授权,那么您的应用可以访问用户私人数据。如果没有,请继续执行下一步。
  • 每次执行需要该权限的操作时,您都必须检查自己是否具有该权限。
  1. 检查您的应用是否应向用户显示理由,说明您的应用需要用户授予特定运行时权限的原因。如果系统确定您的应用不应显示理由,请继续直接执行下一步,无需显示界面元素。
  • 不过,如果系统确定您的应用应该显示一个理由,请在界面元素中向用户显示理由,明确说明您的应用试图访问哪些数据,以及应用获得运行时权限后可为用户提供哪些好处。用户确认理由后,请继续执行下一步。
  1. 请求您的应用访问用户私人数据所需的运行时权限。系统会显示运行时权限提示,例如权限概览页面上显示的提示。
  2. 检查用户的响应,他们可能会选择同意或拒绝授予运行时权限。
  3. 如果用户向您的应用授予权限,您就可以访问用户私人数据。如果用户拒绝授予该权限,请适当降低应用体验,使应用在未获得受该权限保护的信息时也能向用户提供功能。

其中申请运行时权限可仿照如下代码

if (ContextCompat.checkSelfPermission(
CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
PackageManager.PERMISSION_GRANTED) {
// You can use the API that requires the permission.
performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...);
} else {
// You can directly ask for the permission.
requestPermissions(CONTEXT,
new String[] { Manifest.permission.REQUESTED_PERMISSION },
REQUEST_CODE);
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission is granted. Continue the action or workflow
// in your app.
} else {
// Explain to the user that the feature is unavailable because
// the features requires a permission that the user has denied.
// At the same time, respect the user's decision. Don't link to
// system settings in an effort to convince the user to change
// their decision.
}
return;
}
// Other 'case' lines to check for other
// permissions this app might request.
}
}

也可参考下代码工程samples中的RuntimePermissions

其中主要代码有

1、checkSelfPermission鉴权

2、shouldShowRequestPermissionRationale是否应该显示申请权限的理由(结合示例代码和逻辑,旨在其返回true时应用能显示具体的权限的用处)

3、requestPermissions申请权限

1、Activity.shouldShowRequestPermissionRationale

image-20210915223744044

image-20210915223744044

显然,Activity的shouldShowRequestPermissionRationale方法调用的是packageManager的,这里getPackageManager获取的是ApplicationPackageManager的对象,查看ApplicationPackageManager的shouldShowRequestPermissionRationale方法:

image-20210915224030937

image-20210915224030937

显然这里会调用到PackageManagerService的shouldShowRequestPermissionRationale方法

image-20210915224401907

image-20210915224401907

image-20210915224517757

image-20210915224517757

这里既是该方法的主要逻辑部分,其主要部分有:

1、如果已经有对应权限,则shouldShowRequestPermissionRationale返回false

2、如果对应permission的flags包含fixedFlags,则返回false(这里对于一般应用如在申请权限时用户选择了“拒绝,不要再询问”后,则属于该场景)

3、如果对应permission的flags包含FLAG_PERMISSION_USER_SET则返回true(这里一般对于应用在申请权限时用户选择了拒绝(不是“拒绝,不要再询问”)后,再次申请权限时的场景),否则返回flase

1.1、申请权限用户选择与flags变化

这里仍以外部存储读取权限为例(android.permission.READ_EXTERNAL_STORAGE)(这里使用adb shell dumpsys package命令获取对应应用的信息,如果手机root了,可以直接查看/data/system/users/0/runtime-permissions.xml文件进行查看):

1、应用刚安装时:

image-20210915225605621

image-20210915225605621

2、代码申请权限后弹框,用户选择拒绝后(在之后如再次申请权限弹框,仍选择拒绝后,其flags仍是下面的不变)(显然,相对于刚安装时,多了USER_SET的flag):

image-20210915225826560

image-20210915225826560

3、代码权限申请后弹框,用户选择“拒绝,不要再询问”后(显然,相对于刚安装时,多了USER_FIXED的flag):

image-20210915230209348

image-20210915230209348

4、如果在有弹框的时候,用户选择允许后(granted变为了true):

image-20210915230742936

image-20210915230742936

2、Activity.requestPermissions

image-20210915232730639

image-20210915232730639

从上述代码可以看到,其实Activity.requestPermissions的主要逻辑即是启动了一个Activity,这里PackageManager.buildRequestPermissionsIntent逻辑如下

image-20210915232840189

image-20210915232840189

其实这里启动的是PermissionController应用的GrantPermissionsActivity

image-20210915233326976

image-20210915233326976

这里简要摘取些代码片段介绍下大致流程

在GrantPermissionsActivity的onCreate方法中设置显示布局:

image-20210915233528665

image-20210915233528665

其中mViewHandler是GrantPermissionsViewHandlerImpl的对象

image-20210915233619193

image-20210915233619193

查看其createView方法:

image-20210915233752223

image-20210915233752223

查看下其点击允许按钮(mAllowButton)的大致逻辑,查看GrantPermissionsViewHandlerImpl中onClick逻辑:

image-20210915233918597

image-20210915233918597

显然,在点击允许的时候,其主要是回调GrantPermissionsActivity的onPermissionGrantResult方法:

image-20210915234116407

image-20210915234116407

继续查看GrantPermissionsActivity的onPermissionGrantResultSingleState方法

image-20210915234210324

image-20210915234210324

这里选择允许时,主要逻辑是调用上面groupState.mGroup.grantRuntimePermissions方法,其中mGroup是AppPermissionGroup对象

在AppPermissionGroup的grantRuntimePermissions中会先对对应权限持有的permission对象进行对应的赋值,然后其会调用persistChanges方法进行权限的处理,如赋予权限、更新flags等

image-20210915234647841

image-20210915234647841

另外在用户选择了“拒绝,不要再询问”后,再次调用requestPermissions方法时,仍是去启动上面GrantPermissionsActivity,只是在其onCreate方法中会调用setResultAndFinish方法退出,所以看起来没有反应

image-20210915234927744

image-20210915234927744

标签:permission,image,用户,应用,权限,运行
From: https://www.cnblogs.com/luoliang13/p/18227126

相关文章

  • 开源代码分享(32)-基于改进多目标灰狼算法的冷热电联供型微电网运行优化
    参考文献:[1]戚艳,尚学军,聂靖宇,等.基于改进多目标灰狼算法的冷热电联供型微电网运行优化[J].电测与仪表,2022,59(06):12-19+52.DOI:10.19753/j.issn1001-1390.2022.06.002.1.问题背景        针对冷热电联供型微电网运行调度的优化问题,为实现节能减排的目标,以微电......
  • 为什么GD32F303代码运行在flash比sram更快?
    我们知道一般MCU的flash有等待周期,随主频提升需要插入flash读取的等待周期,以stm32f103为例,主频在72M时需要插入2个等待周期,故而代码效率无法达到最大时钟频率。所以STM32F103将代码加载到sram运行速度更快。但使用GD32F303时将代码加载到SRAM后速度反而下降了一些,这是为什么......
  • MySQL 权限详解
    All/AllPrivileges权限代表全局或者全数据库对象级别的所有权限Alter权限代表允许修改表结构的权限,但必须要求有create和insert权限配合。如果是rename表名,则要求有alter和drop原表,create和insert新表的权限Alterroutine权限代表允许修改或者删除存储过程、函数的权限Create......
  • vmicres.dll文件丢失导致程序无法运行问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个vmicres.dll文件(挑选合适的版本文件)把它放......
  • vdsutil.dll文件丢失导致程序无法运行问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个vdsutil.dll文件(挑选合适的版本文件)把它放......
  • 2.2 Go运行时(runtime)
    2.2.1Go运行时(runtime)尽管Go编译器产生的是本地可执行代码,这些代码仍旧运行在Go的runtime(这部分的代码可以在runtime包中找到)当中。这个runtime类似Java和.NET语言所用到的虚拟机,它负责管理包括内存分配、垃圾回收(第10.8节)、栈处理、goroutine、channel、切片(sli......
  • 红米AX6000 Openwrt FIP 没权限 Can't open device for writing!
     ......
  • B端系统:角色与权限界面设计,一文读懂。
    一、什么是角色与权限系统角色与权限系统是一种用于管理和控制用户在系统中的访问和操作权限的机制。它通过将用户分配到不同的角色,并为每个角色分配相应的权限,来实现对系统资源的权限控制和管理。在角色与权限系统中,通常会定义多个角色,每个角色代表一组用户,具有相似的权......
  • 权限管理,鸿蒙Next版
      一、应用权限概述注意事项在鸿蒙开发中,调用部分API时需要申请权限后,才能调用,如:网络请求,获取网络信息等。部分API权限调用的时候还会弹窗,如:麦克风、位置、摄像头、相册、传感器(sensor)、日历等。申请应用权限时,需要注意两个关键信息:权限级别授权方式权限文档截图......
  • YOLOv8改进 | 卷积模块 | 添加选择性内核SKConv【附完整代码一键运行】
    ......