Android 应用开发(17)---应用权限
权限概述
许可 的目的是保护Android用户的隐私。Android应用程序必须请求访问敏感用户数据(如联系人和短信)以及某些系统功能(如相机和互联网)的权限。根据功能的不同,系统可能会自动授予权限,或者可能会提示用户批准请求。
此页面概述了Android权限的工作原理,包括:如何向用户显示权限,安装时间和运行时权限请求之间的区别,权限的执行方式以及权限和组的权限类型。如果您只想使用应用权限的操作指南,请参阅 请求应用权限。
许可批准
应用程序必须通过 <uses-permission>
在应用程序清单中包含标签 来公布所需的权限 。例如,需要发送SMS消息的应用程序将在清单中包含以下行:
<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>
如果您的应用在其清单中列出了正常权限(即,对用户的隐私或设备操作不构成风险的权限),系统会自动将这些权限授予您的应用。
如果您的应用在其清单中列出了危险的权限(即可能影响用户隐私权或设备正常操作的SEND_SMS
权限),例如上述 权限,则用户必须明确同意授予这些权限。
有关正常和危险权限的更多信息,请参阅保护级别。
请求提示输入危险的权限
只有危险的权限需要用户同意。Android要求用户授予危险权限的方式取决于用户设备上运行的Android版本以及您的应用定位的系统版本。
运行时请求(Android 6.0及更高版本)
如果设备运行的是Android 6.0(API级别23)或更高版本, 并且该应用程序的版本targetSdkVersion
是23或更高,则安装时用户不会收到任何应用程序权限的通知。您的应用程序必须要求用户在运行时授予危险权限。当您的应用程序请求权限时,用户会看到一个系统对话框(如图1左侧所示),告诉用户您的应用正试图访问哪个权限组。该对话框包含拒绝和允许按钮。
如果用户拒绝权限请求,则在您的应用下次请求权限时,该对话框将包含一个复选框,该复选框在选中后表示用户不会再次被要求提供权限(请参阅图2右侧)。
图1.初始权限对话框(左侧)和辅助权限请求(带有关闭更多请求的选项)(右侧)
如果用户选中永不再问框并点击 拒绝,则系统不再提示用户,如果您稍后尝试请求相同的权限。
即使用户向您的应用程序授予您所请求的权限,您也不能始终依靠它。用户还可以选择在系统设置中逐个启用和禁用权限。您应该始终在运行时检查并请求权限以防止运行时错误(SecurityException
)。
有关如何处理运行时权限请求的详细信息,请参阅 请求应用程序权限。
安装时请求(Android 5.1.1及以下)
如果设备 在任何版本的Android上运行时运行 的是Android 5.1.1(API级别22)或更低,或者该应用的运行级别targetSdkVersion
为22或更低,则系统会自动要求用户在安装时为您的应用授予所有危险权限(见图2)。
图2.安装时权限对话框
如果用户点击接受,则应用请求的所有权限都被授予。如果用户拒绝权限请求,系统将取消应用程序的安装。
如果应用程序更新包含对额外权限的需求,则在更新应用程序之前会提示用户接受这些新的权限。
有关请求权限的建议用户体验模式概述,请参阅应用程序权限最佳实践。
要了解如何检查和请求用户的权限,请参阅 请求应用程序权限。
可选硬件功能的权限
访问某些硬件功能(例如蓝牙或相机)需要应用程序许可。但是,并非所有的Android设备都具备这些硬件功能。因此,如果您的应用程序请求 CAMERA
许可权,则还必须<uses-feature>
在清单中包含 标记以声明是否实际需要此功能。例如:
<uses-feature android:name="android.hardware.camera" android:required="false" />
如果您声明android:required="false"
了该功能,那么Google Play可让您的应用安装在没有此功能的设备上。然后您必须通过调用来检查当前设备是否在运行时具有该功能 PackageManager.hasSystemFeature()
,并在不可用时正常禁用该功能。
如果您不提供 <uses-feature>
代码,那么当Google Play发现您的应用请求相应的权限时,会假定您的应用需要此功能。因此,它会在没有该功能的设备上过滤您的应用,就像您android:required="true"
在 <uses-feature>
代码中声明一样 。
有关更多信息,请参阅 Google Play和基于功能的过滤
许可执行
权限不仅用于请求系统功能。应用程序提供的服务可以强制自定义权限,以限制可以使用它们的人员。有关声明自定义权限的更多信息,请参阅定义自定义应用程序权限。
活动许可执行
使用该android:permission
属性应用到清单中标记的权限限制了谁可以启动该权限。在和 期间检查权限 。如果呼叫者没有所需的权限, 则从呼叫中抛出。<activity>
Activity
Context.startActivity()
Activity.startActivityForResult()
SecurityException
服务许可执行
使用该android:permission
属性应用于清单中标记的权限限制了可以启动或绑定到关联的权限。在权限检查 ,和 。如果呼叫者没有所需的权限,则从呼叫中抛出。<service>
Service
Context.startService()
Context.stopService()
Context.bindService()
SecurityException
广播许可执行
使用android:permission
属性应用到标记的权限限制谁可以将广播发送到关联的。系统尝试将提交的广播传送给给定的接收者时,会在返回后检查权限。因此,权限失败不会导致异常被抛回给调用者; 它只是没有提供的。<receiver>
BroadcastReceiver
Context.sendBroadcast()
Intent
以同样的方式,可以提供许可Context.registerReceiver()
来控制谁可以以编程方式注册的接收者进行广播。换句话说,在调用Context.sendBroadcast()
限制哪些广播接收机被允许接收广播时可以提供许可。
请注意,接收者和广播者都需要获得许可。发生这种情况时,必须通过权限检查才能将意图传递到关联的目标。有关更多信息,请参阅 限制带权限的广播。
内容提供商许可执行
使用android:permission
属性应用于标记的权限限制谁可以访问a中的数据 。(内容提供者有一个重要的额外安全设施可用于他们,称为 URI权限,这将在下面介绍。)与其他组件不同,您可以设置两个单独的权限属性: 限制谁可以从提供者读取,并 限制谁可以写入它。请注意,如果提供者受到读写权限的保护,只保留写权限并不意味着您可以从提供者读取。 <provider>
ContentProvider
android:readPermission
android:writePermission
当您首次检索提供程序时(如果您没有权限,SecurityException
则会引发)以及在对提供程序执行操作时检查权限。使用 ContentResolver.query()
需要保持读取权限; 使用 ContentResolver.insert()
,ContentResolver.update()
, ContentResolver.delete()
需要写权限。在所有这些情况下,不保留所需的许可都会导致SecurityException
通话中丢失。
URI权限
目前描述的标准许可系统在与内容提供商一起使用时往往是不够的。内容提供者可能希望通过读写权限来保护自己,而直接客户端也需要将特定的URI传递给其他应用程序供他们操作。
一个典型的例子是电子邮件应用程序中的附件。访问电子邮件应受权限保护,因为这是敏感的用户数据。但是,如果将图像附件的URI提供给图像查看器,则该图像查看器不再有权打开该附件,因为它没有理由持有访问所有电子邮件的权限。
此问题的解决方案是每个URI权限:当启动一个活动或将结果返回给一个活动时,调用者可以设置Intent.FLAG_GRANT_READ_URI_PERMISSION
和/或 Intent.FLAG_GRANT_WRITE_URI_PERMISSION
。这允许接收活动权限访问意图中的特定数据URI,而不管其是否具有访问与意图相对应的内容提供者中的数据的任何权限。
这种机制允许一种通用的能力风格模型,在这种模型中,用户交互(例如打开附件或从列表中选择联系人)驱动临时授予细粒度权限。这可能是将应用程序所需的权限仅限于与其行为直接相关的权限的关键工具。
要构建使其他应用程序对其应用程序负责的最安全的实现,您应该以这种方式使用细粒度的权限,并使用属性或 标记声明您的应用程序对它的支持 。 android:grantUriPermissions
<grant-uri-permissions>
更多信息可在发现 Context.grantUriPermission()
, Context.revokeUriPermission()
和Context.checkUriPermission()
方法。
其他许可执行
任何调用服务时都可以强制任意细化权限。这是用该Context.checkCallingPermission()
方法完成的。使用所需的权限字符串进行调用,并返回一个整数,指示该权限是否已授予当前调用进程。请注意,只有当您执行从另一个进程调用的调用时(通常是通过从服务发布的IDL接口或以其他方式向另一个进程发送的调用),才可以使用它。
还有许多其他有用的方法来检查权限。如果您拥有其他进程的进程ID(PID),则可以使用该Context.checkPermission()
方法检查针对该PID的权限。如果您拥有其他应用的软件包名称,则可以使用该PackageManager.checkPermission()
方法来确定该特定软件包是否已被授予特定权限。
自动权限调整
随着时间的推移,新的限制可能会被添加到平台,以便为了使用某些API,您的应用程序必须请求以前不需要的权限。由于现有应用程序假定对这些API的访问是免费提供的,因此Android可能会将新的权限请求应用于应用程序的清单,以避免在新平台版本上破坏应用程序(从而为您的应用程序“授予权限”)。Android根据为该targetSdkVersion
属性提供的值来决定应用程序是否需要权限。如果该值低于添加权限的版本,则Android会添加权限。
例如,该READ_EXTERNAL_STORAGE
权限从API级别19开始执行,以限制对共享存储空间的访问。如果您的版本targetSdkVersion
是18或更低版本,则会在新版Android上将此权限添加到您的应用中。
警告:如果您的应用自动添加了权限,那么即使您的应用实际上不需要它们,Google Play上的应用列表也会列出这些附加权限。为了避免这种情况并删除您不需要的默认权限,请始终将您的权限更新 targetSdkVersion
为尽可能高。您可以查看Build.VERSION_CODES
文档中每个版本添加的权限。
保护级别
权限分为几个保护级别。保护级别影响是否需要运行时权限请求。
有三个保护级别会影响第三方应用程序: 正常,签名和危险权限。
普通权限
普通权限包括应用程序需要访问应用程序沙箱外的数据或资源的区域,但是用户的隐私或其他应用程序的操作风险很小。例如,设置时区的权限是普通权限。
如果应用程序在其清单中声明它需要正常许可,系统会在安装时自动授予应用程序该许可权。系统不会提示用户授予正常权限,并且用户无法撤消这些权限。
从Android 8.1(API级别27)开始,以下权限分类为 PROTECTION_NORMAL
:
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MANAGE_OWN_CALLS
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_COMPANION_RUN_IN_BACKGROUND
REQUEST_COMPANION_USE_DATA_IN_BACKGROUND
REQUEST_DELETE_PACKAGES
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
SET_ALARM
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
签名权限
系统在安装时授予这些应用程序权限,但仅当试图使用权限的应用程序由与定义权限的应用程序相同的证书签名时。
注意:某些签名权限不适用于第三方应用程序。
从Android 8.1(API级别27)开始,第三方应用程序可以使用的以下权限分类为 PROTECTION_SIGNATURE
:
BIND_ACCESSIBILITY_SERVICE
BIND_AUTOFILL_SERVICE
BIND_CARRIER_SERVICES
BIND_CHOOSER_TARGET_SERVICE
BIND_CONDITION_PROVIDER_SERVICE
BIND_DEVICE_ADMIN
BIND_DREAM_SERVICE
BIND_INCALL_SERVICE
BIND_INPUT_METHOD
BIND_MIDI_DEVICE_SERVICE
BIND_NFC_SERVICE
BIND_NOTIFICATION_LISTENER_SERVICE
BIND_PRINT_SERVICE
BIND_SCREENING_SERVICE
BIND_TELECOM_CONNECTION_SERVICE
BIND_TEXT_SERVICE
BIND_TV_INPUT
BIND_VISUAL_VOICEMAIL_SERVICE
BIND_VOICE_INTERACTION
BIND_VPN_SERVICE
BIND_VR_LISTENER_SERVICE
BIND_WALLPAPER
CLEAR_APP_CACHE
MANAGE_DOCUMENTS
READ_VOICEMAIL
REQUEST_INSTALL_PACKAGES
SYSTEM_ALERT_WINDOW
WRITE_SETTINGS
WRITE_VOICEMAIL
危险的权限
危险权限涵盖应用程序需要涉及用户私人信息的数据或资源的区域,或者可能会影响用户的存储数据或其他应用程序的操作。例如,阅读用户联系人的权限是一个危险的权限。如果一个应用程序声明它需要一个危险的权限,用户必须明确授予该应用程序的权限。在用户批准权限之前,您的应用无法提供取决于该权限的功能。
要使用危险权限,您的应用必须提示用户在运行时授予权限。有关如何提示用户的更多详细信息,请参阅 请求提示输入危险权限。
有关危险权限的列表,请参阅下面的表1。
特殊权限
有几个权限不具有正常和危险的权限。SYSTEM_ALERT_WINDOW
并且WRITE_SETTINGS
特别敏感,所以大多数应用程序不应该使用它们。如果应用程序需要这些权限之一,则必须在清单中声明权限,并发送请求用户授权的意图。系统通过向用户显示详细的管理屏幕来响应意图。
有关如何请求这些权限的详细信息,请参阅SYSTEM_ALERT_WINDOW
和 WRITE_SETTINGS
参考条目。
Android系统提供的所有权限都可以在这里找到 Manifest.permission
。
权限组
权限被组织到与设备功能相关的组中。在此系统下,权限请求在组级别处理,并且单个权限组对应于应用清单中的多个权限声明。例如,SMS组中同时包含READ_SMS
和 RECEIVE_SMS
声明。以这种方式分组权限使得用户能够做出更有意义和更明智的选择,而不会被复杂的技术许可请求所淹没。
所有危险的Android权限都属于权限组。不管保护级别如何,任何权限都可以属于权限组。但是,如果权限是危险的,权限组只会影响用户体验。
如果设备运行的是Android 6.0(API级别23),并且该应用的级别targetSdkVersion
为23或更高,则当您的应用请求危险权限时,以下系统行为适用:
- 如果应用程序当前没有权限组的权限,系统会向描述该应用程序想要访问的权限组的用户显示权限请求对话框。该对话框没有描述该组内的特定权限。例如,如果应用程序请求
READ_CONTACTS
权限,则系统对话框只是表示应用程序需要访问设备的联系人。如果用户同意,系统只给予应用程序许可。 - 如果应用程序已被授予同一权限组中的另一个危险权限,系统会立即授予权限,而不会与用户进行任何交互。例如,如果一个应用程序先前已经请求并被授予了该
READ_CONTACTS
权限,然后它会请求WRITE_CONTACTS
,系统会立即授予该权限,而不会向用户显示权限对话框。
警告:未来版本的Android SDK可能会将特定权限从一个组移到另一个组。因此,不要将您的应用的逻辑基于这些权限组的结构。
例如,与Android 8.1(API级别27)READ_CONTACTS
处于相同的权限组 WRITE_CONTACTS
。如果您的应用请求READ_CONTACTS
权限,然后请求 WRITE_CONTACTS
权限,请不要假定系统可以自动授予 WRITE_CONTACTS
权限。
如果设备运行Android 5.1(API级别22)或更低,或者应用程序的级别 targetSdkVersion
为22或更低,则系统会要求用户在安装时授予权限。系统再一次告诉用户应用程序需要什么权限组,而不是个人权限。例如,当应用程序请求READ_CONTACTS
安装对话框列出联系人组时。当用户接受时,只有READ_CONTACTS
权限被授予应用程序。
注意:即使用户已经在同一组中授予另一个权限,您的应用仍需要明确请求所需的每个权限。另外,在未来的Android版本中,将权限分组成组可能会有所不同。您的代码不应具有依赖于同一组中的一组特定权限的逻辑。
表1.危险权限和权限组。
权限组 | 权限 |
---|---|
CALENDAR
|
|
CAMERA
|
|
CONTACTS
|
|
LOCATION
|
|
MICROPHONE
|
|
PHONE
|
|
SENSORS
|
|
SMS
|
|
STORAGE
|
|
查看应用程序的权限
您可以使用“设置”应用程序和shell命令查看系统中当前定义的所有权限adb shell pm list permissions
。要使用设置应用,请转到设置 > 应用。选择一个应用并向下滚动以查看该应用使用的权限。对于开发人员,adb'-s'选项以类似于用户看到它们的方式显示权限:
$ adb shell pm列表权限-s所有权限:网络通信:查看Wi-Fi状态,创建蓝牙连接,已满互联网接入,查看网络状态您的位置:访问额外的位置提供商命令,罚款(GPS)位置,用于测试的模拟位置源,粗略(基于网络)的位置为您花费的服务:发送短信,直接拨打电话号码...
-g
在模拟器或测试设备上安装应用程序时,您还可以使用adb 选项自动授予所有权限:
$ adb shell install -g MyApp.apk
继续阅读:
- 请求应用程序权限
- 如何在您的应用程序中请求权限的操作指南。
- 暗含功能需求的权限
- 有关如何请求某些许可权的信息会将您的应用程序限制为包含相应硬件或软件功能的设备。
-
<uses-permission>
- 清单标记的API参考声明您的应用程序的必需权限。
你也可能对此有兴趣:
- 设备兼容性
- 有关Android的信息适用于不同类型的设备,并介绍如何针对每个设备优化您的应用或限制您的应用在不同设备上的可用性。
- Android安全概述
- 关于Android平台安全模型的详细讨论。
Android 应用开发(17)---应用权限相关推荐
- 【Android 应用开发】动态权限管理示例 ( 使用原生代码实现 | 申请权限 | 判定权限申请结果 | 判定 “ 不再询问 “ 情况 )
文章目录 一.申请权限 二.判定权限申请结果 三.判定 " 不再询问 " 情况 四.完整代码示例 1.权限管理代码 2.主界面代码 3.执行结果 五.博客资源 一.申请权限 首先 ...
- 【Android 应用开发】Google 官方 EasyPermissions 权限申请库 ( 最简单用法 | 一行代码搞定权限申请 | 推荐用法 )
文章目录 一.添加依赖 二.在 AndroidManifest.xml 中配置权限 三.权限申请最简单用法 四.推荐使用的用法 五.GitHub 地址 上一篇博客 [Android 应用开发]Goog ...
- android权限--android开发中的权限及含义(下)
android权限--android开发中的权限及含义(下) android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权 ...
- Android 应用开发(20)--- 定义自定义应用程序权限
定义自定义应用程序权限 本文档描述应用程序开发人员如何使用Android提供的安全功能来定义他们自己的权限.通过定义自定义权限,应用程序可以与其他应用程序共享其资源和功能.有关权限的更多信息,请参阅权 ...
- 《Android游戏开发详解》一2.17 对象是独立的
本节书摘来异步社区<Android游戏开发详解>一书中的第2章,第2.1节,译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区"异步社区"公众号查看. 2.17 ...
- Android SELinux开发入门指南之如何增加Native Binder Service权限
Android SELinux开发入门指南之如何增加Native Binder Service权限 Android SELinux开发多场景实战指南目录: Android SELinux开发入门指 ...
- Android SELinux开发入门指南之正确姿势解决访问data目录权限问题
Android SELinux开发入门指南之正确姿势解决访问data目录权限问题 Android SELinux开发多场景实战指南目录: Android SELinux开发入门指南之SELinux ...
- Android SELinux开发入门指南之如何增加Java Binder Service权限
Android SELinux开发入门指南之如何增加Java Binder Service权限 Android SELinux开发多场景实战指南目录: Android SELinux开发入门指南之 ...
- Android直播开发之旅(17):使用FFmpeg提取MP4中的H264和AAC
最近在开发中遇到了一个问题,即无法提取到MP4中H264流的关键帧进行处理,且保存到本地的AAC音频也无法正常播放.经过调试分析发现,这是由于解封装MP4得到的H264和AAC是ES流,它们缺失解码时 ...
最新文章
- wxpython输入框_基于wxPython的GUI实现输入对话框(1)
- 解决robotframework安装时提示wxPython not found问题
- python commands_python commands模块在python3.x被subprocess取代
- 苏区振兴下的赣州发展状况分析
- 库存管理-历史库存和收发存系列-MB5B
- 985博导:我的研究生,学生会干部不招,面试的时候,直接淘汰!
- 《深入实践Spring Boot》一3.3 使用Thymeleaf模板
- SentOS 7防火墙配置与端口增删改查的命令
- vmware-tools安装失败
- mysql日期函数转换_Mysql日期函数大全 转
- 系统学习深度学习(三十六)--Actor-Critic
- sql处理null值
- python版本历史_python历史介绍
- CMA检测报告中,CNAS,CMA分别代表的意义
- matlab 开普勒方程,第二章 开普勒方程.ppt
- 库存数量控制中储备定额方法的改进与实现
- 剑指offer:用两个栈实现队列
- 八、Sentinel.conf 配置文件详细介绍
- 二阶系统的单位阶跃响应与比例控制器
- 如何创建一张属于自己的简单的网页
热门文章
- NAPI 技术在 Linux 网络驱动上的应用和完善
- Linux内核分析 - 网络[四补]:路由表补充
- 去除报错_转录组分析 | 使用trimgalore去除低质量的reads和adaptor
- intellij idea开发工具
- 2018-10-20
- HDU - 4746预处理莫比乌斯反演
- 纯CSS实现table表头固定(自创备忘)
- Spark学习笔记(3)--SparkContext部分源码分析
- Activiti启动某个流程失败,页面报500
- 【树状数组】Bzoj1878[SDOI2009] HH的项链