Android运行时权限详解

news2024/11/14 22:48:27

文章目录

  • Android运行时权限详解
    • Android权限机制详解
    • 在程序运行时申请权限

Android运行时权限详解

Android的权限机制并不是什么新鲜事物,从系统的第一个版本开始就已经存在了。但其实之前Android的权限机制在保护用户安全和隐私等方面起到的作用比较有限,尤其是一些大家都离不开的常用软件,非常容易“店大欺客”。为此,Android开发团队在Android 6.0系统中引用了运行时权限这个功能,从而更好地保护了用户的安全和隐私,那么本节我们就来详细学习一下这个6.0系统中引入的新特性。

Android权限机制详解

首先来回顾一下过去Android的权限机制是什么样的。我们在第5章写BroadcastTest项目的时候第一次接触了Android权限相关的内容,当时为了要访问系统的网络状态以及监听开机广播,于是在AndroidManifest.xml文件中添加了这样两句权限声明:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
</manifest>

因为访问系统的网络状态以及监听开机广播涉及了用户设备的安全性,因此必须在AndroidManifest.xml中加入权限声明,否则我们的程序就会崩溃。

那么现在问题来了,加入了这两句权限声明后,对于用户来说到底有什么影响呢?为什么这样就可以保护用户设备的安全性了呢?

其实用户主要在以下两个方面得到了保护,一方面,如果用户在低于6.0系统的设备上安装该程序,会在安装界面给出提醒。这样用户就可以清楚地知晓该程序一共申请了哪些权限,从而决定是否要安装这个程序。如图所示:

在这里插入图片描述

另一方面,用户可以随时在应用程序管理界面查看任意一个程序的权限申请情况。这样该程序申请的所有权限就尽收眼底,什么都瞒不过用户的眼睛,以此保证应用程序不会出现各种滥用权限的情况。如图所示:

在这里插入图片描述

这种权限机制的设计思路其实非常简单,就是用户如果认可你所申请的权限,那么就会安装你的程序,如果不认可你所申请的权限,那么拒绝安装就可以了。

但是理想是美好的,现实却很残酷,因为很多我们所离不开的常用软件普遍存在着滥用权限的情况,不管到底用不用得到,反正先把权限申请了再说。比如说微信所申请的权限列表如图所示:

在这里插入图片描述

这只是微信所申请的一半左右的权限,因为权限太多一屏截不下来。其中有一些权限我并不认可,比如微信为什么要读取我手机的短信和彩信?但是我不认可又能怎样,难道我拒绝安装微信?没错,这种例子比比皆是,当一些软件已经让我们产生依赖的时候就会容易 “店大欺客”,

反正这个权限我就是要了,你自己看着办吧!

Android开发团队当然也意识到了这个问题,于是在6.0系统中加入了运行时权限功能。也就是说,用户不需要在安装软件的时候一次性授权所有申请的权限,而是可以在软件的使用过程中再对某一项权限申请进行授权。比如说一款相机应用在运行时申请了地理位置定位权限,就算我拒绝了这个权限,但是我应该仍然可以使用这个应用的其他功能,而不是像之前那样直接无法安装它。

当然,并不是所有权限都需要在运行时申请,对于用户来说,不停地授权也很烦琐。Android现在将所有的权限归成了两类,一类是普通权限,一类是危险权限。准确地讲,其实还有第三类特殊权限,不过这种权限使用得很少,因此不在本书的讨论范围之内。普通权限指的是那些不会直接威胁到用户的安全和隐私的权限,对于这部分权限申请,系统会自动帮我们进行授权,而不需要用户再去手动操作了,比如在BroadcastTest项目中申请的两个权限就是普通权限。危险权限则表示那些可能会触及用户隐私或者对设备安全性造成影响的权限,如获取设备联系人信息、定位设备的地理位置等,对于这部分权限申请,必须要由用户手动点击授权才可以,否则程序就无法使用相应的功能。但是Android中有一共有上百种权限,我们怎么从中区分哪些是普通权限,哪些是危险权限呢?

其实并没有那么难,因为危险权限总共就那么几个,除了危险权限之外,剩余的就都是普通权限了。下表列出了Android中所有的危险权限,一共是9组24个权限。

在这里插入图片描述

这张表格你看起来可能并不会那么轻松,因为里面的权限全都是你没使用过的。不过没有关系,你并不需要了解表格中每个权限的作用,只要把它当成一个参照表来查看就行了。每当要使用一个权限时,可以先到这张表中来查一下,如果是属于这张表中的权限,那么就需要进行运行时权限处理,如果不在这张表中,那么只需要在AndroidManifest.xml文件中添加一下权限声明就可以了。

