Android 中的权限

news2024/11/14 3:21:21

1、权限类型

Android 将权限分为不同的类型,包括安装时权限、运行时权限和特殊权限。每种权限类型都指明了当系统授予应用该权限后,应用可以访问的受限数据范围以及应用可以执行的受限操作范围。每项权限的保护级别取决于其类型。

1.1、安装时权限

安装时权限授予应用对受限数据的受限访问权限,或允许应用执行对系统或其他应用只有最低影响的受限操作。如果在应用中声明了安装时权限,应用商店会在用户查看应用详情页面时向其显示安装时权限通知,系统会在用户安装应用时自动向应用授予权限。

Android 提供多个安装时权限子类型,包括一般权限签名权限

一般权限

此类权限允许访问超出应用沙盒的数据和执行超出应用沙盒的操作,但对用户隐私和其他应用的操作风险很小。

系统会为一般权限分配 normal 保护级别。

签名权限

只有当应用与定义权限的应用使用相同的证书签名时,系统才会向应用授予签名权限。

实现特权服务(如自动填充或VPN服务)的应用也会使用签名权限。这些应用需要服务绑定签名权限,以便只有系统可以绑定到服务。

系统会为签名权限分配 signature 保护级别。

1.2、运行时权限

运行时权限也称为危险权限,此类权限授予应用对受限数据的额外访问权限,或允许应用执行对系统和其他应用具有更严重影响的受限操作。需要先在应用中请求运行时权限,然后才能访问受限数据或执行受限操作。请勿假定这些权限之前已经授予过,务必仔细检查,并根据需要在每次访问之前请求这些权限。

当应用请求运行时权限时,系统会显示运行时权限提示。

许多运行时权限会访问用户私人数据,这是一种特殊的受限数据,其中包括可能比较敏感的信息。例如,位置信息和联系信息就属于用户私人数据。

麦克风和摄像头可用于获取特别敏感的信息。因此,该系统会帮助说明应用获取这类信息的原因。

系统会为运行时权限分配 dangerous 保护级别。

1.3、特殊权限

特殊权限与特定的应用操作相对应。只有平台和原始设备制造商 (OEM) 可以定义特殊权限。此外,如果平台和 OEM 想要防止有人执行功能特别强大的操作(例如通过其他应用绘图),通常会定义特殊权限。

系统设置中的特殊应用访问权限页面包含一组用户可切换的操作。其中的许多操作都是以特殊权限的形式实现的。

每项特殊权限都有自己的实现细节。

系统会为特殊权限分配 appop 保护级别。

1.4、权限组

权限可以属于权限组。权限组由一组逻辑相关的权限组成。例如,发送和接收短信的权限可能属于同一组,因为它们都涉及应用与短信的互动。

权限组的作用是在应用请求密切相关的多个权限时,帮助系统尽可能减少向用户显示的系统对话框数量。当系统提示用户授予应用权限时,属于同一组的权限会在同一个界面中显示。但是,权限可能会在不另行通知的情况下更改组,因此不要假定特定权限与任何其他权限组合在一起。

2、声明应用权限

请求权限的过程取决于权限类型:

  • 如果是安装时权限(例如一般权限或签名权限),系统会在安装应用时自动为其授予相应权限。
  • 如果是运行时权限,并且应用安装在搭载 Android 6.0(API 级别 23)或更高版本的设备上,则必须自己请求权限。

2.1、向应用清单添加声明

如需声明应用可能请求的权限,请在应用的清单文件中添加相应的 <uses-permission> 元素。例如,如果应用需要访问相机,则应在 AndroidManifest.xml 中添加以下代码行:

<manifest ...>
    <uses-permission android:name="android.permission.CAMERA"/>
    <application ...>
        ...
    </application>
</manifest>

2.2、将硬件声明为可选

某些权限(例如 CAMERA)可让应用访问只有部分 Android 设备具备的硬件。如果应用声明了这类硬件相关权限,请考虑应用在没有该硬件的设备上是否仍可运行。在大多数情况下,硬件是可选的,因此最好在 <uses-feature> 声明中将 android:required 设置为 false,从而将硬件声明为可选项,如 AndroidManifest.xml 中的以下代码段所示:

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

如果未在 <uses-feature> 声明中将 android:required 设置为 false,则 Android 会假定应用必须在有该硬件的情况下才能运行。因此,系统会阻止某些设备安装应用。

确定硬件可用性

如果将硬件声明为可选,应用在没有该硬件的设备上也可以运行。如需检查设备是否具有特定的硬件,请使用 hasSystemFeature() 方法。如果设备不具有该硬件,只需在应用中停用此功能即可。

// Check whether your app is running on a device that has a front-facing camera.
if (getApplicationContext().getPackageManager().hasSystemFeature(
        PackageManager.FEATURE_CAMERA_FRONT)) {
    // Continue with the part of your app's workflow that requires a
    // front-facing camera.
} else {
    // Gracefully degrade your app experience.
}

2.3、按 API 级别声明权限

如需仅针对支持运行时权限的设备(即搭载 Android 6.0 [API 级别 23] 或更高版本的设备)声明某项权限,请添加 <uses-permission-sdk-23>(而非 <uses-permission>)元素。

使用这些元素中的任意一个时,都可以设置 maxSdkVersion 属性,以指明搭载的 Android 版本高于指定值的设备不需要特定权限。这样,就可以消除不必要的权限,同时仍为旧款设备提供兼容性。

例如,应用可能会显示用户在使用应用时创建的媒体内容,例如照片或视频。在这种情况下,只要应用以 Android 10 或更高版本为目标平台,就无需在搭载 Android 10(API 级别 29)或更高版本的设备上使用 READ_EXTERNAL_STORAGE 权限。不过,为了与旧款设备兼容,可以声明 READ_EXTERNAL_STORAGE 权限并将 android:maxSdkVersion 设置为 28。

3、请求应用权限

3.1、基本原则

在运行时请求权限的基本原则如下:

  • 当用户开始与需要相关权限的功能互动时,在具体使用情境下请求权限。
  • 不要阻止用户使用应用。始终提供选项供用户取消指导界面流程,例如说明请求权限理由的流程。
  • 如果用户拒绝或撤消某项功能所需的权限,请适当降级应用以便让用户可以继续使用应用(可能通过停用需要权限的功能来实现)。
  • 不要对系统行为做任何假设。例如,假设某些权限会出现在同一个权限组中。权限组的作用只是在应用请求密切相关的多个权限时,帮助系统尽可能减少向用户显示的系统对话框数量。

3.2、​请求权限的工作流

在应用中声明并请求运行时权限之前,请评估应用是否需要这样做。无需声明任何权限就可以在应用中实现很多用例,例如拍照、暂停媒体播放和展示相关广告。

如果确定应用需要声明和请求运行时权限,请完成以下步骤:

  1. 在应用的清单文件中,声明应用可能需要请求的权限。
  2. 设计应用的用户体验,使应用中的特定操作与特定运行时权限相关联。告知用户哪些操作可能会要求他们向应用授予访问其私人数据的权限。
  3. 等待用户调用应用中需要访问特定用户私人数据的任务或操作。届时,应用可以请求访问相应数据所需的运行时权限。
  4. 检查用户是否已授予应用所需的运行时权限。如果已授权,那么应用可以访问用户私人数据。如果没有,请继续执行下一步。每次执行需要该权限的操作时,都必须检查自己是否具有该权限。
  5. 检查应用是否应向用户显示理由,说明应用需要用户授予特定运行时权限的原因。如果系统确定应用不应显示理由,请继续直接执行下一步,无需显示界面元素。不过,如果系统确定应用应该显示一个理由,请在界面元素中向用户显示理由,明确说明应用试图访问哪些数据,以及应用获得运行时权限后可为用户提供哪些好处。用户确认理由后,请继续执行下一步。
  6. 请求应用访问用户私人数据所需的运行时权限。系统会显示运行时权限提示,例如权限概览页面上显示的提示。
  7. 检查用户的响应,他们可能会选择同意或拒绝授予运行时权限。
  8. 如果用户向应用授予权限,就可以访问用户私人数据。如果用户拒绝授予该权限,请适当降低应用体验,使应用在未获得受该权限保护的信息时也能向用户提供功能。

3.3、确定应用是否已获得权限

如需检查用户是否已向应用授予特定权限,请将该权限传入 ContextCompat.checkSelfPermission() 方法。根据应用是否具有相应权限,此方法会返回 PERMISSION_GRANTED 或 PERMISSION_DENIED。

//动态检查相机权限
int selfPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
//检查结果
if (selfPermission == PackageManager.PERMISSION_GRANTED) {
    //有许可
} else {
    //无
}

3.4、说明应用为何需要获取权限

