android应用权限梗概

权限概述

权限的目的是保护Android用户的隐私。Android应用程序必须请求访问敏感用户数据(如联系人和短信)以及某些系统特性(如摄像头和互联网)的权限。根据功能的不同,系统可能自动授予权限,也可能提示用户批准请求。

本页面概述了Android权限的工作方式,包括:如何向用户显示权限、安装时间和运行时权限请求之间的差异、权限是如何执行以及权限的类型及其组。如果您只是想要一个如何使用应用程序权限的指南,请参见请求应用程序权限。

权限许可

应用程序必须通过在应用程序清单中包含标签来公开所需的权限。例如,需要发送SMS消息的应用程序会在清单中有这一行:



    

    
        ...
    

如果您的应用程序在其清单中列出了正常的权限(即对用户的隐私或设备的操作没有太大风险的权限),系统会自动授予您的应用程序这些权限。
如果您的应用程序在其清单中列出了危险的权限(即可能影响用户隐私或设备正常操作的权限),如上面的SEND_SMS权限,用户必须明确同意授予这些权限。
有关正常权限和危险权限的更多信息,请参见保护级别。

请求危险权限

只有危险的权限才需要用户同意。Android要求用户授予危险权限的方式取决于用户设备上运行的Android版本,以及应用程序针对的系统版本。(两个条件
运行时请求(Android 6.0和更高版本)
如果该设备运行的是Android 6.0 (API级别23)或更高版本,并且该应用程序的targetSdkVersion是23或更高,那么用户在安装时就不会被通知任何应用程序权限。应用程序必须要求用户在运行时授予危险的权限。当您的应用程序请求权限时,用户会看到一个系统对话框(如图1所示,左),告诉用户您的应用程序要访问哪个权限组。对话框包含一个Deny和Allow按钮。
如果用户拒绝权限请求,那么下次您的应用程序请求权限时,对话框将包含一个复选框,如果选中该复选框,则表明用户不希望再次被提示请求权限(请参见图2,右)。

android应用权限梗概_第1张图片
运行时权限请求 初始请求框和二次请求框

图1所示。初始权限请求框(左)和二次请求请求框,附带永久拒绝的选择(右)
如果用户检查“永不再问”框并单击“拒绝”,如果您以后试图请求相同的权限,系统将不再提示用户。
即使用户授予你的应用所请求的权限,你也不能总是依赖它。用户还可以选择在系统设置中逐个启用和禁用权限。您应该始终在运行时检查并请求权限,以防止运行时错误(SecurityException)。
有关如何处理运行时权限请求的详细信息,请参阅请求应用程序权限。

安装时间请求(Android 5.1.1和以下)
如果设备运行的是安卓5.1.1 (API级别22)或更低,或者应用程序的targetSdkVersion在运行任何版本的Android时是22或更低,那么系统会自动要求用户在安装时为您的应用授予所有危险的权限(参见图2)。

android应用权限梗概_第2张图片
安装时请求权限

如果用户单击Accept,则授予应用程序请求的所有权限。如果用户拒绝权限请求,系统将取消应用程序的安装。
如果一个应用程序更新包含了额外权限的需要,用户在更新应用程序之前会被提示接受这些新权限。
有关请求推荐的用户权限体验模式的概述,请参阅应用程序权限最佳实践。
要了解如何检查和请求用户的权限,请参阅请求应用程序权限。


可选硬件特性的权限

访问某些硬件特性(如蓝牙或摄像头)需要应用程序许可。然而,并不是所有的Android设备都有这些硬件特性。因此,如果您的应用程序请求相机许可,那么您还需要在清单中包含标记,以声明这个特性是否确实需要。例如:


这个tag是google pay用于预下载的判断标志,如果未申明它,但是检测到你的应用需要申请camera权限那就和require=true一样,不允许没有camera的设备下载(以下是原文):

如果您声明android:required="false",那么谷歌Play允许您的应用程序安装在没有该功能的设备上。然后,您必须通过调用PackageManager.hasSystemFeature()来检查当前设备在运行时是否具有该特性,如果该特性不可用,则应适当地禁用该特性。
如果您不提供标签,那么当谷歌Play看到您的应用程序请求相应的权限时,它假定您的应用程序需要这个特性。因此,它可以从设备中过滤你的应用程序,而不使用该功能,就像你在标签中声明android:required="true"一样。
有关更多信息,请参见谷歌Play和基于特性的过滤

强制权限(自定义权限)


权限不仅仅用于请求系统功能。应用程序提供的服务可以执行自定义权限,以限制谁可以使用它们。有关声明自定义权限的更多信息,请参见定义自定义应用程序权限。
Activity权限限制
使用android:permission属性对manifest中标签应用权限限制谁可以启动该活动。在Context.startActivity()和Activity.startActivityForResult()过程中检查权限。如果调用者没有必要的权限,则从调用中抛出SecurityException。
Service权限限制
使用android:permission属性对清单中的标签进行权限限制,限制谁可以启动或绑定到关联的服务。权限在Context.startService()、Context.stopService()和Context.bindService()期间检查。如果调用者没有必要的权限,则从调用中抛出SecurityException。
Broadcast权限限制
使用android:permission属性对标签进行权限限制,该标签可以向关联的BroadcastReceiver发送广播。在Context.sendBroadcast()返回后检查权限,此时系统试图将提交的广播发送给给定的接收方。因此,权限失败不会导致向调用者抛出异常;它只是不能传达意图。
同样,可以向Context.registerReceiver()提供权限,以控制谁可以向程序注册的接收者广播。反过来,可以在调用Context.sendBroadcast()时提供权限,以限制允许哪些广播接收器接收广播。
请注意,接收方和广播方都需要获得许可。当发生这种情况时,两个权限检查都必须传递给要传递到关联目标的意图。有关更多信息,请参见使用权限限制广播。
Content Provider权限限制
使用android:permission属性对可以访问ContentProvider中的数据的标签进行限制。(内容提供者有一个重要的附加安全设施,称为URI权限,后面将对此进行介绍。)与其他组件不同,您可以设置两个独立的权限属性:android:readPermission限制谁可以从提供程序中读取,而android:writePermission限制谁可以写入。请注意,如果提供程序同时具有读和写权限,那么只保留写权限并不意味着可以从提供程序中读取。
当您第一次检索提供者时(如果您没有任何权限,则抛出SecurityException)和在提供者上执行操作时,将检查权限。使用ContentResolver.query()需要持有读权限;使用ContentResolver.insert()、ContentResolver.update()、ContentResolver.delete()需要写权限。在所有这些情况下,不持有所需的权限会导致从调用中抛出SecurityException。

URI的权限
当与内容提供者一起使用时,到目前为止所描述的标准权限系统通常是不够的。内容提供者可能希望使用读和写权限保护自己,而其直接客户端也需要将特定的uri交给其他应用程序,以便它们进行操作。
一个典型的例子是电子邮件应用程序中的附件。访问电子邮件应该受到权限保护,因为这是敏感的用户数据。但是,如果图像附件的URI给了图像查看器,那么该图像查看器就不再具有打开附件的权限,因为它没有理由持有访问所有电子邮件的权限。
这个问题的解决方案是每个uri权限:当启动一个活动或将结果返回给一个活动时,调用者可以设置意图。FLAG_GRANT_READ_URI_PERMISSION和/或Intent.FLAG_GRANT_WRITE_URI_PERMISSION。这将授予接收活动权限访问特定数据URI的意图,无论它是否有权限访问与意图相对应的内容提供程序中的数据。
这种机制允许用户交互(如打开附件或从列表中选择联系人)驱动特定的细粒度权限授予的公共能力样式模型。这是一个关键的功能,可以将应用程序所需的权限减少到仅与它们的行为直接相关的权限。
要构建最安全的实现,使其他应用程序在您的应用程序中对其操作负责,您应该以这种方式使用细粒度权限,并使用android:grantUriPermissions属性或标记声明应用程序对其的支持。
更多信息可以在Context.grantUriPermission()、Context.revokeUriPermission()和Context.checkUriPermission()方法中找到。
其他许可实施
任意细粒度的权限可以在调用服务时强制执行。这是通过Context.checkCallingPermission()方法完成的。使用所需的权限字符串进行调用,并返回一个整数,该整数指示是否已将该权限授予当前调用进程。注意,这只能在执行来自另一个进程的调用时使用,通常是通过从服务发布的IDL接口,或者以其他方式提供给另一个进程。
检查权限还有许多其他有用的方法。如果您有另一个进程的进程ID (PID),您可以使用Context.checkPermission()方法对该PID检查权限。如果您有另一个应用程序的包名,您可以使用PackageManager.checkPermission()方法来确定特定的包是否被授予了特定的权限。
允许自动调整

android生态决定权限检查,在低版本设备上允许正常,高设备时会有审核,解决方案就是提前考虑?(以下为原文)

随着时间的推移,可能会向平台添加新的限制,以便为了使用某些api,应用程序必须请求以前不需要的权限。由于现有的应用程序假定可以免费访问这些api,因此Android可能会对应用程序的manifest应用新的权限请求,以避免在新的平台版本上破坏应用程序(因此,对您的应用程序进行“扩展”以获得许可)。Android根据targetSdkVersion属性提供的值来决定应用程序是否需要权限。如果值低于添加权限的版本,则Android添加权限。
例如,READ_EXTERNAL_STORAGE权限从API级别19开始强制执行,以限制对共享存储空间的访问。如果你的targetSdkVersion是18或更低,这个权限会被添加到新版本的Android上。

注意:如果一个权限被自动添加到你的应用程序中,你的应用程序在谷歌播放列表中列出了这些附加的权限,即使你的应用程序实际上可能并不需要这些权限。为了避免这种情况并删除不需要的默认权限,总是将targetSdkVersion更新得尽可能高。您可以在Build.VERSION_CODES文档中查看每个版本中添加了哪些权限。
保护水平(权限的三个级别)
权限分为几个保护级别。保护级别影响是否需要运行时权限请求。
有三个保护级别会影响第三方应用程序:正常的、签名的和危险的权限。
Normal permissions:
正常的权限涵盖了应用程序需要访问应用程序沙箱之外的数据或资源的领域,但对用户的隐私或其他应用程序的操作风险非常小。例如,设置时区的权限是正常的权限。
如果一个应用程序在其清单中声明它需要一个正常的权限,系统会在安装时自动授予这个应用程序权限。系统不会提示用户授予正常权限,用户不能撤销这些权限。
Signature permissions签名权限
系统在安装时授予这些应用程序权限,但只有当试图使用权限的应用程序与定义许可的应用程序签署相同的证书时才会授予。
注意:有些签名权限不是第三方应用程序使用的。

权限组(分组方式为按功能分)


权限被组织成与设备功能或特性相关的组。在这个系统中,权限请求在组级别处理,单个权限组对应于应用程序清单中的多个权限声明。例如,SMS组包括READ_SMS和RECEIVE_SMS声明。通过这种方式对权限进行分组,使用户能够做出更有意义、更明智的选择,而不会被复杂的技术权限请求所淹没。
![权限组]https://developer.android.google.cn/images/training/articles/user-data-overview-permissions-flow01.jpg
所有危险的Android权限属于权限组。无论保护级别如何,任何权限都可以属于权限组。然而,权限组仅在权限危险的情况下才会影响用户体验。
如果设备运行的是安卓6.0 (API级别23),而应用程序的targetSdkVersion为23或更高,当应用程序请求危险权限时,应用以下系统行为:

  • 如果应用程序当前在权限组中没有任何权限,系统将向用户显示权限请求对话框,描述应用程序希望访问的权限组。对话框没有描述组内的特定权限。例如,如果一个应用程序请求READ_CONTACTS权限,系统对话框只是说应用程序需要访问设备的联系人。如果用户授予批准,系统只会给应用程序它所要求的权限。
  • 如果应用程序已经在同一个权限组中被授予了另一个危险的权限,系统会立即授予该权限,而无需与用户进行任何交互。例如,如果一个应用程序先前请求并被授予READ_CONTACTS权限,然后它请求WRITE_CONTACTS,系统会立即授予该权限,而不会向用户显示权限对话框。(规则会变,所以应该用最稳当的写法)
    注意:Android SDK的未来版本可能会将特定的权限从一个组转移到另一个组。因此,不要将应用程序的逻辑建立在这些权限组的结构上。
    例如,READ_CONTACTS与Android 8.1 (API level 27)中的WRITE_CONTACTS相同。如果您的应用程序请求READ_CONTACTS权限,然后请求WRITE_CONTACTS权限,不要假设系统可以自动授予WRITE_CONTACTS权限。
  • 如果设备运行的是安卓5.1 (API级别22)或更低,或者应用的targetSdkVersion为22或更低,系统要求用户在安装时授予权限。再一次,系统只告诉用户应用程序需要的权限组,而不是单独的权限。例如,当应用程序请求READ_CONTACTS时,安装对话框会列出联系人组。当用户接受时,只有READ_CONTACTS权限被授予应用程序。
    注意:您的应用程序仍然需要显式地请求它需要的每个权限,即使用户已经在同一组中授予了另一个权限。此外,在未来的Android版本中,权限分组可能会发生变化。您的代码不应该具有依赖于同一组中的一组特定权限的逻辑。

Viewing an app's permissions


您可以使用设置应用程序和shell命令adb shell pm list permissions,查看系统中当前定义的所有权限。要使用设置应用程序,请转到设置>应用程序。选择一个应用程序,向下滚动查看应用程序使用的权限。对于开发人员,adb的-s选项以类似于用户看到的方式显示权限:

$ 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

...

您还可以使用adb -g选项在模拟器或测试设备上安装应用程序时自动授予所有权限:

$ adb shell install -g MyApp.apk

你可能感兴趣的:(android应用权限梗概)