另外注意一下,表格中每个危险权限都属于一个权限组,我们在进行运行时权限处理时使用的是权限名,但是用户一旦同意授权了,那么该权限所对应的权限组中所有的其他权限也会同时被授权。

在程序运行时申请权限

首先新建一个RuntimePermissionTest项目,我们就在这个项目的基础上来学习运行时权限的使用方法。在开始动手之前还需要考虑一下到底要申请什么权限,其实刚才表中列出的所有权限都是可以申请的,这里简单起见我们就使用CALL_PHONE这个权限来作为本小节中的示例吧。

CALL_PHONE这个权限是编写拨打电话功能的时候需要声明的,因为拨打电话会涉及用户手机的资费问题,因而被列为了危险权限。在Android 6.0系统出现之前,拨打电话功能的实现其实非常简单,修改activity_main.xml布局文件,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/make_call"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Make Call" />
</LinearLayout>

我们在布局文件中只是定义了一个按钮,当点击按钮时就去触发拨打电话的逻辑。接着修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button makeCall = (Button) findViewById(R.id.make_call);
makeCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
} catch (SecurityException e) {
e.printStackTrace();
}
}
});
}
}

可以看到,在按钮的点击事件中,我们构建了一个隐式Intent,Intent的action指定为Intent.ACTION_CALL,这是一个系统内置的打电话的动作,然后在data部分指定了协议是tel,号码是10086。其实这部分代码我们在2.3.3小节中就已经见过了,只不过当时指定的action是Intent.ACTION_DIAL,表示打开拨号界面,这个是不需要声明权限的,

而Intent.ACTION_CALL则可以直接拨打电话,因此必须声明权限。另外为了防止程序崩溃,我们将所有操作都放在了异常捕获代码块当中。

那么接下来修改AndroidManifest.xml文件,在其中声明如下权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.runtimepermissiontest">
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
</application>
</manifest>

这样我们就将拨打电话的功能成功实现了,并且在低于Android 6.0系统的手机上都是可以正常运行的,但是如果我们在6.0或者更高版本系统的手机上运行,点击Make Call按钮就没有任何效果,这时观察logcat中的打印日志,你会看到如图所示的错误信息:

在这里插入图片描述

错误信息中提醒我们“Permission Denial”,可以看出,是由于权限被禁止所导致的,因为6.0及以上系统在使用危险权限时都必须进行运行时权限处理。

那么下面我们就来尝试修复这个问题,修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button makeCall = (Button) findViewById(R.id.make_call);
makeCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.
permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new
String[]{ Manifest.permission.CALL_PHONE }, 1);
} else {
call();
}
}
});
}
private void call() {
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
} catch (SecurityException e) {
e.printStackTrace();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.
PERMISSION_GRANTED) {
call();
} else {
Toast.makeText(this, "You denied the permission", Toast.LENGTH_
SHORT).show();
}
break;
default:
}
}
}

上面的代码将运行时权限的完整流程都覆盖了,下面我们来具体解析一下。说白了,运行时权限的核心就是在程序运行过程中由用户授权我们去执行某些危险操作,程序是不可以擅自做主去执行这些危险操作的。因此,第一步就是要先判断用户是不是已经给过我们授权了,借助的是ContextCompat.checkSelfPermission()方法。checkSelfPermission()方法接收两个参数,第一个参数是Context,这个没什么好说的,第二个参数是具体的权限名,比如打电话的权限名就是Manifest.permission.CALL_PHONE,然后我们使用方法的返回值和PackageManager.PERMISSION_GRANTED做比较,相等就说明用户已经授权,不等就表示用户没有授权。

如果已经授权的话就简单了,直接去执行拨打电话的逻辑操作就可以了,这里我们把拨打电话的逻辑封装到了call()方法当中。如果没有授权的话,则需要调用ActivityCompat.requestPermissions()方法来向用户申请授权,requestPermissions()方法接收3个参数,第一个参数要求是Activity的实例,第二个参数是一个String数组,我们把要申请的权限名放在数组中即可,第三个参数是请求码,只要是唯一值就可以了,这里传入了1。

调用完了requestPermissions()方法之后,系统会弹出一个权限申请的对话框,然后用户可以选择同意或拒绝我们的权限申请,不论是哪种结果,最终都会回调到onRequestPermissionsResult()方法中,而授权的结果则会封装在grantResults参数当中。这里我们只需要判断一下最后的授权结果,如果用户同意的话就调用call()方法来拨打电话,如果用户拒绝的话我们只能放弃操作,并且弹出一条失败提示。