系统在调用 requestPermissions() 时显示的权限对话框将说明应用需要哪些权限,但不会解释为何需要这些权限。在某些情况下,用户可能会感到困惑。因此,最好在调用 requestPermissions() 之前向用户解释应用需要相应权限的原因。

研究表明,如果用户知道应用需要权限的原因(例如需要权限来支持应用的核心功能或投放广告),他们会更容易接受权限请求。因此,如果仅使用归入权限组的一小部分 API 调用,明确列出使用哪些权限以及使用原因会非常有用。例如,如果仅使用粗略位置信息,请在应用说明或应用的帮助文章中告知用户。

在特定条件下,让用户实时了解应用在访问敏感数据也是很有帮助的。例如,如果要使用相机或麦克风,最好在应用中的某个位置或在通知栏中(如果应用正在后台运行)使用通知图标通知用户,避免让看上去是在偷偷地收集数据。

从 Android 12(API 级别 31)开始,每当应用使用麦克风或摄像头时,隐私指示标志都会通知用户。

最后,如果需要请求权限以便在应用中运行某项功能,但用户不清楚原因,则需要找到一种方法让用户知道为什么需要最敏感的权限。

如果 ContextCompat.checkSelfPermission() 方法返回 PERMISSION_DENIED,请调用 shouldShowRequestPermissionRationale()。如果此方法返回 true,请向用户显示指导界面,在此界面中说明用户希望启用的功能为何需要特定权限。

此外,如果应用请求与位置信息、麦克风或相机相关的权限,请考虑说明该应用需要访问这些信息的原因。

3.5、请求权限

用户查看指导界面后或者 shouldShowRequestPermissionRationale() 的返回值表明不需要显示指导界面后,可以请求权限。用户会看到系统权限对话框,并可在其中选择是否向应用授予特定权限。

为此,请使用 AndroidX 库中包含的 RequestPermission 协定类,可在其中允许系统替你管理权限请求代码。由于使用 RequestPermission 协定可以简化逻辑,因此建议尽量使用这种解决方案。不过,如果需要,也可以在权限请求过程中自行管理请求代码,并将该请求代码添加到权限回调逻辑中。

3.5.1、允许系统管理权限请求代码

如需允许系统管理与权限请求相关联的请求代码,请在模块的 build.gradle 文件中添加以下库的依赖项:

  • androidx.activity,版本 1.2.0 或更高版本
  • androidx.fragment,版本 1.3.0 或更高版本

然后,可以使用以下某个类:

  • 如需请求一项权限,请使用 RequestPermission。
  • 如需同时请求多项权限,请使用 RequestMultiplePermissions。

以下步骤显示了如何使用 RequestPermission 协定类。使用 RequestMultiplePermissions 协定类的流程基本与此相同。

  1. 在 activity 或 fragment 的初始化逻辑中,将 ActivityResultCallback 的实现传入对 registerForActivityResult() 的调用。ActivityResultCallback 定义应用如何处理用户对权限请求的响应。保留对 registerForActivityResult()(类型为 ActivityResultLauncher)的返回值的引用。
  2. 如需在必要时显示系统权限对话框,请对在上一步中保存的 ActivityResultLauncher 实例调用 launch() 方法。调用 launch() 之后,系统会显示系统权限对话框。当用户做出选择后,系统会异步调用在上一步中定义的 ActivityResultCallback 实现。

处理权限响应:

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher, as an instance variable.
private ActivityResultLauncher<String> requestPermissionLauncher =
    registerForActivityResult(new RequestPermission(), isGranted -> {
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // feature requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    });

检查权限并根据需要向用户请求权限的建议流程:

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user continue
    // using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    // The registered ActivityResultCallback gets the result of this request.
    requestPermissionLauncher.launch(
            Manifest.permission.REQUESTED_PERMISSION);
}

3.5.2、自行管理权限请求代码

作为允许系统管理权限请求代码的替代方法,可以自行管理权限请求代码。为此,请在对 requestPermissions() 的调用中添加请求代码。

应用无法自定义调用 requestPermissions() 时显示的对话框。系统权限对话框中的文本会提及权限组,但此权限分组是为了让系统易于使用。应用不应依赖于特定权限组之内或之外的权限。

使用请求代码来请求权限:

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user continue
    // using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    requestPermissions(CONTEXT,
            new String[] { Manifest.permission.REQUESTED_PERMISSION },
            REQUEST_CODE);
}

当用户响应系统权限对话框后,系统就会调用应用的 onRequestPermissionsResult() 实现。系统会传入用户对权限对话框的响应以及定义的请求代码。

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
        int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            }  else {
                // Explain to the user that the feature is unavailable because
                // the feature requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return;
        }
        // Other 'case' lines to check for other
        // permissions this app might request.
    }
}

3.5.3、请求位置信息权限

请求位置信息权限时,请遵循与请求任何其他运行时权限相同的最佳实践。请求位置权限时的一个重要区别在于,系统中包含与位置相关的多项权限。具体请求哪项权限以及请求相关权限的方式取决于应用用例的位置信息要求。

前台位置信息

如果应用的某项功能仅分享或接收一次位置信息,或者只在特定的一段时间内分享或接收位置信息,则该功能需要前台位置信息访问权限。以下是此类情况的一些示例:

  • 在导航应用中,某项功能可让用户查询精细导航路线。
  • 在即时通讯应用中,某项功能可让用户与其他用户分享自己目前所在的位置。

如果应用的功能在下列某种情况下访问设备的当前位置信息,系统就会认为应用需要使用前台位置信息:

  • 属于应用的某个 activity 可见。
  • 应用的某个前台服务正在运行中。当有前台服务在运行时,系统会显示一条常驻通知来提醒用户注意。当应用被置于后台时(例如当用户按设备上的主屏幕按钮或关闭设备的显示屏时),其位置信息访问权限会得到保留。在 Android 10(API 级别 29)及更高版本中,必须声明前台服务类型 location,如以下代码段所示。在早期版本的 Android 中,建议声明此前台服务类型。
<!-- Recommended for Android 9 (API level 28) and lower. -->
<!-- Required for Android 10 (API level 29) and higher. -->
<service
    android:name="MyNavigationService"
    android:foregroundServiceType="location" ... >
    <!-- Any inner elements go here. -->
</service>

当应用请求 ACCESS_COARSE_LOCATION 权限或 ACCESS_FINE_LOCATION 权限时,就是在声明需要获取前台位置信息。

<manifest ... >
  <!-- Include this permission any time your app needs location information. -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

  <!-- Include only if your app benefits from precise location access. -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

后台位置信息

如果应用中的某项功能会不断与其他用户分享位置信息或使用 Geofencing API,则该应用需要后台位置信息访问权限。以下是此类情况的几个示例:

  • 在家庭位置信息分享应用中,某项功能可让用户与家庭成员持续分享位置信息。
  • 在 IoT 应用中,某项功能可让用户配置自己的家居设备,使其在用户离家时关机并在用户回家时重新开机。

除了前台位置信息部分所述的情况之外,如果应用在任何其他情况下访问设备的当前位置信息,系统就会认为应用需要使用后台位置信息。后台位置信息精确度与前台位置信息精确度相同,具体取决于应用声明的位置信息权限。

在 Android 10(API 级别 29)及更高版本中,必须在应用的清单中声明 ACCESS_BACKGROUND_LOCATION 权限,以便请求在运行时于后台访问位置信息。在较低版本的 Android 系统中,当应用获得前台位置信息访问权限时,也会自动获得后台位置信息访问权限。

<manifest ... >
  <!-- Required only when requesting background location access on
       Android 10 (API level 29) and higher. -->
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

Google Play 商店设置了有关设备位置的位置信息政策,限制应用仅在实现核心功能所必需的情形下且在满足相关政策要求后才能请求后台位置信息访问权限。 

3.6、处理权限请求遭拒情况

如果用户拒绝了权限请求,应用应该帮助用户了解拒绝授予权限的影响。具体而言,应用应该让用户知道因缺少权限而无法使用哪些功能。在处理这种情况时,请牢记以下最佳做法:

  • 引导用户的注意力。在应用界面中突出显示因为应用没有获得必要的权限而受限的功能所在的具体部分。以下示例说明了可以采取的做法:
  1. 在原本用于显示该功能的结果或数据的位置显示一条消息。
  2. 显示一个包含错误图标并带有相应错误颜色的不同按钮。
  • 内容要具体。显示的消息不要空泛,而要指出因为应用没有获得必要的权限而无法使用的具体功能。
  • 不要阻止界面显示。换言之,不要显示全屏警告消息,让用户根本无法继续使用应用。

即使在权限请求遭拒后,应用也应尽可能提供最佳的用户体验。例如,即使麦克风使用权限请求遭拒,仍应全面提高文本功能的易用性。

