通知运行时权限

Android 13(API 级别 33)及更高版本支持用于从应用发送非豁免(包括前台服务 [FGS])通知的运行时权限:POST_NOTIFICATIONS。此项变更有助于用户专注于对他们最重要的通知。

强烈建议您尽快以 Android 13 或更高版本为目标平台,以利用此功能提供的额外控制能力和灵活性。如果您继续以 12L(API 级别 32)或更低版本为目标平台,您将 失去在应用功能环境中请求权限的某些灵活性

声明权限

如需向应用请求新的通知权限,请将应用更新为以 Android 13 为目标平台,并完成与请求其他运行时权限类似的流程,如以下几个部分所述。

需要在应用的清单文件中声明的权限会显示 在以下代码段中:

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

应用功能取决于用户在权限对话框中所做的选择

在此对话框中,用户可以执行以下操作:

下面几个部分介绍了根据用户操作的不同,应用会有哪些不同的行为表现。

用户选择“允许”

如果用户选择允许选项,您的应用可以执行以下操作:

用户选择“不允许”

如果用户选择不允许 选项,您的应用将无法发送 通知,除非该应用符合豁免条件。除了几个特定角色之外,所有通知渠道都会被屏蔽。这类似于用户在系统设置中手动关闭应用的所有通知后发生的行为。

注意:如果您的应用以 12L 或更低版本为目标平台 ,并且用户点按不允许(即使仅点按一次),那么系统不会再次提示用户 ,直到发生以下任一情况:

  • 用户卸载并重新安装您的应用。
  • 您将应用更新为以 Android 13 或更高版本为目标平台。

用户滑开对话框

如果用户滑开对话框(即未选择 允许不允许 ),通知权限的状态不会 发生变化。

对新安装的应用的影响

如果用户在搭载 Android 13 或更高版本的设备上安装您的应用,则应用的通知默认处于关闭状态 。在您请求新的权限且用户向您的应用授予该权限之前,您的应用都将无法发送通知。

权限对话框的显示时间取决于应用的目标 SDK 版本:

  • 如果您的应用以 Android 13 或更高版本为目标平台,则应用可以完全控制权限对话框的显示时间。您可以借此机会向用户说明应用需要此权限的原因,鼓励他们授予该权限。
  • 如果您的应用以 12L(API 级别 32)或更低版本为目标平台,系统会显示 该权限对话框,具体时机为:在您 创建通知渠道后您的应用首次启动 activity 时,或在您的应用启动一个 activity,然后 创建它的第一个通知渠道时。这通常是在应用启动时。 在单 activity 应用(例如大多数 Compose 应用)中,系统会在 MainActivity 启动时显示该对话框。

对现有应用更新的影响

为了最大限度地减少与通知权限相关的中断,当用户 将其设备升级到 Android 13 或更高版本后,系统 会自动向所有符合条件的应用预先授予相应权限。换言之,这些应用可以继续向用户发送通知,而用户不会看到运行时权限提示。

预先授予权限的资格条件

您的应用要获得自动预先授权必须满足以下条件:应用必须已具有通知渠道,并且用户未在搭载 12L 或更低版本的设备上明确停用应用的通知。

如果用户在搭载 12L 或更低版本的设备上停用了应用的通知,当设备升级到 Android 13 或更高版本后,该停用会继续有效。

豁免

此部分列出了一些不受通知权限行为变更影响的通知和应用。在 Android 13(API 级别 33)或更高版本中,如果用户拒绝授予通知权限,他们仍会在 任务管理器 中看到与前台服务相关的通知,但在 通知抽屉中不会看到此类通知。

媒体会话

媒体会话有关的通知不受此行为 变更的影响。

配置为自行管理通话的应用

如果您将应用配置为自行管理通话,那么您无需 POST_NOTIFICATIONS权限即可让应用发送使用 Notification.CallStyle通知样式的通知。

如果您的应用执行以下每项操作,系统就会认为您的应用已将自己配置为自行管理通话:

  1. 声明 MANAGE_OWN_CALLS 权限。
  2. 实现 ConnectionService 接口。
  3. 通过调用 registerPhoneAccount()向设备的电信服务提供商注册。

测试应用

