Android权限概述

本文详述了Android权限管理的各个方面,包括权限的请求、执行、权限等级、权限组和如何查看APP权限。Android 6.0及以上版本引入运行时权限,用户需在APP运行时对危险权限进行授权。权限执行涉及到Activity、Service、Broadcast和Content Provider。同时,文章介绍了如何适配新权限以确保APP在不同Android版本上的兼容性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android的权限机制是用于保护用户的隐式信息。APP访问敏感用户数据(如联系人和SMS)或某些系统功能(如Camera和Internet)时,必须请求用户授予对应的权限。根据被访问的特性,系统会自动授予权限或请求用户授予权限。本文将对Android权限是怎样工作的进行概述,包括:权限请求提示框是怎样展示给用户的、“安装时请求权限”与“运行时请求权限”的区别、权限是如何执行的、权限的类型及分组。

权限授予

APP需要在Manifest文件中用<uses-permission>显示申请所需的权限。例如,APP需要发送SMS,那么需要在manifest中做如下申请:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.snazzyapp">

    **<uses-permission android:name="android.permission.SEND_SMS"/>**

    <application ...>
        ...
    </application>
</manifest>

对于APP在Manifest中申请的普通权限(不会给用户隐私和设备操作带来风险的权限),系统会自动授予权限给APP;对于APP在Manifest中申请的危险权限(会给用户隐私和设备操作带来风险的权限),如SEND_SMS权限,用户必须显式授予权限给APP。关于普通权限和危险权限的详细信息,请见“安全等级”。

请求授予危险权限

只有危险权限才需要用户的授予。Android系统请求用户授予危险权限的方法与用户设备上运行的Android版本和APP的Target Version有关。

运行时请求权限(Android 6.0及以上)

如果Android系统版本为Android 6.0(API 23)及以上,APP的targetSdkVersion是23及以上,那么在安装APP时不提示用户授予权限,而在APP运行时提示用户授予危险权限。系统会向用户展示一个提示框(如图1左边所示),提示用户APP当前正在请求哪个权限。对话框包括一个Deny按钮和一个Allow按钮。

如果用户不允许授予此权限,那么APP下次请求这个权限时,弹出的提示框上会多一个单选框。如果用户勾选提示框中的“Never ask again”,那么APP下次再请求同一个权限时,系统不会再提示用户授予权限。(如图1右边所示)。
这里写图片描述
图1:左边为首次弹出的权限提示框,右边为第二次弹出的权限提示框

即使用户授予了APP请求的权限,用户仍然可以在设置中禁止或开启此权限,所以APP需在运行时检查和请求权限,以防止运行时出现SecurityException。

安装时请求权限(Android 5.1.1及以下)

如果Android系统版本为Android 5.1.1(API 22)及以下,或者APP的targetSdkVersion是22及以下,那么系统在安装APP时提示用户授予危险权限(如图2)。
这里写图片描述
图2:安装时展示权限提示框
如果用户点击Accept,那么将授予APP请求的所有权限;如果用户不同意授权,那么系统取消安装此APP。如果更新后的APP需要请求新的权限,那么需要在更新APP前先让用户先授权这个新的权限。

硬件特性的权限

APP访问某些硬件特性(如Bluetooth和Camera)时也需要请求权限,但不是所有Android设备都有这些特性。所以,如果APP请求CAMERA 权限,应该在Manifest文件中用 申明是否需要使用此硬件特性,如:

<uses-feature android:name="android.hardware.camera" android:required="false" />

如果把一个特性设置为android:required=”false” ,那么Google Play允许APP安装到一个不支持此特性的设备上,且APP必须在运行时调用 PackageManager.hasSystemFeature()来检查当前设备是否支持此特性,如果设备不支持此特性就优雅的屏蔽对应的功能。

如果申请了访问此特性的权限,但是不提供 ,系统就会认为APP需要使用此特性,即相当于在中设置android:required=”true”。Google Play就会认为APP需要使用这个特性,那么它不允许APP安装到不支持这个特性的设备上。更多信息,可参考 Google Play and feature-based filtering

权限执行

权限不仅用于限制对系统功能的请求,而且用于限制Service、Activity、Broadcast等的请求。

Activity的权限执行

在Manifest文件中,给 tag设置android:permission的属性,用以限制谁可以启动此Activity。在 Context.startActivity()和Activity.startActivityForResult()时会检查这个权限。如果调用者没有这个权限,那么会抛出SecurityException异常。

Service的权限执行

在Manifest文件中,给 tag设置android:permission的属性,用以限制谁可以start或bind此Service。在 Context.startService()、 Context.stopService()和Context.bindService()时会检查这个权限。如果调用者没有这个权限,那么会抛出SecurityException异常。

Broadcast的权限执行

在Manifest文件中,给 tag设置android:permission的属性,用以限制谁可以向这个静态注册的BroadcastReceiver发送广播。在 Context.sendBroadcast() return后会检查这个权限。如果调用者没有这个权限,那么不会抛出异常,而是系统不把广播发送给对应的BroadcastReceiver。

类似的方法,在调用Context.registerReceiver()时设置权限,用以限制谁可以向这个动态注册的BroadcastReceiver发送广播。相反的,可以在调用Context.sendBroadcast()时设置权限,用以限制谁可以接受这个Broadcast发送的广播。

注意,当receiver和broadcaster都设置了权限时,两边的权限都检查通过了,才能成功发送和接收广播。

Content Provider的权限执行