与此同时,应用还应尊重用户拒绝授予权限的决定。从 Android 11(API 级别 30)开始,在应用安装到设备上后,如果用户在使用过程中多次针对某项特定的权限点按拒绝,那么在应用再次请求该权限时,用户将不会看到系统权限对话框。该操作表示用户希望“不再询问”。在之前的版本中,除非用户先前已选中“不再询问”复选框或选项,否则每当应用请求权限时,用户都会看到系统权限对话框。

如果用户多次拒绝某项权限请求,则会被视为永久拒绝请求。仅在用户需要使用特定功能时提示用户授予权限,这一点非常重要;否则,可能会无意中失去重新请求权限的能力。

在某些情况下,系统可能会自动拒绝权限,而无需用户执行任何操作(系统也可能会自动授予权限)。请千万不要对系统的自动行为做出任何假设。每当应用需要使用的功能需要权限时,请检查应用是否仍被授予该权限。

3.7、单次授权

从 Android 11(API 级别 30)开始,每当应用请求与位置、麦克风或相机相关的权限时,面向用户的权限对话框都会包含仅限这一次选项。如果用户在对话框中选择此选项,系统会向应用授予临时的单次授权。

然后,应用可以在一段时间内访问相关数据,具体时间取决于应用的行为和用户的操作:

  • 当应用的 activity 可见时,应用可以访问相关数据。
  • 如果用户将应用转为后台运行,应用可以在短时间内继续访问相关数据。
  • 如果在 activity 可见时启动了一项前台服务,并且用户随后将应用转到后台,那么应用可以继续访问相关数据,直到该前台服务停止。

应用进程在权限被撤消时终止

如果用户撤消单次授权(例如在系统设置中撤消),无论是否启动了前台服务,应用都无法访问相关数据。与任何权限一样,如果用户撤消了应用的单次授权,应用进程就会终止。

当用户下次打开应用并且应用中的某项功能请求访问位置信息、麦克风或摄像头时,系统会再次提示用户授予权限。

注意:如果应用在请求运行时权限时已遵循最佳实践,那么无需在应用中添加或更改任何逻辑即可支持单次授权。

3.8、重置未使用的权限

Android 提供了多种方法来将未使用的运行时权限重置为默认的拒绝状态:

  • API,可主动取消应用对未使用的运行时权限的访问权限。
  • 系统机制,可自动重置未使用的应用的权限。

取消应用访问权限

在 Android 13(API 级别 33)及更高版本中,可以取消应用对不再需要的运行时权限的访问权限。更新应用时,请执行此步骤,以便用户更有可能了解应用继续请求特定权限的原因。这些信息有助于建立用户对应用的信任。

如需取消对运行时权限的访问权限,请将该权限的名称传递到 revokeSelfPermissionOnKill()。如需同时取消对一组运行时权限的访问权限,请将这组权限名称传递到 revokeSelfPermissionsOnKill()。权限取消过程是异步执行的,会终止与应用 UID 关联的所有进程。

注意:为了让系统设置显示应用不会访问特定权限组中的数据,必须取消对该权限组中的所有权限的访问权限。在这种情况下,调用 revokeSelfPermissionsOnKill() 并传入权限组内的多项权限会很有帮助。

为了让系统取消应用对权限的访问权限,必须终止与应用关联的所有进程。当调用该 API 时,系统会确定何时可以安全终止这些进程。通常,系统会等待应用在后台(而不是在前台)运行较长的时间。

要通知用户应用不再需要对特定运行时权限的访问权限,请在用户下次启动应用时显示一个对话框。此对话框可以包含权限列表。

自动重置未使用的应用的权限

如果应用以 Android 11(API 级别 30)或更高版本为目标平台并且数月未使用,系统会通过自动重置用户已授予应用的运行时敏感权限来保护用户数据。

3.9、在必要时请求成为默认处理程序

有些应用依赖于访问与通话记录和短信有关的敏感用户信息。如果想请求特定于通话记录和短信的权限,并将应用发布到 Play 商店,必须在请求这些运行时权限之前,提示用户将应用设置为核心系统功能的默认处理程序。

3.10、授予所有运行时权限以进行测试

如需在模拟器或测试设备上安装应用时自动授予所有运行时权限,请为 adb shell install 命令使用 -g 选项,如以下代码段所示:

adb shell install -g PATH_TO_APK_FILE

4、解释对比较敏感信息的访问权限

在授予应用与位置信息、麦克风和相机相关的权限后,应用可以访问关于用户的特别敏感的信息。该平台包含多种机制,可帮助用户及时了解和控制哪些应用可以访问位置信息、麦克风和相机。

这些隐私保护系统功能应该不会影响应用处理与位置信息、麦克风和相机相关的权限的方式,但前提是遵循隐私设置最佳做法。

具体来说,请确保在对应用执行相关操作时做到以下几点:

  • 等到用户向应用授予 CAMERA 权限后再使用设备的相机。
  • 等到用户向应用授予 RECORD_AUDIO 权限后再使用设备的麦克风。
  • 等到用户与应用中某项需要获取位置信息的功能互动后再请求 ACCESS_COARSE_LOCATION 权限或 ACCESS_FINE_LOCATION 权限,如介绍如何请求位置信息权限的指南中所述。
  • 等到用户向应用授予 ACCESS_COARSE_LOCATION 权限或 ACCESS_FINE_LOCATION 权限后再请求 ACCESS_BACKGROUND_LOCATION 权限。

4.1、隐私信息中心

在搭载 Android 12 或更高版本的受支持设备上,系统设置中会显示“隐私信息中心”屏幕。在此屏幕上,用户可以访问一些单独的屏幕,这些屏幕显示了应用何时访问位置信息、相机和麦克风信息。每个屏幕都会显示一个时间轴,指明不同的应用何时访问过特定类型的数据。

显示数据访问的理由

应用可以向用户提供一个理由,帮助他们了解为什么应用访问位置信息、相机或麦克风信息。此理由可以显示在新的“隐私信息中心”屏幕和/或应用的权限屏幕上。

如需解释为什么应用访问位置信息、相机和麦克风信息,请完成以下步骤:

  • 添加一个 activity,它在启动后会提供某种理由,说明为什么应用执行特定类型的数据访问操作。在此 activity 中,将 android:permission 属性设置为 START_VIEW_PERMISSION_USAGE。如果应用以 Android 12 或更高版本为目标平台,必须明确地为 android:exported 属性定义一个值。
  • 向新添加的 activity 添加以下 intent 过滤器:
<!-- android:exported required if you target Android 12. -->
<activity android:name=".DataAccessRationaleActivity"
          android:permission="android.permission.START_VIEW_PERMISSION_USAGE"
          android:exported="true">
       <!-- VIEW_PERMISSION_USAGE shows a selectable information icon on
            your app permission's page in system settings.
            VIEW_PERMISSION_USAGE_FOR_PERIOD shows a selectable information
            icon on the Privacy Dashboard screen. -->
    <intent-filter>
       <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
       <action android:name="android.intent.action.VIEW_PERMISSION_USAGE_FOR_PERIOD" />
       <category android:name="android.intent.category.DEFAULT" />
       ...
    </intent-filter>
</activity>
  • 决定数据访问理由 activity 应显示什么内容。例如,可以显示应用的网站或帮助中心文章。如需提供更详细的解释来说明应用访问的数据类型以及访问发生的时间,请处理系统在调用权限使用 intent 时包含的 extra:
  1. 如果系统调用 ACTION_VIEW_PERMISSION_USAGE,应用可以检索 EXTRA_PERMISSION_GROUP_NAME 的值。
  2. 如果系统调用 ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD,应用可以检索 EXTRA_PERMISSION_GROUP_NAME、EXTRA_ATTRIBUTION_TAGS、EXTRA_START_TIME 和 EXTRA_END_TIME 的值。

根据添加的 intent 过滤器,用户会在某些屏幕上看到应用的名称旁边有一个信息图标:

  • 如果添加包含 VIEW_PERMISSION_USAGE 操作的 intent 过滤器,用户会在系统设置中的应用权限页面上看到该图标。可以将该操作应用于所有运行时权限。
  • 如果添加包含 VIEW_PERMISSION_USAGE_FOR_PERIOD 操作的 intent 过滤器,每当应用显示在“隐私信息中心”屏幕中,用户都会在应用的名称旁边看到该图标。

当用户选择该图标时,系统会启动应用的理由 activity。

4.2、指示标志

注意:本部分提到的图标不应要求更改应用的逻辑,前提是遵循隐私设置最佳做法。

在搭载 Android 12 或更高版本的设备上,当应用使用麦克风或相机时,图标会出现在状态栏中。如果应用处于沉浸模式,图标会出现在屏幕的右上角。用户可以打开“快捷设置”,并选择图标以查看哪些应用当前正在使用麦克风或摄像头。

确定指示标志在屏幕上的位置

