2025-09-08升级问题记录: 升级SDK从Android11到Android12

将 Android 工程的 targetSdkVersion 从 30 (Android 11)升级到 31(Android 12)需要关注一些重要的行为变更和适配点。

主要适配要点:

适配类别 关键变更点 适配紧迫性 简要说明
组件导出属性 声明了 Intent Filter 的组件必须显式设置 android:exported 属性 强制 避免组件被意外调用,提升安全性。
PendingIntent 必须显式声明可变性标志 强制 指定 FLAG_MUTABLEFLAG_IMMUTABLE 以明确意图。
前台服务 限制从后台启动前台服务 强制 除特定情况外,应用在后台时无法启动前台服务。
自定义通知 自定义通知视图使用系统标准模板 强制 自定义通知的内容区域不再覆盖整个通知区域,需检查布局适配性。
应用启动动画 引入新的 SplashScreen API 推荐 提供一致的应用启动体验,建议替换自定义启动页。
隐私和安全 近似位置权限、麦克风和摄像头指示器、剪贴板访问提示等 强制/推荐 增强用户隐私保护,需适配新的权限模型和提示。

1. 组件导出属性 (android:exported)

问题 :在 Android 12 中,所有包含了 intent-filterActivityServiceBroadcast、Receiver 都必须显式声明 android:exported 属性,明确指示该组件是否允许被其他应用调用。

适配方案 :检查你的 AndroidManifest.xml 文件,为所有包含 <intent-filter> 的组件添加 android:exported 属性。

XML 复制代码
<activity
    android:name=".YourActivity"
    android:exported="true"> <!-- 明确设置 exported 值 -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
    </intent-filter>
</activity>

<service
    android:name=".YourService"
    android:exported="false"> <!-- 仅限内部使用 -->
</service>

<receiver
    android:name=".YourReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

注意android:exported="true" 表示允许外部应用调用,false 则表示不允许。缺乏此声明在 Android 12 及以上版本会导致安装失败或运行时错误,如下:

2. PendingIntent 可变性

问题 :Android 12 要求为创建的每个 PendingIntent 对象显式指定其可变性标志:FLAG_MUTABLEFLAG_IMMUTABLE

适配方案 :检查所有创建 PendingIntent 的代码。

java 复制代码
// 创建一个可变的 PendingIntent(通常用于需要被其他应用修改的 Intent)
PendingIntent mutablePendingIntent = PendingIntent.getActivity(
    context,
    requestCode,
    intent,
    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE // 添加 FLAG_MUTABLE
);

// 创建一个不可变的 PendingIntent(安全性更高,推荐只要不需要修改 Intent 就使用此选项)
PendingIntent immutablePendingIntent = PendingIntent.getActivity(
    context,
    requestCode,
    intent,
    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE // 添加 FLAG_IMMUTABLE
);

原则 :如果不需要让其他应用修改你的 PendingIntent 所包装的 Intent优先使用 FLAG_IMMUTABLE,这样更安全。

3. 前台服务启动限制

问题 :Android 12 开始,应用在处于后台时,通常无法启动前台服务 。这是为了节省电量和管理资源。否则会抛出 ForegroundServiceStartNotAllowedException

适配方案

  • 评估需求 :确认是否必须在后台启动前台服务。许多后台任务可以用 WorkManager 来调度和执行。

  • 使用替代方案 :优先考虑使用 WorkManager加急作业(Expedited Work)来处理需要立即执行的后台任务。

java 复制代码
// WorkManager 示例 (使用加急作业)
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(YourWorker.class)
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) // 设置加急
    .build();
WorkManager.getInstance(context).enqueue(request);
  • 检查例外情况:如果你的场景确实符合后台启动前台服务的少数例外条件(例如,由于用户操作,如点击通知、小部件;或者特定的系统事件回调),请确保正确配置并准备好处理可能的异常。

4. 自定义通知样式

问题 :Android 12 改变了完全自定义通知的视觉效果。系统会使用一个标准模板来装饰所有通知,自定义布局只能占据模板内指定区域,而不再是整个通知区域。

适配方案

  • 测试通知外观:务必在 Android 12 设备上测试所有自定义通知,确保布局正确显示。

  • 使用标准样式 :尽可能使用系统的标准通知样式和扩展布局(如 InboxStyle, BigPictureStyle),它们能更好地适应不同版本。

  • 提供展开式布局 :如果必须使用自定义视图,确保同时为展开状态提供布局(setCustomBigContentView)。

5. 应用启动画面 (Splash Screen)

问题 :Android 12 引入了统一的应用启动画面 API (SplashScreen)。系统会为所有应用默认显示一个启动画面,该画面由应用的启动图标和主题的 windowBackground 组成。

适配方案

  • 接受默认效果:如果不介意默认效果,可以不做任何改动。

  • 定制启动画面 (推荐):若要自定义,请使用 Jetpack 的 SplashScreen 兼容库,它可以在 Android 12 之前和之后的版本上提供一致的体验。

  1. 添加依赖:implementation "androidx.core:core-splashscreen:1.0.1"

  2. 定义主题,继承 Theme.SplashScreen

  3. AndroidManifest.xml 中将该主题应用于启动 Activity。

  4. 在 Activity 中安装 Splash Screen。

6. 隐私和安全增强

Android 12 引入了多项隐私改进,部分会影响所有应用,部分仅针对 targetSdkVersion 31+的应用:

  • 近似位置权限 :用户可以仅授予应用大致位置 (模糊位置)权限。如果你的应用需要精确定位,需要在运行时明确向用户解释为何需要,并妥善处理用户只授予大致位置的情况。

  • 麦克风和摄像头指示器 :当应用使用麦克风或摄像头时,状态栏会出现相应图标8。确保你的应用只在必要时访问这些传感器,并妥善处理用户可能因此产生的疑虑。

  • 剪贴板访问提示 :当应用读取来自其他应用 的剪贴板内容时,系统会显示提示 toast8。避免不必要的剪贴板读取。

相关推荐
阿巴斯甜9 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker9 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952710 小时前
Andorid Google 登录接入文档
android
黄林晴11 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android