在Manifest文件中,给 tag设置android:permission的属性,用以限制谁可以访问这个 ContentProvider中的数据。与其它组件不同,你可以给 ContentProvider分别设置两个权限: android:readPermission用于限制谁可以从 这个ContentProvider读取数据,android:writePermission用于限制谁可以向这个ContentProvider写入数据。如果一个ContentProvider同时设置了android:readPermission和android:writePermission,那么一个只有写权限的APP不能从这个ContentProvider读数据。

当APP第一次检索或操作这个ContentProvider时,系统会检查APP是否有对应权限,如果没有,就会抛出SecurityException异常。调用ContentResolver.query()时需要读权限,调用 ContentResolver.insert()、ContentResolver.update()、ContentResolver.delete()时需要写权限。

URI的权限执行

ContentProvider不仅用上述的android:readPermission、android:writePermission,还用URI permissions来限制谁可以读写这个ContentProvider。例如访问email需要权限控制,如果一个image附件的URI给了一个查看者,但是这个查看者没有查看所有email的权限,所以他无法查看这个附件。为了解决这个问题,可以用一次性授权的方式:当startActivity时,给Intent设置Intent.FLAG_GRANT_READ_URI_PERMISSION 或 Intent.FLAG_GRANT_WRITE_URI_PERMISSION标志。

其它权限执行

如果APP在处理来自其他进程的调用时,可以使用 Context.checkCallingPermission()、Context.checkPermission() 、PackageManager.checkPermission() 来检查其它进程是否有对应的权限。

自动适配权限

随着时间的推移,新的权限可能会添加到平台上,为了使用某些API,APP必须请求它以前不需要的权限。由于现有的APP假定是可以不用权限就可以访问这些API的,Android就把新的权限请求适配到应用程序的Manifest中,以避免破坏新平台版本的app。Android根据APP的 targetSdkVersion值判断APP是否需要这个权限。例如:READ_EXTERNAL_STORAGE权限是在API level 19才开始添加的,如果APP的targetSdkVersion值为18或更低,那么在新的Android版本上这个权限将被添加到APP

权限等级

权限被分为几个等级,系统更具权限的等级来决定是否需要在运行时请求权限。所有的权限请见Manifest.permission

一般权限

一般权限覆盖的范围为:APP需要访问其它进程内的数据和资源,但是对用户隐私和对其它APP的操作不会带来风险。例如,设置时区的权限就是一般权限。

如果APP在Manifest中申明了要使用某个一般权限,那么系统会在安装这个APP时自动授予这个权限。系统不会让用户来授予一般权限,用户也不能撤销一般权限。

危险权限

危险权限的覆盖范围为:APP需要访问的数据和资源涉及用户隐私,或能影响到用户的存储数据,或能影响到其它APP的操作。例如,读取联系人的权限就是危险权限。如果APP申请使用危险权限,那么需要用户在APP运行时显式授予权限。

特殊权限

有几个权限与一般权限和危险权限的表现形式不同,如 SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS特别敏感,所以极少的APP会使用它们。如果APP需要使用这些权限,必须在Manifest文件中申明权限,且发送一个Intent请求用户的授权,系统就会向用户展示一个详细的权限管理界面。

权限组

根据设备的功能和特性,权限被分为权限组。系统以权限组的形式来处理权限请求,一个权限组可能对应Manifest中申请的几个权限。例如,SMS权限组包括READ_SMS 和RECEIVE_SMS权限。权限组的方式让用户更容易理解权限,和更方便处理APP的权限请求,防止过多的复杂的授予单独的权限。
这里写图片描述
所有的权限,不管它是什么权限等级,都属于某一个权限组。只有当权限为危险权限时,权限组才影响到用户体验。

如果设备运行的系统为Android 6.0 (API level 23),APP的 targetSdkVersion为23或更高,当APP请求危险权限时,系统的表现如下:
1、如果当前APP没有获得过权限组中的任何权限,APP请求权限组中的权限时,系统会向用户展示APP请问访问权限组的提示框。提示框不会单独描述权限组中的某一个权限。例如APP请求访问READ_CONTACTS权限,提示框只描述APP需要访问设备的联系人。如果用户授予APP这个权限,那么APP只获得这个权限。
2、如果当前APP获得过权限组中的某个权限,APP请求权限组中的其它权限时,系统会立刻授予APP这个权限,而不需要与用户做任何交互。例如APP之前已经请求并被授予READ_CONTACTS权限,如果它再请求 WRITE_CONTACTS权限,那么系统会立刻授予APP这个权限,而不需要弹出权限提示框。

如果设备运行的系统为Android 5.1 (API level 22)或更低,或targetSdkVersion为22或更低,系统中安装APP时让用户授予权限。系统只告诉用户APP需要哪些权限组,而不相信展示所需的单个权限。例如,APP请求 READ_CONTACTS权限,那么安装提示框只列出Contacts权限组。如果用户同意授权这个权限,那么APP只获得这个权限。

查看APP的权限

你可以在“设置”APP中,或用shell命令adb shell pm list permissions查看当前系统定义的权限。如果通过“设置”APP查看,进入Settings > Apps,选择要查看的APP,就能看到这个APP使用的权限。对于开发者,key用adb命令查看APP使用的权限,例如:

$ adb shell pm list permissions -s
All Permissions:

Network communication: view Wi-Fi state, create Bluetooth connections, full
internet access, view network state

Your location: access extra location provider commands, fine (GPS) location,
mock location sources for testing, coarse (network-based) location

Services that cost you money: send SMS messages, directly call phone numbers

...

你也可以在安装APP时用adb -g命令自动授予APP所有权限,例如:

$ adb shell install -g MyApp.apk
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值