如果应用支持沉浸模式或全屏界面,指示标志可能会与应用界面短暂重叠。为协助应用界面适应这些指示标志,系统引入了 getPrivacyIndicatorBounds() 方法,如下方的代码段所示。利用此 API,可以确定指示标志可能出现的边界。然后,可能会决定以不同的布局安排屏幕界面。

4.3、切换开关

注意:本部分提到的切换开关不应要求更改应用的逻辑,前提是遵循隐私设置最佳做法。

在搭载 Android 12 或更高版本的受支持设备上,用户可以通过按一个切换开关选项,为设备上的所有应用启用和停用摄像头和麦克风使用权限。用户可以从快捷设置访问可切换的选项,也可以从系统设置中的“隐私设置”屏幕访问。

摄像头和麦克风切换开关会影响设备上的所有应用:

  • 当用户关闭摄像头访问权限后,应用会收到空白的摄像头画面。
  • 当用户关闭麦克风使用权限后,应用会收到无声音频。此外,无论是否声明 HIGH_SAMPLING_RATE_SENSORS 权限,移动传感器都有采样率限制。

注意:当用户拨打应急服务电话时,系统会开启麦克风使用权限。此行为可保护用户安全。

当用户关闭摄像头或麦克风的使用权限,然后启动需要使用摄像头或麦克风信息的应用时,系统会提醒用户,设备范围的切换开关已关闭。

4.4、检查设备支持情况

如需检查设备是否支持麦克风和摄像头切换开关,请添加以下代码段中所示的逻辑:

SensorPrivacyManager sensorPrivacyManager = getApplicationContext()
        .getSystemService(SensorPrivacyManager.class);
boolean supportsMicrophoneToggle = sensorPrivacyManager
        .supportsSensorToggle(Sensors.MICROPHONE);
boolean supportsCameraToggle = sensorPrivacyManager
        .supportsSensorToggle(Sensors.CAMERA);

5、仅在默认处理程序中使用的权限

多种核心设备功能(例如,读取通话记录和发送短信)都依赖于访问敏感的用户信息。为了保护用户隐私并让用户更好地控制他们为设备上的应用提供的信息,Google Play 会限制应用对与通话和短信相关的权限组的访问权。

如果在 Google Play 商店分发应用,并想要访问与通话记录和短信相关的敏感用户信息,应用需要注册为与该权限相关的核心设备功能的用户默认处理程序,除非应用满足 Play 管理中心帮助中心内显示的任意一种例外情况。例如,为了获取与通话相关的权限,应用需要注册为用户的默认电话或 Google 助理处理程序,除非应用满足某种例外情况。

本指南简要概述了用户如何访问搭载 Android 的设备上的默认处理程序;然后介绍了应用必须满足哪些要求才有资格成为默认处理程序;最后详细介绍了应用征求用户同意以成为默认处理程序的过程。

5.1、查看和更改默认处理程序集

Android 允许用户为拨打电话、发送短信和提供辅助技术功能等多种核心使用场景设置默认处理程序。

Android“设置”应用中的一个界面向用户显示了哪些应用目前为设备核心功能的默认处理程序,用户可以在此屏幕中更改特定功能的默认处理程序。

5.2、遵守对默认处理程序的要求 

鉴于应用在充当默认处理程序时会访问敏感的用户信息,因此,只有满足以下 Play 商品详情和核心功能要求的应用才可成为默认处理程序:

  • 应用必须能够执行其作为默认处理程序所负责的功能。例如,默认短信处理程序必须能够发送短信。
  • 应用必须提供隐私权政策。
  • 应用必须在 Play 商店说明中清晰阐述其核心功能。例如,默认电话处理程序应在说明中描述其与电话相关的功能。
  • 应用必须声明与其使用场景相符的权限。如需详细了解特定处理程序可声明哪些权限,请参阅 Play 管理中心帮助内有关使用短信或通话记录权限组的指南。
  • 应用必须先请求成为默认处理程序,然后才能请求与成为该处理程序相关的权限。例如,应用必须先请求成为默认短信处理程序,然后才能请求 READ_SMS 权限。

5.3、征求用户同意

在确保应用遵守成为默认处理程序所需满足的各项要求之后,可以添加逻辑以显示询问用户是否要更改设备的默认短信处理程序的提示。此对话框要求用户针对特定使用场景将应用设置为默认处理程序。

应用必须先请求成为默认处理程序,然后才能请求与成为该处理程序相关联的权限。例如,应用必须先请求成为默认短信处理程序,然后才能请求 READ_SMS 权限。

以下示例代码展示了显示询问用户是否同意更改设备默认短信处理程序的提示所需的逻辑:

Intent setSmsAppIntent =
        new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
setSmsAppIntent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
        getPackageName());
startActivityForResult(setSmsAppIntent, your-result-code);

6、限制与其他应用的交互

权限不仅仅用于请求获取系统功能的使用权。还可以限制其他应用与应用组件互动的方式。

本指南介绍了如何查看其他应用已声明的权限集,还介绍了如何配置 activity、服务、content provider 和广播接收器来限制其他应用与你的应用互动的方式。

注意:如果要仅限与某一个开发者提供的应用进行互动(例如,为了保证进程间通信的安全),建议使用自定义签名权限。

6.1、查看其他应用的权限

如需查看其他应用声明的权限集,请使用设备或模拟器完成以下步骤:

  • 打开应用的应用信息屏幕。
  • 选择权限。系统会加载应用权限屏幕。此屏幕会显示一系列权限组。系统会将应用所声明的权限整理到这些权限组内。

还可以通过其他一些实用方式来检查权限:

  • 在调用某项服务期间,将权限字符串传入 Context.checkCallingPermission()。此方法会返回一个整数,指示当前调用进程是否已获授权限。请注意,仅在执行从另一个进程传入的调用(通常是通过从服务发布的 IDL 接口或提供给另一进程的某种其他方式来实现)时,才可使用此方法。
  • 如需检查另一进程是否已获得特定权限,请将该进程 (PID) 传入 Context.checkPermission()。
  • 如需检查其他软件包是否已获得特定权限,请将该软件包的名称传入 PackageManager.checkPermission()。

6.2、限制与应用的 activity 的互动

对清单中的 <activity> 标记使用 android:permission 属性,以限制哪些其他应用可以启动该 Activity。系统会在 Context.startActivity() 和 Activity.startActivityForResult() 期间检查该权限。如果调用方没有所需的权限,将会发生 SecurityException。

6.3、限制与应用的服务的互动

对清单中的 <service> 标记使用 android:permission 属性,以限制哪些其他应用可以启动或绑定到关联的 Service。系统会在 Context.startService()、Context.stopService() 和 Context.bindService() 期间检查该权限。如果调用方没有所需的权限,将会发生 SecurityException。

6.4、限制与应用的 content provider 的互动

对 <provider> 标记使用 android:permission 属性,以限制哪些其他应用可以访问 ContentProvider 中的数据。(content provider 有重要的附加安全工具可供其使用,称为 URI 权限,将在下一部分介绍。)与其他组件不同,可以为 content provider 设置两个单独的权限属性:android:readPermission,用于限制哪些其他应用可以从 provider 读取数据;以及 android:writePermission,用于限制哪些其他应用可以向其写入数据。请注意,如果某个 provider 有读取权限和写入权限保护,则仅拥有写入权限并不允许应用从该 provider 读取数据。

第一次检索 provider 以及应用对 provider 执行操作时,系统会检查这些权限。如果发出请求的应用没有任何相应权限,则会发生 SecurityException。使用 ContentResolver.query() 需要读取权限;使用 ContentResolver.insert()、ContentResolver.update() 或 ContentResolver.delete() 需要写入权限。在所有这些情况下,没有所需的权限将会导致 SecurityException。

根据 URI 授予权限

可以进一步对其他应用如何访问应用的 content provider 进行精细控制。具体而言,content provider 可以利用读取和写入权限保护自己,同时仍允许其直接客户端与其他应用共享特定 URI。如需声明应用支持此模式,请使用 android:grantUriPermissions 属性或 <grant-uri-permission> 元素。

还可以根据 URI 授予权限。在启动 activity 或将结果返回给 activity 时,请设置 Intent.FLAG_GRANT_READ_URI_PERMISSION intent 标志、Intent.FLAG_GRANT_WRITE_URI_PERMISSION intent 标志或者同时设置两者。这会分别为其他应用授予对 intent 中包含的数据 URI 的读取、写入或读取/写入权限。无论从更笼统的角度来说其他应用是否有权访问 content provider 中的数据,它都会获得针对该 URI 的上述权限。

例如,假设用户正在使用应用查看包含图片附件的电子邮件。一般来说,其他应用本该无法访问电子邮件内容,但它们可能希望查看这张图片。应用可以结合使用 intent 和 Intent.FLAG_GRANT_READ_URI_PERMISSION intent 标志,以便图片查看应用能够查看这张图片。

