在之前关于应用内数据本地保存为文件时,曾提到应用需要申请外部存储设备的读写权限才能访问外部存储中的文件。那么针对某一种权限,应用程序具体应该怎么申请使用呢?本文将详细介绍。

应用中的权限主要分为两类,分为正常权限和危险权限。在Android6.0即API 23之前,这两种权限均只需要在清单文件中声明即可,自Android6.0即API 23开始,危险权限不仅需要在清单文件中声明,还需要在代码使用该权限的界面Activity中动态申请,弹出权限申请框,由用户决定是否授权。应用所需要的权限列表及授权结果,可以从系统设置-应用管理-权限管理中查看。

这里对权限的分类与官网权限分类有所差异,为了便于理解,将官网的权限等级与本文中的权限分类对照关系绘制下表。

权限等级ProtectionLevel 本文权限分类
normal 正常权限
signature 正常权限
dangerous 危险权限
appop 正常权限

权限的相关设置,大多是在清单文件中配置的,只有在动态申请或增加附加权限与四大组件交互时需要在代码中配置。

如果应用程序如果需要使用某种权限,就必须在其清单文件中声明这些权限。

在清单文件中使用标签<uses-permission />,并为其属性android:name赋值,不同的权限分别定义了对应的字符串值。这些不同的权限可以从android.Manifest.permission权限类中查看。

从Android6.0即API 23开始,危险权限需要动态申请,并由用户主动授权后,才能继续执行获得授权后的操作,否则在未经授权时执行相关操作,程序运行时会抛出java.lang.SecurityException异常。

动态申请的权限,同样需要借助Context上下文环境对象来完成授权的相关操作。同时由于Android系统库的升级,下面涉及到的相关类,可以在老的系统支持库android.support.v4中找到,同样也可以在新版的androidx.core支持库中找到对应类。

动态申请权限,主要分为三个步骤,检查、请求、结果回调。

检查主要针对两个方向,一是检查应用程序是否已获得相关权限。调用ContextCompat.checkSelfPermission(Context context, String permission)静态方法,将上下文环境对象和相关权限的固定字符串分别作为参数传入即可。返回int类型的结果标注是否授权,其数值在android.content.pm.PackageManager类中以静态常量的形式分别定义了已授权的PERMISSION_GRANTED=0和未授权的PERMISSION_DENIED=-1

如果检查权限结果是已授权,那么可以执行获得该权限的后续操作。而当结果是未授权时,需要继续检查当前权限是否可向用户展示请求授权界面。调用ActivityCompat.shouldShowRequestPermissionRationale(android.app.Activity, java.lang.String)静态方法,参数activity是当前所在Activity界面对象,参数permission是相关权限字符串常量。返回boolean类型的结果,表示是否可正常展示请求授权界面。

如果检查展示请求授权界面结果失败,则需要提示用户相关权限无法正常授权,通常会提示用户可以到系统设置-权限管理中将该应用程序的相关权限打开,以正常执行应用程序获得授权后的操作。而当检查展示界面返回结果是true时,可以继续请求该权限。调用ActivityCompat.requestPermissions(Activity activity, String[] permissions, int requestCode)静态方法,参数activity是当前所在Activity界面对象,参数permissions是多个权限字符串组成的数组,参数requestCode是当前请求值,可任意定义,同时该值与请求结果返回时对应一致。

这里注意,在请求权限时必须要传入Activity界面对象,也就是说要想请求权限,必须通过应用程序的某个已处于正常运行状态的可视界面。而所谓的请求权限,与界面之间的互相启动有些相似,其本质都是一样的。

最后是请求结果的回调,在请求权限的Activity界面中,重写方法public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){}。在用户选择同意授权或拒绝授权后,由系统回调该方法。其中参数requestCode是请求值,与请求权限时的参数一致;参数permissions是相关的权限数组,同样与请求权限时的参数一致;参数grantResults是用户的授权结果,其数组索引与参数permissions中的索引一一对应,取值同样有表示已授权的PERMISSION_GRANTED=0和未授权的PERMISSION_DENIED=-1

在请求结果返回的所有权限均已授权后,边可以执行获得相关权限的后续操作。如果有未授权的权限,通常是执行异常操作,例如给用户相应提示并不再执行正常的后续操作。

另外,在检查权限相关操作返回如果某项权限在之前由用户选择拒绝授权并不再提示,


应用程序中对权限的使用方式在Android12之前可参考上述方式。那么具体系统提供了哪些权限,获得这些权限后可以做什么操作,这些问题将在后面的文章中介绍。

