Android复习(四)权限—>概览

权限概述

许可 的目的是保护Android用户的隐私。Android应用必须获得访问敏感用户数据(例如联系人和SMS)以及某些系统功能(例如相机和互联网)的权限。根据功能的不同,系统可能会自动授予权限,或者可能提示用户批准请求。

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>
</ manifest>

  

如果您的应用在其清单中列出了正常权限(即,不会对用户的隐私或设备的操作造成太大风险的权限),则系统会自动将这些权限授予您的应用。

如果您的应用在清单中列出了危险的权限(即可能会影响用户隐私或设备正常操作的SEND_SMS权限),例如上述 权限,则用户必须明确同意授予这些权限。

有关正常和危险权限的更多信息,请参阅保护级别

请求提示危险权限

只有危险的权限需要用户同意。Android要求用户授予危险权限的方式取决于在用户设备上运行的Android版本以及您的应用定位的系统版本。

运行时请求(Android 6.0及更高版本)

如果设备运行的是Android 6.0(API级别23)或更高版本, 并且应用程序的版本targetSdkVersion 为23或更高版本,则在安装时不会通知用户任何应用程序权限。您的应用程序必须要求用户在运行时授予危险权限。当您的应用请求权限时,用户会看到一个系统对话框(如图1左侧所示),告诉用户您的应用正在尝试访问哪个权限组。该对话框包括“拒绝”和“ 允许”按钮。

如果用户拒绝许可请求,则下次您的应用程序请求许可时,对话框将包含一个复选框,选中该复选框后,该复选框指示用户不想再次被提示输入许可(请参见图1,右)。

图1.初始许可对话框(左)和辅助许可请求,带有关闭其他请求的选项(右)

如果用户选中“ 不再询问”框并点击 “拒绝”,则系统不再提示用户是否以后再尝试请求相同的权限。

即使用户向您的应用授予了它所请求的权限,您也不能总是依靠它。用户还可以选择在系统设置中一对一启用和禁用权限。您应该始终在运行时检查并请求权限,以防止运行时错误(SecurityException)。

有关如何处理运行时权限请求的详细信息,请参阅“ 请求应用程序权限”

安装时间请求(Android 5.1.1及更低版本)

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

图2.安装时权限对话框

如果用户单击“ 接受”,则将授予应用程序请求的所有权限。如果用户拒绝权限请求,则系统将取消应用程序的安装。

如果应用程序更新包含对其他权限的需求,则会提示用户在更新应用程序之前接受这些新权限。

有关建议的请求权限的用户体验模式的概述,请参阅“ 应用程序权限最佳实践”

要了解如何检查用户的权限并向其请求权限,请参阅“ 请求应用程序权限”

请求提示以访问敏感的用户信息

某些应用程序依赖对与呼叫日志和SMS消息相关的敏感用户信息的访问。如果要请求特定于呼叫日志和SMS消息的权限并将应用程序发布到Play商店,则必须提示用户将应用程序设置为核心系统功能默认处理程序,然后再请求这些运行时权限。

有关默认处理程序的更多信息,包括有关向用户显示默认处理程序提示的指南请参阅仅在默认处理程序中使用的权限指南

可选硬件功能的权限

要访问某些硬件功能(例如蓝牙或摄像头),必须获得应用程序许可。但是,并非所有的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>ActivityContext.startActivity()Activity.startActivityForResult()SecurityException

服务许可执行

使用android:permission属性应用于清单中标签的权限限制了谁可以启动或绑定到相关的权限在权限检查 , 和 如果呼叫者没有所需的权限,则会从呼叫中抛出。 <service>ServiceContext.startService()Context.stopService()Context.bindService()SecurityException

广播许可执行

使用android:permission属性对标签应用的权限会限制谁可以将广播发送到关联的返回会检查权限,因为系统会尝试将提交的广播交付给给定的接收者。结果,权限失败不会导致异常被抛出给调用者。它只是不提供。 <receiver>BroadcastReceiver Context.sendBroadcast()Intent

以相同的方式,可以提供权限Context.registerReceiver()来控制谁可以广播到以编程方式注册的接收器。反之,当呼叫Context.sendBroadcast()以限制允许哪些广播接收者接收广播时,可以提供许可

请注意,接收方和广播方都可能需要许可。发生这种情况时,必须通过两个权限检查,才能将意图传递给关联的目标。有关更多信息,请参阅“ 使用权限限制广播”

内容提供者权限执行

使用android:permission属性对标记应用的权限限制了谁可以访问中的数据 (内容提供者有一个重要的附加安全工具可供使用,称为 URI权限,下面将对其进行介绍。)与其他组件不同,可以设置两个单独的许可属性: 限制可以从提供者读取的用户,以及 限制可以写入的用户。它。请注意,如果提供者同时受到读和写权限的保护,则仅持有写许可并不意味着您可以从提供者中进行读取。 <provider>ContentProvider android:readPermission android:writePermission

首次检索提供程序时会检查权限(如果您既没有权限,SecurityException 则抛出a),并且在对提供程序执行操作时会进行检查。使用 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文档中查看每个发行版中添加了哪些权限

防护等级

权限分为几个保护级别。保护级别会影响是否需要运行时权限请求。

有三种影响第三方应用程序的保护级别: 正常签名危险权限。要查看特定权限具有的保护级别,请访问 权限API参考页

普通权限

普通权限涵盖了您的应用需要访问其沙盒之外的数据或资源的区域,但这些区域对用户的隐私或其他应用的操作几乎没有风险。例如,设置时区的权限是普通权限。

如果应用程序在其清单中声明需要正常权限,则系统会在安装时自动向该应用程序授予该权限。系统不会提示用户授予普通权限,并且用户无法撤消这些权限。

签名权限

系统会在安装时授予这些应用程序权限,但仅在尝试使用权限的应用程序与定义该权限的应用程序使用相同的证书签名时。

注意:某些签名权限不适用于第三方应用程序。

危险权限

危险权限涵盖应用程序需要涉及用户私人信息的数据或资源的区域,或可能影响用户存储的数据或其他应用程序的操作的区域。例如,读取用户联系人的功能是危险的权限。如果应用程序声明需要危险的权限,则用户必须向该应用程序明确授予该权限。在用户批准许可之前,您的应用无法提供依赖于该许可的功能。

要使用危险权限,您的应用必须提示用户在运行时授予权限。有关如何提示用户的更多详细信息,请参阅 请求危险权限提示

特殊权限

有一些权限的行为与正常和危险的权限不同。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版本中更改。您的代码不应具有依赖同一组中一组特定权限的逻辑。

查看应用程序的权限

您可以使用“设置”应用程序和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

...

  

 

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

$ adb shell install -g MyApp.apk

  

 

 

原文地址:https://www.cnblogs.com/developer-wang/p/12626772.html