另一个需要考虑的因素是应用可见性。如果应用以 Android 11(API 级别 30)或更高版本为目标平台,在默认情况下,系统会自动让部分应用对应用可见,并隐藏其他应用。如果应用具有 content provider,并且已向其他应用授予 URI 权限,那么应用会自动对该应用可见。

如需了解详情,请查看介绍 grantUriPermission()、revokeUriPermission() 和 checkUriPermission() 方法的参考资料。

6.5、限制与应用的广播接收器的互动

对 <receiver> 标记使用 android:permission 属性,以限制哪些其他应用可以向关联的 BroadcastReceiver 发送广播。系统会在 Context.sendBroadcast() 返回后检查该权限,此时系统会尝试将提交的广播传递到指定的接收器。这意味着权限错误不会导致向调用方抛回异常;只是不会传递该 Intent。

同样,可以向 Context.registerReceiver() 提供权限,用于控制哪些其他应用可以向程序化地注册的接收器发送广播。另一方面,可以在调用 Context.sendBroadcast() 时提供权限,用于限制哪些广播接收器可以接收广播。

请注意,接收器和广播方可能都需要权限。发生这种情况时,两项权限检查都必须顺利通过,系统才会将 intent 传递到关联的目标。

7、定义自定义应用权限

Android 是一种权限分离的操作系统,其中每个应用都以不同的系统身份(Linux 用户 ID 和组 ID)运行。系统的各个部分也会被分隔为不同的身份。因此,Linux 可以将应用同其他应用和系统隔离开来。

应用可以定义其他应用可请求的权限,从而将自己的功能提供给后者。它们还可以定义能够自动提供给已使用同一证书进行签名的任何其他应用的权限。

7.1、应用签名

所有 APK 都必须使用证书进行签名,证书的私钥由其开发者持有。此证书可标识应用创作者。证书无需由证书授权机构进行签名;Android 应用完全可以使用自签名证书,这种做法也十分普遍。Android 中的证书旨在区分应用创作者。这样,系统可以授予或拒绝应用对签名级权限的访问权限,以及同意或拒绝应用获取与另一应用相同的 Linux 身份的请求。

7.2、用户 ID 和文件访问权限

安装时,Android 会为每个软件包提供不同的 Linux 用户 ID。只要软件包在该设备上存续,在此期间其身份将保持不变。同一软件包在其他设备上可具有不同的 UID;重要的是每个软件包在指定设备上的 UID 是唯一的。

由于系统会在进程级别强制执行安全措施,因此任何两个软件包的代码通常都无法在同一进程中运行,因为它们需要以不同的 Linux 用户身份运行。您可以在每个软件包的 AndroidManifest.xml 的 清单标记中使用 sharedUserId 属性为它们分配相同的用户 ID。这样做以后,出于安全考虑,系统随后会将这两个软件包视为具有相同用户 ID 和文件权限的同一应用。请注意,为了确保安全性,只有具有相同签名(以及请求了相同 sharedUserId)的两个应用才能够获得相同的用户 ID。

系统会为应用存储的所有数据分配该应用的用户 ID,而其他软件包通常无法访问这些数据。

如需详细了解 Android 的安全模型,请参阅 Android 安全性概览。

7.3、定义并强制执行权限

如需强制执行自己的权限,您首先必须使用一个或多个 <permission> 元素在您的 AndroidManifest.xml 中声明它们。

例如,某个应用若要控制谁可以启动它的 Activity,可以针对此操作声明一个权限,如下所示:

<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.example.myapp" >
    
    <permission
      android:name="com.example.myapp.permission.DEADLY_ACTIVITY"
      android:label="@string/permlab_deadlyActivity"
      android:description="@string/permdesc_deadlyActivity"
      android:permissionGroup="android.permission-group.COST_MONEY"
      android:protectionLevel="dangerous" />
    ...
</manifest>

注意:系统不允许多个软件包声明同名权限,除非所有软件包均使用同一证书进行签名。如果软件包声明了某个权限,系统不会允许用户安装其他具有相同权限名称的软件包,除非这些软件包使用与第一个软件包相同的证书进行签名。在为自定义权限命名时,为了避免命名冲突,我们建议采用反向域名方式,例如 com.example.myapp.ENGAGE_HYPERSPACE。

protectionLevel 属性为必需项,用于指示系统如何向用户告知哪些应用正在请求权限或者谁可以获得该权限,如链接的文档中所述。

android:permissionGroup 属性为可选项,仅用于帮助系统向用户显示权限。在大多数情况下,您应将其设置为标准系统组(在 android.Manifest.permission_group 中列出),但您也可以自行定义组。最好使用现有的组,因为这可以简化用户看到的权限界面。

您需要为权限提供标签和说明。这些是用户在查看权限列表 (android:label) 或有关单个权限的详细信息 (android:description) 时能够看到的字符串资源。标签应当简短,用几个词描述该权限所保护的关键功能。说明应该用几个句子描述权限允许权限获得者执行哪些操作。我们通常会使用包含两个句子的说明:第一句描述权限;第二句提醒用户在向应用授予权限后可能会出现哪类错误。

以下示例展示了 CALL_PHONE 权限的标签和说明:

<string name="permlab_callPhone">directly call phone numbers</string>
<string name="permdesc_callPhone">Allows the app to call
    phone numbers without your intervention. Malicious apps may
    cause unexpected calls on your phone bill. Note that this does not
    allow the app to call emergency numbers.</string>

7.4、创建权限组

如上一部分中所示,您可以使用 android:permissionGroup 属性帮助系统向用户说明权限。在大多数情况下,您需要将此属性设置为标准系统组(在 android.Manifest.permission_group 中列出),但您也可以使用 <permission-group> 定义自己的组。

<permission-group> 元素为一组权限定义标签,这一组权限可以包括使用 <permission> 元素在清单中声明的权限和在其他位置声明的权限。此元素只会影响权限在向用户显示时的分组方式。<permission-group> 元素并不指定属于该组的权限,而是为该组提供名称。

将组名称分配给 <permission> 元素的 permissionGroup 属性可将权限放入组中。

<permission-tree> 元素为代码中定义的一组权限声明命名空间。

7.5、自定义权限建议

应用可以定义自己的自定义权限,还可以通过定义 <uses-permission> 元素向其他应用请求自定义权限。不过,您应该仔细评估应用是否有必要这样做。

  • 如果要设计一套向彼此公开功能的应用,请尽可能将应用设计为每个权限仅定义一次。如果这些应用并非全都使用同一证书进行签名,那么您就必须这样做。即使应用均使用同一证书进行签名,每个权限仅定义一次也是最佳做法。
  • 如果功能仅适用于与提供该功能的应用具有相同签名的应用,您也许能使用签名检查功能来避免定义自定义权限。如果您的某个应用向您的另一个应用发出请求,后者会先验证两者是否使用相同的证书进行签名,只有证书相同时才会遵照该请求行事。

8、权限API参考文档:

https://developer.android.com/reference/android/Manifest.permissionhttps://developer.android.com/reference/android/Manifest.permission

ACCEPT_HANDOVER
允许呼叫应用继续在另一个应用中启动的呼叫

ACCESS_BACKGROUND_LOCATION
允许应用程序在后台访问位置

ACCESS_BLOBS_ACROSS_USERS
允许应用程序跨用户访问数据块

ACCESS_CHECKIN_PROPERTIES
允许对checkin数据库中的“properties”表进行读/写操作,改值可以修改上传

ACCESS_COARSE_LOCATION
允许应用程序访问大致位置

ACCESS_FINE_LOCATION
允许应用程序访问精确位置

ACCESS_LOCATION_EXTRA_COMMANDS
允许应用程序访问额外的位置提供程序命令

ACCESS_MEDIA_LOCATION
允许应用程序访问用户共享集合中保留的任何地理位置

ACCESS_NETWORK_STATE
允许应用程序访问有关网络的信息

ACCESS_NOTIFICATION_POLICY
标记希望访问通知策略的应用程序的权限

ACCESS_WIFI_STATE
允许应用程序访问有关Wi-Fi网络的信息

ACCOUNT_MANAGER
允许应用程序调用帐户验证器

ACTIVITY_RECOGNITION
允许应用程序活动识别

ADD_VOICEMAIL
允许应用程序将语音邮件添加到系统中

ANSWER_PHONE_CALLS
允许应用程序接听来电

BATTERY_STATS
允许应用程序收集电池统计信息
保护级别:签名|特权|开发

BIND_ACCESSIBILITY_SERVICE
必须是辅助功能服务所要求的,以确保只有系统才能绑定到它

BIND_APPWIDGET
允许应用程序告诉应用程序控件服务哪个应用程序可以访问应用程序控件的数据