Android系统编程入门系列之应用权限的定义与申请的更多相关文章

  1. Android系统编程入门系列之加载界面Activity

    上回说到应用初始化加载及其生命周期,在Android系统调用Applicaiton.onCreate()之后,继续创建并加载清单文件中注册的首个界面即主Activity,也可称之为入口界面.主Acti ...

  2. Android系统编程入门系列之应用环境及开发环境介绍

        作为移动端操作系统,目前最新的Android 11.0已经发展的比较完善了,现在也到了系统的整理一番的时间,接下来的系列文章将以Android开发者为中心,争取用归纳总结的态度对初级入门者所应 ...

  3. Android系统编程入门系列之应用数据文件化保存

    应用中关于数据的持久化保存,不管是简单的SharedPreferences还是数据库SQLiteDatabase,本质上都是将数据保存到系统的某种类型的文件中.因此可以直接使用java.io.File ...

  4. Android系统编程入门系列之硬件交互——传感器

    到目前为止,关于应用程序与用户之间的相关内容便比较肤浅的大致介绍完毕.而在整个系统架构中,应用程序与用户之间的交互,犹如参天大树上的枝干和树叶,交互起来五彩缤纷,但使整个生态系统保持生命力的核心,在于 ...

  5. Android系统编程入门系列之硬件交互——通信硬件Bluetooth

    通信硬件NFC的文章,虽然可以在Android系统中通过非直接接触的形式与支持NFC硬件的设备通信,但是也只能交互一些简短的标签内容,对大量的持续性数据,却并不能很好的支持.因此针对这个弊端,可以考虑 ...

  6. Android系统编程入门系列之硬件交互——无线通信WLAN

    Android系统的移动设备大多支持无线WLAN技术.利用该技术,不仅能实现互联网通信,还能实现无线定位,热点共享等远程通信功能.针对使用WLAN的不同功能,可能需要分别申请不同的权限声明,同时调用不 ...

  7. Android系统编程入门系列之清单文件

    在上一篇文章中已经提到,Android系统加载应用程序之后,首先会读取该应用程序的AndroidManifest.xml清单文件,之后根据该清单文件加载后边的东西.所以要开发应用程序,自然要先知道清单 ...

  8. Android系统编程入门系列之界面Activity绘制展示

    上篇文章介绍了界面Activity的启动方式和生命周期,本篇将继续介绍在界面Activity中的内容是如何绘制展示给用户的. 在Android系统上运行新创建的界面Activtiy,给用户展示的是空白 ...

  9. Android系统编程入门系列之界面Activity交互响应

    在上篇文章中已经了解到界面Activity的绘制完全依赖其加载的视图组件View,不仅如此,用户的每次触摸操作都可以在界面Activity内接收并响应,也可以直接传递给其中的某个视图View响应.本文 ...

随机推荐

  1. 【odoo】【知识杂谈】单一实例多库模式下定时任务的问题分析

    欢迎转载,但需标注出处,谢谢! 背景: 有客户反应有个别模块下的定时任务没有正常执行,是否是新装的模块哪些有问题?排查后发现,客户是在一台服务器上跑着一个odoo容器,对应多个数据库.个别库的定时任务 ...

  2. Pytest系列(15)- 多重校验插件之pytest-assume的详细使用

    如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 pytest中可以用pyth ...

  3. junit4 套件测试

    junit4 中的套件可以用来测试一个需要依赖的业务流程,如购买必须依赖与登录成功 代码实现: 测试数据存放 public class BaseTest { protected static Hash ...

  4. java中各个类相互调用资源的原理

       当我们要进行跨类的调用/使用的时候,比如当前类调用另一个类中的变量或方法时, 这时需要一定的条件,如果那些将要被调用的变量或方法是static(静态)变量,也叫类变 量,那么可以通过类名调用,相 ...

  5. 概述 .NET 6 ThreadPool 实现

    目录 前言 任务的调度 基本调度单元 IThreadPoolWorkItem 实现类的实例. Task 全局队列 本地队列 偷窃机制 Worker Thread 的生命周期管理 线程生命注入实验 .N ...

  6. 数据库删除discuz 部分数据操作

    如何快速清理discuz 3.2 中等待审核的回复数:pre_forum_post_moderate,点击清空 清空回收站的主题帖:DELETE FROM `pre_forum_thread` WHE ...

  7. Jmeter系列(27)- 常用逻辑控制器(6) | 如果(if)控制器If Controller

    如果(if)控制器(If Controller) 在实际工作中,当使用JMeter做性能脚本或者接口脚本时,当遇到需要对不同的条件做不同的操作时,我们可以使用JMeter中if控制器来实现 if控制器 ...

  8. shell 基本语法介绍

    一.介绍 shell 是属于弱类型语言,指的是在定义变量时不需要指定变量的类型,就如python也是弱类型语言.一般以: :.sh结尾的文件 :文件第一行固定为:#!/bin/bash,表示指定以sh ...

  9. Python - Context Manager 上下文管理器

    什么是上下文管理器 官方解释... 上下文管理器是一个对象 它定义了在执行 with 语句时要建立的运行时上下文 上下文管理器处理进入和退出所需的运行时上下文以执行代码块 上下文管理器通常使用 wit ...

  10. str.strip(chars)

    strip会去除给定字符串的指定字符,指定字符可以是一个或多个,去除从左右分别进行,没有则忽略,如果需要去除某个中间的字符,必须先去除外围的字符 看几个例子,以s为例,故意设置为非对称结构, s = ...