3. AndroidManifest.xml 权限声明:POST_NOTIFICATIONS
在 Android 13 (API 33) 中,通知权限从以往的“安装即授权”转变为“运行时权限”。应用必须先在 AndroidManifest.xml 中静态声明 POST_NOTIFICATIONS 权限,才能在实际运行时向系统请求用户授权。本章将围绕该声明的原理、标准写法、检查手段以及常见踩坑点展开。
3.1 原理:为何需要静态声明
Android 权限系统中,普通权限(Normal Permissions)在安装时自动授予;危险权限(Dangerous Permissions)则需运行时动态申请。Android 13 将 POST_NOTIFICATIONS 归类为危险权限,因此必须满足两个条件:
- 在
AndroidManifest.xml中使用<uses-permission>标签声明 - 运行时调用
requestPermissions()或ActivityResultLauncher获取用户同意
静态声明是动态请求的前提——若缺少声明,系统将在运行时直接拒绝授权,且不会弹出对话框。
| Android 版本 | 通知权限管理方式 | 是否需声明 POST_NOTIFICATIONS |
|---|---|---|
| Android 12 及更低 | 安装即授权,应用可随时发送通知 | 否(声明会被忽略) |
| Android 13+ | 运行时危险权限,需用户授权 | 是(必须声明) |
3.2 实现流程
在项目的 src/main/AndroidManifest.xml 文件中,将权限声明放置在 <manifest> 根元素下、<application> 元素之前。标准写法如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourapp">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
...>
...
</application>
</manifest>
android:maxSdkVersion 属性以避免低版本上无意义的权限声明(虽然并无副作用),但更常见的做法是直接声明,系统在低版本会自动忽略。
3.3 声明后的验证与调试
声明完成后,可以通过以下两种方式验证权限是否被正确识别:
- 编译检查: 运行
./gradlew assembleDebug,Gradle 不会因权限声明报错;若存在拼写错误(如POST_NOTIFICATIONS写成POST_NOTIFICATION),编译器会提示“Permission name not found”。 - ADB 命令检查: 安装应用后,使用
adb shell dumpsys package <包名>查看权限列表:
adb shell dumpsys package com.example.yourapp | grep -A 10 "runtime-permissions"
输出中应出现类似如下条目:
android.permission.POST_NOTIFICATIONS: granted=false, flags=[ REVOKE_WHEN_REQUESTED ]
若未出现该条目,说明 Manifest 中未正确声明或 targetSdkVersion 未升至 33+。
3.4 常见错误及规避
<uses-permission> 必须写在 <manifest> 的直接子级,不能放在 <application> 内部。否则编译期可能不报错,但运行时权限无法被识别。
android.permission.POST_NOTIFICATIONS(注意复数 NOTIFICATIONS)。误写为 NOTIFICATION(单数)将导致编译失败。
build.gradle 中 targetSdkVersion 未设置到 33 或以上,即使声明了权限,系统也不会将其视为危险权限,用户将无法在设置中看到开关,应用也不会触发运行时授权流程。
3.5 性能与稳定性说明
静态权限声明本身对 APK 体积、启动时间、运行时性能无任何影响。它只是一个可被 PackageManager 解析的 XML 条目。唯一可能影响稳定性的场景是:忘记声明 会导致运行时 SecurityException,或 shouldShowRequestPermissionRationale() 返回 false 且无法弹出授权框。因此,在构建时加入 lint 检查规则可预先拦截遗漏:
android {
lintOptions {
check 'MissingPermission'
}
}
3.6 章节核心流程示意
本图为本章(第 3 章)的核心内容——权限声明在整个适配流程中的位置,以及 AndroidManifest.xml 内部应如何组织标签。确保声明无误后,即可进入第 4 章的运行时授权实现。