BIND_AUTOFILL_SERVICE
必须是自动填充服务所要求的,以确保只有系统才能绑定到它

BIND_CALL_REDIRECTION_SERVICE
必须是呼叫重定向服务所要求的,以确保只有系统才能绑定到它

BIND_CARRIER_MESSAGING_CLIENT_SERVICE
必须使用此权限保护运营商消息客户端服务的子类

BIND_CARRIER_MESSAGING_SERVICE
API level 23中不推荐使用此常量。请改用BIND_CARRIER_SERVICES

BIND_CARRIER_SERVICES
允许绑定到运营商应用程序中的服务的系统进程将具有此权限

BIND_CHOOSER_TARGET_SERVICE
API level 30中不推荐使用此常量。有关发布直接共享目标,请遵循说明:https://developer.android.com/training/sharing/receive.html#providing-direct-share-targets

BIND_COMPANION_DEVICE_SERVICE
必须是任何配套设备服务所要求的,以确保只有系统才能绑定到它。当智能手表、手环等设备可用时,安装在Android手机上的配套应用能够被及时唤醒并保持连接

BIND_CONDITION_PROVIDER_SERVICE
必须是条件提供程序服务所要求的,以确保只有系统才能绑定到它

BIND_CONTROLS
允许系统界面请求第三方控件

BIND_DEVICE_ADMIN
必须由设备管理接收器要求,以确保只有系统才能与其交互

BIND_DREAM_SERVICE
必须是DreamService所要求的,以确保只有系统才能绑定到它

BIND_INCALL_SERVICE
必须是呼叫中服务所要求的,以确保只有系统才能绑定到它

BIND_INPUT_METHOD
必须是输入方法服务所必需的,以确保只有系统才能绑定到它

BIND_MIDI_DEVICE_SERVICE
必须是MidiDevice服务所要求的,以确保只有系统才能绑定到它

BIND_NFC_SERVICE
必须是HostApduService或OffHostApduServices所要求的,以确保只有系统才能绑定到它。如NFC卡功能

BIND_NOTIFICATION_LISTENER_SERVICE
必须是通知监听服务所必需的,以确保只有系统才能绑定到它

BIND_PRINT_SERVICE
必须是打印服务所要求的,以确保只有系统才能绑定到它

BIND_QUICK_ACCESS_WALLET_SERVICE
必须是快捷钱包服务所要求的,以确保只有系统才能绑定到它

BIND_QUICK_SETTINGS_TILE
允许应用程序绑定到第三方快速设置

BIND_REMOTEVIEWS
必须是远程视图服务所必需的,以确保只有系统才能绑定到它

BIND_SCREENING_SERVICE
必须是呼叫筛选服务所要求的,以确保只有系统才能绑定到它

BIND_TELECOM_CONNECTION_SERVICE
必须是连接服务所必需的,以确保只有系统才能绑定到它

BIND_TEXT_SERVICE
必须是文本服务(例如拼写检查器服务)要求的,以确保只有系统才能绑定到它

BIND_TV_INPUT
必须是电视输入服务所要求的,以确保只有系统才能绑定到它

BIND_TV_INTERACTIVE_APP
必须是电视互动应用服务要求的,以确保只有系统才能绑定到它

BIND_VISUAL_VOICEMAIL_SERVICE
必须是链接可视语音邮件服务所必需的,以确保只有系统才能绑定到它

BIND_VOICE_INTERACTION
必须是语音交互服务所要求的,以确保只有系统才能绑定到它

BIND_VPN_SERVICE
必须是VPN服务所要求的,以确保只有系统才能绑定到它

BIND_VR_LISTENER_SERVICE
必须是VR监听服务所必需的,以确保只有系统才能绑定到它

BIND_WALLPAPER
必须是壁纸服务所要求的,以确保只有系统才能绑定到它

BLUETOOTH
允许应用程序连接到配对的蓝牙设备

BLUETOOTH_ADMIN
允许应用程序发现和配对蓝牙设备

BLUETOOTH_ADVERTISE
需要能够向附近的蓝牙设备发布广告

BLUETOOTH_CONNECT
需要能够连接到配对的蓝牙设备

BLUETOOTH_PRIVILEGED
允许应用程序在无需用户交互的情况下配对蓝牙设备,并允许或禁止电话簿访问或消息访问

BLUETOOTH_SCAN
需要能够发现和配对附近的蓝牙设备

BODY_SENSORS
允许应用程序访问来自传感器的数据,用户使用这些传感器来测量体内发生的情况,例如心率

BODY_SENSORS_BACKGROUND
允许应用程序访问来自传感器的数据,用户使用这些传感器来测量体内发生的情况,例如心率

BROADCAST_PACKAGE_REMOVED
允许应用程序广播应用程序包已删除的通知

BROADCAST_SMS
允许应用程序广播SMS接收通知

BROADCAST_STICKY
允许应用程序广播粘性意图

BROADCAST_WAP_PUSH
允许应用程序广播WAP推送接收通知

CALL_COMPANION_APP
允许实现呼叫服务API的应用程序有资格作为呼叫配套应用程序启用

CALL_PHONE
允许应用程序启动电话呼叫,而无需通过拨号器用户界面,以便用户确认呼叫

CALL_PRIVILEGED
允许应用程序拨打任何电话号码,包括紧急电话号码,而无需通过拨号器用户界面让用户确认正在拨打的电话

CAMERA
需要能够访问摄像机设备

CAPTURE_AUDIO_OUTPUT
允许应用程序捕获音频输出

CHANGE_COMPONENT_ENABLED_STATE
允许应用程序更改是否启用应用程序组件(而不是其自身的组件)

CHANGE_CONFIGURATION
允许应用程序修改当前配置,例如区域设置

CHANGE_NETWORK_STATE
允许应用程序更改网络连接状态

CHANGE_WIFI_MULTICAST_STATE
允许应用程序进入Wi-Fi多播模式

CHANGE_WIFI_STATE
允许应用程序更改Wi-Fi连接状态

CLEAR_APP_CACHE
允许应用程序清除设备上所有已安装应用程序的缓存

CONTROL_LOCATION_UPDATES
允许启用/禁用来自无线的位置更新通知

DELETE_CACHE_FILES
删除应用程序缓存文件的旧权限,已不再使用,但这意味着我们要悄悄忽略调用,而不是抛出异常

DELETE_PACKAGES
允许应用程序删除包

DELIVER_COMPANION_MESSAGES
允许应用程序向系统传递配套消息

DIAGNOSTIC
允许应用程序RW访问诊断资源

DISABLE_KEYGUARD
允许应用程序禁用键盘保护(如果它不安全)

DUMP
允许应用程序从系统服务检索状态转储信息

EXPAND_STATUS_BAR
允许应用程序展开或折叠状态栏

FACTORY_TEST
作为制造商测试应用程序运行,作为根用户运行

FOREGROUND_SERVICE
允许常规应用程序使用Service.startForeground

GET_ACCOUNTS
允许访问帐户服务中的帐户列表

GET_ACCOUNTS_PRIVILEGED
允许访问帐户服务中的帐户列表

GET_PACKAGE_SIZE
允许应用程序查找任何包使用的空间

GET_TASKS
API level 21中已弃用此常量。不再强制执行

GLOBAL_SEARCH
此权限可用于内容提供商,以允许全局搜索系统访问其数据

HIDE_OVERLAY_WINDOWS
允许应用程序防止在其上绘制非系统覆盖窗口

HIGH_SAMPLING_RATE_SENSORS
允许应用程序访问采样率大于200 Hz的传感器数据

INSTALL_LOCATION_PROVIDER
允许应用程序将位置提供程序安装到位置管理器中

INSTALL_PACKAGES
允许应用程序安装软件包

INSTALL_SHORTCUT
允许应用程序在Launcher中安装快捷方式

INSTANT_APP_FOREGROUND_SERVICE
允许即时应用程序创建前台服务

INTERACT_ACROSS_PROFILES
允许在同一配置文件组中跨配置文件进行交互

INTERNET
允许应用程序打开网络连接

KILL_BACKGROUND_PROCESSES
允许应用程序调用ActivityManager.killBackgroundProcesses()

LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK
应用程序需要此权限才能进行设置。ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY显示其嵌入设置应用程序中的Activity

LOADER_USAGE_STATS
允许数据加载器读取包的访问日志

LOCATION_HARDWARE
允许应用程序使用硬件中的位置功能,例如地理围栏api

MANAGE_DOCUMENTS
允许应用程序管理对文档的访问,通常作为文档选择器的一部分

MANAGE_EXTERNAL_STORAGE
允许应用程序广泛访问作用域存储中的外部存储

MANAGE_MEDIA
允许应用程序修改和删除此设备或任何连接的存储设备上的媒体文件,而无需用户确认