现在重新运行一下程序,并点击Make Call按钮,效果如图所示:

在这里插入图片描述

由于用户还没有授权过我们拨打电话权限,因此第一次运行会弹出这样一个权限申请的对话框,用户可以选择同意或者拒绝,比如说这里点击了DENY,结果如图所示:

在这里插入图片描述

由于用户没有同意授权,我们只能弹出一个操作失败的提示。下面我们再次点击Make Call按钮,仍然会弹出权限申请的对话框,这次点击ALLOW,结果如图所示:

在这里插入图片描述

可以看到,这次我们就成功进入到拨打电话界面了,并且由于用户已经完成了授权操作,之后再点击Make Call按钮就不会再弹出权限申请对话框了,而是可以直接拨打电话。那可能你会担心,万一以后我又后悔了怎么办?没有关系,用户随时都可以将授予程序的危险权限进行关闭,进入Settings → Apps → RuntimePermissionTest → Permissions,界面如图所示:

在这里插入图片描述

在这里我们就可以对任何授予过的危险权限进行关闭了。好了,关于运行时权限的内容就讲到这里,现在你已经有能力处理Android上各种关于权限的问题了。

如果对你有帮助,就一键三连呗(点赞+收藏+关注),我会持续更新更多干货~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2097497.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用OSINT追踪勒索组织活动

0X00前言 众所周知&#xff0c;勒索组织一直是臭名昭著的代名词。在当今网络世界上时时刻刻都存在着勒索软件的身影。正所谓&#xff0c;不知攻&#xff0c;焉知防。我们可以更据OSINT的方法&#xff0c;去追踪分析各大勒索组织的活动&#xff0c;以及状态。为应对可能的勒索攻…

【Python基础】元组类型

本文收录于 《Python编程入门》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程基础知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、Python 元组2.1 创建特殊元组2.2 访问元组2.3 删除元组2.4 元组截取2.5 元组运算符2.6 元组内置函…

佰朔资本:9月券商金股出炉,这类股获机构力推

现在&#xff0c;券商新一批月度金股近期连续出炉。到9月1日&#xff0c;14家券商发布9月月度金股&#xff0c;举荐的104只金股会集分布在电子、机械设备、传媒、汽车等工作中。从个股来看&#xff0c;比亚迪、我国安全、阳光电源获2家以上券商共同举荐。别的&#xff0c;北方华…

30 静态路由

静态路由 一、配置静态路由 &#xff08;一&#xff09;静态路由特点 ​ 主要特点&#xff1a; ​ 由管理员手工配置&#xff0c;为单向条目通信双方的边缘路由器都需要指定&#xff0c;否则会导致数据包有去无回 &#xff08;二&#xff09;静态路由配置 ​ 使用ip rout…

开学季儿童护眼台灯怎么选择?盘点央视公布十大护眼灯!

随着年级的升高和学习内容的增加&#xff0c;学生的休闲娱乐时间逐渐减少&#xff0c;相反&#xff0c;他们在书桌前度过的时间却越来越多。近年来&#xff0c;由于电子产品的广泛使用&#xff0c;我国青少年的用眼负担显著增加。据权威机构预测&#xff0c;到2050年&#xff0…

ActiViz实战:使用vtkDistanceWidget实现两点测距功能

文章目录 一、效果图预览二、实现步骤三、C#完整实例代码一、效果图预览 二、实现步骤 1、通过vtkCellPicker拾取点坐标 2、通过vtkDistanceRepresentation2D设置起始点和结束点位置 3、通过vtkDistanceRepresentation2D的GetAxis()获取vtkAxisActor2D对象,并设置连线的样式 …

前端安全:如何防范跨站脚本攻击(XSS)

聚沙成塔每天进步一点点 本文回顾 ⭐ 专栏简介前端安全&#xff1a;如何防范跨站脚本攻击 (XSS)1. 引言2. 什么是跨站脚本攻击 (XSS)&#xff1f;2.1 XSS的分类 3. XSS攻击的危害4. XSS的常见攻击手法4.1 注入恶意脚本4.2 伪造表单和链接4.3 操纵DOM结构 5. 如何防范XSS攻击5.1…

Git使用(命令+idea快捷)

目录 一、概述 1.什么是Git 2.Git能干什么 3.简介 4.下载和安装 二、Git代码托管服务 1.常用的Git代码托管服务 2.使用码云代码托管服务 三、Git全局设置&#xff08;常用命令&#xff09; 1.命令 2.实现 四、获取Git仓库&#xff08;常用命令&#xff09; 1.两种方…

基于 cuda sdk 12.4.1安装cudnn8.9.7 步骤备忘——与cudnn9有差别