您可以评估以下因素:当您的应用在搭载 Android 13 或更高版本的设备上首次使用时,通知权限对此应用有何影响。借助以下几组 Android 调试桥 (adb) 命令,您可以模拟最常见的用户选择和设备升级顺序,而无需重置测试设备:

  • 应用新安装在搭载 Android 13 或更高版本的设备上:

    adb shell pm revoke PACKAGE_NAME android.permission.POST_NOTIFICATIONS
    adb shell pm clear-permission-flags PACKAGE_NAME \
      android.permission.POST_NOTIFICATIONS user-set
    adb shell pm clear-permission-flags PACKAGE_NAME \
      android.permission.POST_NOTIFICATIONS user-fixed
  • 当应用安装在搭载 Android 12L 或更低版本的设备上时,用户让通知保持启用状态,然后设备升级到 Android 13 或更高版本:

    adb shell pm grant PACKAGE_NAME android.permission.POST_NOTIFICATIONS
    adb shell pm set-permission-flags PACKAGE_NAME \
      android.permission.POST_NOTIFICATIONS user-set
    adb shell pm clear-permission-flags PACKAGE_NAME \
      android.permission.POST_NOTIFICATIONS user-fixed
  • 当应用安装在搭载 Android 12L 或更低版本的设备上时,用户手动停用通知,然后设备升级到 Android 13 或更高版本:

    adb shell pm revoke PACKAGE_NAME android.permission.POST_NOTIFICATIONS
    adb shell pm set-permission-flags PACKAGE_NAME \
      android.permission.POST_NOTIFICATIONS user-set
    adb shell pm clear-permission-flags PACKAGE_NAME \
      android.permission.POST_NOTIFICATIONS user-fixed

最佳实践

本部分将介绍几种在应用中最有效地使用新通知权限的方式。

更新应用的目标 SDK 版本

为了让应用更灵活地显示权限对话框,请将应用更新为以 Android 13 或更高版本为目标平台。

等待一段时间再显示通知权限提示

等到用户熟悉您的应用之后,再请求他们授予任何权限。

新用户可能想要探索应用,并亲身体验每个通知请求的好处。您可以根据用户操作 触发权限提示。下面列举了几个适合显示通知权限提示的时机:

  • 用户点按“提醒铃铛”按钮时。
  • 用户选择关注他人的社交媒体账号时。
  • 用户提交外卖订单时。

图 1 显示了请求通知权限的建议工作流程。除非 shouldShowRequestPermissionRationale() 返回 true,否则您的应用无需显示中间屏幕(即标题文本为“获取通知!”的屏幕)。在 Compose 中,您可以通过访问 LocalContext.current 并将其转换为 Activity 来查找当前 Activity

或者,您可以设置一个请求,在用户有机会熟悉您的应用后显示该屏幕。例如,您可以等到用户第三次或第四次启动应用时再显示。

用户登录后,系统会向用户显示获取行程更新通知的邀请。当用户按“I&#39;m in”按钮后,应用会请求新权限,这时会显示系统对话框
图 1. 关于请求通知权限的建议用户驱动工作流程。仅当 shouldShowRequestPermissionRationale() 返回 true 时,才有必要显示中间屏幕。

在 Compose 中请求权限

如需在 Compose 界面中请求权限,请使用 rememberLauncherForActivityResult() API 和 ActivityResultContracts.RequestPermission() 合约。

以下代码段展示了如何响应用户互动来请求通知权限:

Kotlin

val context = LocalContext.current
val permissionLauncher = rememberLauncherForActivityResult(
    ActivityResultContracts.RequestPermission()
) { isGranted ->
    if (isGranted) {
        // Permission granted, you can now send notifications.
    } else {
        // Permission denied, handle accordingly.
    }
}

// ... in your UI ...
Button(onClick = {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
    }
}) {
    Text("Enable Notifications")
}

在上下文中请求权限

在应用内请求通知权限时,请在正确的上下文中请求,以便用户明确了解通知的用途以及应该选择接收通知的原因。例如,电子邮件应用可能包含为每封新邮件发送通知的选项,或仅为用户是唯一收件人的邮件发送通知的选项。

借此机会明确向用户表明您的意图,有助于鼓励用户向您的应用授予通知权限。

检查您的应用能否发送通知

在应用发送通知之前,请确认用户是否已为您的应用启用 通知。如需执行此操作,请调用 areNotificationsEnabled()

以负责任的方式使用权限

获得发送通知的许可后,请以负责任的方式使用该权限。用户可以查看您的应用每天发送的通知数量,并且可以随时撤消该权限。