MANAGE_ONGOING_CALLS
允许查询正在进行的通话详细信息并管理正在进行的呼叫
保护级别:签名| appop

MANAGE_OWN_CALLS
允许调用应用程序通过自管理的ConnectionService API管理自己的调用

MANAGE_WIFI_INTERFACES
允许应用程序在不拆除一个或多个其他接口的情况下无法满足Wi-Fi接口请求时获得通知,并提供批准还是拒绝请求的决定

MANAGE_WIFI_NETWORK_SELECTION
此权限用于让OEM授予其受信任的应用程序访问特权wifi API的子集,以提高wifi性能

MASTER_CLEAR
不供第三方应用程序使用

MEDIA_CONTENT_CONTROL
允许应用程序知道正在播放的内容并控制其播放

MODIFY_AUDIO_SETTINGS
允许应用程序修改全局音频设置

MODIFY_PHONE_STATE
允许修改电话状态,如开机、mmi码等

MOUNT_FORMAT_FILESYSTEMS
允许格式化可移动存储的文件系统

MOUNT_UNMOUNT_FILESYSTEMS
允许为可移动存储装载和卸载文件系统

NEARBY_WIFI_DEVICES
需要能够通过Wi-Fi发布广告并连接到附近的设备

NFC
允许应用程序通过NFC执行I/O操作

NFC_PREFERRED_PAYMENT_INFO
允许应用程序接收NFC首选支付服务信息

NFC_TRANSACTION_EVENT
允许应用程序接收NFC交易事件

OVERRIDE_WIFI_CONFIG
允许应用程序修改任何wifi配置,即使是由其他应用程序创建的

PACKAGE_USAGE_STATS
允许应用程序收集组件使用统计信息
声明权限意味着有意使用API,设备用户可以通过设置应用程序授予权限

PERSISTENT_ACTIVITY
API level 15中已弃用此常量。此功能将在将来删除;请不要使用。允许应用程序使其活动持久化

POST_NOTIFICATIONS
允许应用发布通知
防护等级:危险

PROCESS_OUTGOING_CALLS
API level 29中不推荐使用此常量。应用程序应使用CallRedirectionService而不是Intent.ACTION_NEW_OUTGOING_CALL广播

QUERY_ALL_PACKAGES
允许查询设备上的任何正常应用程序,而不考虑清单声明

READ_ASSISTANT_APP_SEARCH_DATA
允许应用程序在AppSearch中查询ASSISTANT角色可见的全局数据

READ_BASIC_PHONE_STATE
允许以非危险权限只读访问手机状态,包括蜂窝网络类型、软件版本等信息

READ_CALENDAR
允许应用程序读取用户的日历数据

READ_CALL_LOG
允许应用程序读取用户的呼叫日志

READ_CONTACTS
允许应用程序读取用户的联系人数据

READ_EXTERNAL_STORAGE
允许应用程序从外部存储读取数据

READ_HOME_APP_SEARCH_DATA
允许应用程序查询对HOME角色可见的AppSearch中的全局数据

READ_INPUT_STATE
API level 16中不推荐使用此常量。已删除使用此权限的API

READ_LOGS
允许应用程序读取低级系统日志文件

READ_MEDIA_AUDIO
允许应用程序从外部存储读取音频文件

READ_MEDIA_IMAGES
允许应用程序从外部存储读取图像文件

READ_MEDIA_VIDEO
允许应用程序从外部存储读取视频文件

READ_NEARBY_STREAMING_POLICY
允许应用程序读取附近的流策略

READ_PHONE_NUMBERS
允许读取设备的电话号码

READ_PHONE_STATE
允许只读访问电话状态,包括当前蜂窝网络信息、任何正在进行的通话的状态以及设备上注册的任何电话帐户的列表

READ_PRECISE_PHONE_STATE
允许只读访问精确的电话状态

READ_SMS
允许应用程序读取短信

READ_SYNC_SETTINGS
允许应用程序读取同步设置

READ_SYNC_STATS
允许应用程序读取同步统计信息

READ_VOICEMAIL
允许应用程序读取系统中的语音邮件

REBOOT
需要重新启动设备

RECEIVE_BOOT_COMPLETED
允许应用程序接收在系统完成引导后广播的Intent.ACTION_BOOT_COMPLETED

RECEIVE_MMS
允许应用程序监视传入的彩信

RECEIVE_SMS
允许应用程序接收短信

RECEIVE_WAP_PUSH
允许应用程序接收WAP推送消息

RECORD_AUDIO
允许应用程序录制音频

REORDER_TASKS
允许应用程序更改任务的Z顺序。

REQUEST_COMPANION_PROFILE_APP_STREAMING
允许应用程序请求与能够通过CompanionDeviceManager流式传输Android应用程序(AssociationRequest.DEVICE_PROFILE_APP_STREAMING)的虚拟显示器关联

REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION
允许应用程序请求与CompanionDeviceManager能够自动投影的车辆主机单元(AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION)关联

REQUEST_COMPANION_PROFILE_COMPUTER
允许应用程序请求与计算机关联,以与其他设备共享功能和/或数据,例如CompanionDeviceManager提供的通知、照片和媒体(AssociationRequest.DEVICE_PROFILE_COMPUTER)

REQUEST_COMPANION_PROFILE_WATCH
允许应用程序通过CompanionDeviceManager请求作为“监视”与设备关联
保护等级:正常

REQUEST_COMPANION_RUN_IN_BACKGROUND
允许配套应用程序在后台运行

REQUEST_COMPANION_SELF_MANAGED
允许应用程序创建“自我管理”关联

REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
允许配套应用程序从后台启动前台服务

REQUEST_COMPANION_USE_DATA_IN_BACKGROUND
允许配套应用程序在后台使用数据

REQUEST_DELETE_PACKAGES
允许应用程序请求删除包

REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
应用程序必须持有的权限才能使用Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS

REQUEST_INSTALL_PACKAGES
允许应用程序请求安装软件包

REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE
允许应用程序订阅有关其关联同伴设备的状态更改的通知

REQUEST_PASSWORD_COMPLEXITY
允许应用程序请求屏幕锁定复杂性,并提示用户将屏幕锁定更新到特定的复杂性级别

RESTART_PACKAGES
API level 15中不推荐使用此常量。不再支持ActivityManager.restartPackage() API

SCHEDULE_EXACT_ALARM
允许应用程序使用精确的报警API

SEND_RESPOND_VIA_MESSAGE
允许应用程序(电话)向其他应用程序发送请求,以便在来电时通过消息操作处理响应

SEND_SMS
允许应用程序发送短信

SET_ALARM
允许应用程序广播意向,为用户设置警报

SET_ALWAYS_FINISH
允许应用程序控制活动在置于后台时是否立即完成

SET_ANIMATION_SCALE
修改全局动画缩放因子

SET_DEBUG_APP
配置应用程序以进行调试

SET_PREFERRED_APPLICATIONS
此常量在API level 15中已弃用。不再有用,请参阅PackageManager.addPackageToPreferred() 获取详细信息

SET_PROCESS_LIMIT
允许应用程序设置可以运行的最大应用程序进程数(不需要)

SET_TIME
允许应用程序直接设置系统时间

SET_TIME_ZONE
允许应用程序直接设置系统时区

SET_WALLPAPER
允许应用程序设置壁纸

SET_WALLPAPER_HINTS
允许应用程序设置壁纸提示

SIGNAL_PERSISTENT_PROCESSES
允许应用程序请求向所有持久进程发送信号

SMS_FINANCIAL_TRANSACTIONS
API level 31中不推荐使用此常量。使用此权限的API不再起作用

START_FOREGROUND_SERVICES_FROM_BACKGROUND
允许应用程序随时从后台启动前台服务

START_VIEW_APP_FEATURES
允许持有者使用应用程序功能列表启动屏幕

START_VIEW_PERMISSION_USAGE
允许持有者启动应用程序的权限使用屏幕

STATUS_BAR
允许应用程序打开、关闭或禁用状态栏及其图标

SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE
允许应用程序订阅键盘锁定(即显示)状态

SYSTEM_ALERT_WINDOW
允许应用程序使用WindowManager.LayoutParams.type_APPLICATION_OVERLAY类型创建窗口,该类型显示在所有其他应用程序的顶部

TRANSMIT_IR
允许使用设备的红外发射器(如果可用)

UNINSTALL_SHORTCUT
不要在应用中使用此权限

UPDATE_DEVICE_STATS
允许应用程序更新设备统计信息

UPDATE_PACKAGES_WITHOUT_USER_ACTION
允许应用程序通过PackageInstaller.SessionParams.setRequireUserAction(int) 进行指示,表示应用程序更新不需要用户操作。

USE_BIOMETRIC
允许应用程序使用设备支持的生物特征模式