cuda环境崩了&#xff0c;运行 nvidia-smi后无法 连接 drvier&#xff0c;重装了 cuda 12.4.1 cudnn 8.9.7 因为看到pytorch daily 代码目前是支持 12.4的。发现 cudnn8 与 nv官网提供的cudnn9的安装时在文字上稍微有些差别&#xff0c; 主要是 cudnn8: sudo apt-get -y i…

水凝胶支架进行4D生化光定制?有啥用?快来看看!

大家好&#xff0c;今天我们来了解一项关于水凝胶支架的技术——4D生化光定制——《4D Biochemical Photocustomization of Hydrogel Scaffolds for Biomimetic Tissue Engineering》发表于《Accounts of Materials Research》。随着科技的发展&#xff0c;人们对组织工程和生物…

【C++】C++STL 揭秘:Strng背后的底层逻辑

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用 在上篇介绍string类的使用与理解&#xff0c;本篇将为大家来带关于string的底层实现逻辑&…

「SpEL Validator」使用指南(一套无敌的参数校验组件)

前言 这是一套全新的参数校验组件&#xff0c;并非造轮子。 看完本文你可能会觉得用不上或不屑于使用&#xff0c;但这玩意确实有应用场景&#xff0c;你不妨稍微留意一下&#xff0c;日后你总会发现有用得上的时候。 此乃系列文章&#xff0c;当前为第②篇&#xff0c;其他…

Puppeteer的高级用法:如何在Node.js中实现复杂的Web Scraping

概述 随着互联网的发展&#xff0c;网页数据抓取&#xff08;Web Scraping&#xff09;已成为数据分析和市场调研的重要手段之一。Puppeteer作为一款强大的无头浏览器自动化工具&#xff0c;能够在Node.js环境中模拟用户行为&#xff0c;从而高效地抓取网页数据。然而&#xf…

Java基于微信小程序的实习管理系统

简介 本次开发的实习生管理系统实现了字典管理、公告管理、公司管理、简历管理、老师管理、实习管理、实习日志管理、通知管理、学生管理、职位招聘管理、职位收藏管理、职位留言管理、简历投递管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库&am…

点云配准之ICP和NDT算法的高斯牛顿法求解

ICP算法 NDT算法 代码&#xff1a;https://github.com/taifyang/pointcloud-registration 参考&#xff1a;高翔《自动驾驶与机器人中的SLAM技术》

打造灵动空间,流动会场的声学优势—轻空间

在现代社会中&#xff0c;各类会议、展览、演出、培训等活动越来越多&#xff0c;对场地的需求也越来越多样化。传统的固定场地往往难以满足不同活动的需求&#xff0c;而“流动会场”凭借其灵活多变的特点&#xff0c;迅速成为各类活动的新宠。特别是其独特的声学优势&#xf…

【数据结构】二叉树的链式结构,二叉树的遍历,求节点个数以及高度

目录 1. 二叉树链式结构的概念 2. 二叉树的遍历 2.1 前序遍历 2.2 中序遍历 2.3 后序遍历 2.4 层序遍历 3. 二叉树的节点个数以及高度 3.1 二叉树节点个数 3.2 二叉树叶子节点个数 3.3 二叉树的高度 3.4 二叉树第k层节点个数 3.5 二叉树查找值为x的节点 4. 二叉树…

数造科技荣登“科创杯”领奖台,开启数据驱动新篇章!

8月27日&#xff0c;第十三届中国创新创业大赛(海南赛区)暨海南省第十届“科创杯”创新创业大赛决赛在海口圆满落幕。数造科技凭其在大数据管理领域的专业技术实力&#xff0c;荣获成长企业组三等奖。 突出重围&#xff0c;崭露头角 海南省“科创杯”创新创业大赛是在中国科技…

安科瑞ADL系列导轨式多功能电能表 带外置互感器 CE认证

产品概述&#xff1a; ‌安科瑞ADL系列导轨式多功能电能表‌是安科瑞企业微电网能效管理事业部推出的一款智能仪表&#xff0c;主要针对光伏并网系统、微逆系统、储能系统、交流耦合系统等新能源发电系统设计。这款电能表具有高精度、体积小、响应速度达100ms&#xff0c;以及…

噪音消除模块调研

一.原理 1.1降噪 noisereduce 库的 reduce_noise 函数使用的是一种基于频谱减法的噪声消除算法。它通过分析音频的频谱&#xff0c;识别出噪声成分&#xff0c;并尝试将这些噪声成分从音频信号中去除&#xff0c;从而提升信号的清晰度。 1.2 动态范围压缩&#xff08;预加重&am…