USE_EXACT_ALARM
允许应用程序使用与SCHEDULE_exact_ALARM相同的精确报警,但无需向用户请求此权限

USE_FINGERPRINT
API level 28中不推荐使用此常量。应用程序应改为请求USE_BIOMETRIC

USE_FULL_SCREEN_INTENT
针对Build.VERSION_CODES.Q的应用程序需要使用通知全屏intent。比如微信来语音或者视频通话时,弹出的接听页面就是使用这一功能

USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
允许读取设备标识符并使用基于ICC的身份验证,如EAP-AKA

USE_SIP
允许应用程序使用SIP服务

UWB_RANGING
需要能够覆盖使用超宽带的设备

VIBRATE
允许访问手机振动器

WAKE_LOCK
允许使用电源管理器唤醒锁定来防止处理器休眠或屏幕变暗

WRITE_APN_SETTINGS
允许应用程序写入apn设置并读取现有apn设置的敏感字段,如用户和密码

WRITE_CALENDAR
允许应用程序写入用户的日历数据

WRITE_CALL_LOG
允许应用程序写入(但不读取)用户的呼叫日志数据

WRITE_CONTACTS
允许应用程序写入用户的联系人数据

WRITE_EXTERNAL_STORAGE
允许应用程序写入外部存储

WRITE_GSERVICES
允许应用程序修改Google服务地图

WRITE_SECURE_SETTINGS
允许应用程序读取或写入安全系统设置

WRITE_SETTINGS
允许应用程序读取或写入系统设置

WRITE_SYNC_SETTINGS
允许应用程序写入同步设置

WRITE_VOICEMAIL
允许应用程序修改和删除系统中现有的语音邮件

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

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

相关文章

智慧农业发展,商业计划书撰写,商业模式,ppt亮点

目录 什么是商业模式 中华人民共和国国民经济和社会发展第十四个五年规划和2035年远景目标纲要_滚动新闻_中国政府网 第五篇 加快数字化发展 建设数字中国 第十五章 打造数字经济新优势 第十六章 加快数字社会建设步伐 第十七章 提高数字政府建设水平 第十八章 营造…

Linux下载安装 RabbitMQ​

压缩包&#xff1a;RabbitMQ-Linux版-Java文档类资源-CSDN下载 一、官网下载&#xff1a; 1、需要先下载RabbitMQ所需要的erl语言环境 官网地址&#xff1a;Downloads - Erlang/OTP 2、下载MQ 官网&#xff1a;Messaging that just works — RabbitMQgithub地址&#xff1a;…

一篇文章,教你彻底掌握接口测试!

Part 01、什么是接口测试 所谓接口&#xff0c;是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据库的对接。而接口测试&#xff0c;则是通过接口的不同情况下的输入&#xff0c;去对比输出&#xff0c;看看是否满足接口规范所规定的功能、安全以及…

【设计模式】外观模式(Facade Pattern)

外观模式属于结构型模式&#xff0c;主要解决客户程序访问复杂程序中的多个子程序而产生的高耦合度及高复杂度问题&#xff0c;根本目的在于简化接口的调用。例如我们去医院看病&#xff0c;可能要去挂号、门诊、划价、取药&#xff08;子系统角色&#xff09;&#xff0c;这让…

Redis主从复制、哨兵模式、集群模式

文章目录一、Redis主从复制主从复制流程Redis主从复制的作用二、哨兵模式1、哨兵模式集群架构2、哨兵模式主要功能3、哨兵监控整个系统节点的过程4、主观下线5、客观下线6、master 选举7、故障迁移8、优点与缺点三、Cluster群集1、集群的作用2、Redis集群的数据分片四、实验一&…

Linux||使用vi编辑器按上下键输出字母

一、问题描述 在终端执行sudo命令时&#xff0c;系统提示“vboxuser is not in the sudoers file.This incident will be reported”&#xff0c;因此需要修改/etc/sudoers文件。 使用Linux自带的vi编辑器修改/etc/sudoers文件时候&#xff0c;按i键进入编辑模式。使用键盘上下…

SD-Branch多分支组网解决方案

一、多分支组网建设背景 多分支一般是指行政上由总部和分支单位组成&#xff0c;总部和各分支处在地域不同的区域&#xff1b;由于业务访问需要&#xff0c;组网要求“总部-分支”互联打通。多分支网络组网方案主要针对的是总分企业、金融网点、连锁酒店、连锁门店、商超地产、…

组合预测 | MATLAB实现基于BP-Adaboost强分类器多特征分类预测

组合预测 | MATLAB实现基于BP-Adaboost强分类器多特征分类预测 目录 组合预测 | MATLAB实现基于BP-Adaboost强分类器多特征分类预测预测效果基本介绍模型特性程序设计参考资料预测效果 基本介绍 MATLAB实现基于BP-Adaboost强分类器多特征分类预测。在集成学习-Boosting,Bagging…

如何建立公司网站?【公司网站建设】

现在很多实体公司企业都会做一个自己的公司网站&#xff0c;毕竟一个网站等同于一张在互联网中的名片&#xff0c;可以让更多客户了解到你。那么如何建立公司网站&#xff1f;流程步骤大概是什么&#xff1f;今天给大家简单讲解一下。 一、注册域名 这个域名是就是网址&#…

学编程:Python入门考级必备[8]

目录 知识模块(8) 列表知识——井然有序 1.列表的创建 2.列表访问(查找操作) 3.列表增加操作 4.列表删除操作 5.统计与计算 附件代码&#xff1a; 炼 知识模块(8) 列表知识——井然有序 知识模块(8) 列表知识——井然有序 1.列表的创建 1.1 空列表&#xff1a; lie …

[Linux](16)网络编程:网络概述,网络基本原理,套接字,UDP,TCP,并发服务器编程,守护(精灵)进程

文章目录网络协议初识OSI 七层模型TCP/IP 四层(或五层)模型IP、MAC、端口号TCP 协议与 UDP 协议套接字套接字地址结构socket 函数bind 函数recvfrom 函数sendto 函数UDP 通信实现服务端客户端TCP 通信实现服务端listen 函数accept 函数实现客户端connect 函数实现改进&#xff…

项目中集成高德地图

如果文章对你有帮助欢迎【关注❤️❤️❤️点赞&#x1f44d;&#x1f44d;&#x1f44d;收藏⭐⭐⭐】一键三连&#xff01;一起努力&#xff01; 本文我们主要讲述的是怎么在自己的项目中集成高德地图。 一、注册账号并申请Key 首先我们打开浏览器&#xff0c;直接百度&…

python小知识--创建scrapy工程步骤

python小知识--创建scrapy工程步骤前言python中的scrapy框架是我们在平时使用爬虫使用比较多的框架首先第一步就是创建scrapy工程&#xff0c;下面通过pycharm软件来演示效果图1、右击文件名称选择open in terminal打开终端cmd2、在终端控制台输入scrapy startproject kuaikank…

grafana alert告警面板配置说明

grafana alert告警面板配置说明 前提&#xff1a;只有graph panel 也就是图表面板&#xff08;一般都是折线图和柱状图或者点状图&#xff09;可以添加Alert &#xff0c;其他面板不支持。 Rule Name &#xff1a;Alert规则 的名称 每多少时间评估一次 如果配置了这个参数&…

安卓APP源码和设计报告——基于Android的垃圾分类系统

《移动应用开发》大作业报告 题 目基于Android的垃圾分类系统系 部班 级学 生 姓 名学 号指 导 教 师时 间 1、项目名称 垃圾分类系统 2、项目概述 近些年&#xff0c;由于人民生活水平是的提高&#xff0c;生活方式与生活节奏的加快&#xff0c;使我国的垃圾生产数量已远超…

Flink系列之Flink之Time和WaterMark深入剖析

title: Flink系列 一、Flink Window 常见需求背景 1.0 理论描述 需求描述&#xff1a; 每隔 5 秒&#xff0c;计算最近 10 秒单词出现的次数。 滑动窗口 每隔 5 秒&#xff0c;计算最近 5 秒单词出现的次数。 滚动窗口 第一个&#xff1a; 关于 TimeCharacteristic Process…

[附源码]Python计算机毕业设计Django医疗纠纷处理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[附源码]Python计算机毕业设计Django校园一卡通服务平台

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

HarmonyOS/OpenHarmony应用开发-FA卡片开发体验

卡片概述 卡片是一种界面展示形式&#xff0c;可以将应用的重要信息或操作前置到卡片&#xff0c;以达到服务直达&#xff0c;减少体验层级的目的。 卡片常用于嵌入到其他应用&#xff08;当前只支持系统应用&#xff09;中作为其界面的一部分显示&#xff0c;并支持拉起页面…

[附源码]Python计算机毕业设计Django校园疫情管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…