一张表看懂 Android 8-15 所有适配要点

一张表看懂 Android 8-15 所有适配要点

Android 系统每年发布一个新版本,每个版本都有行为变更和新的限制。本文以表格形式汇总 Android 8 到 Android 15 所有需要适配的核心要点,方便开发者快速查阅。建议收藏,新版本发布后会持续更新。


一、快速查阅总表

Android 版本 API 发布年份 必须适配的核心变更 适配优先级
8.0 Oreo 26 2017 通知渠道、后台执行限制 中(旧设备)
9.0 Pie 28 2018 Apache HTTP 移除、前台服务权限 中(旧设备)
10 Q 29 2019 分区存储、后台启动 Activity 限制 高(大量设备)
11 R 30 2020 包可见性、单次权限
12 S 31 2021 SplashScreen API、PendingIntent 可变性
13 Tiramisu 33 2022 通知权限、精细化媒体权限
14 Upside Down Cake 34 2023 前台服务类型、广播注册导出声明
15 Vanilla Ice Cream 35 2024 Edge-to-Edge、16KB 页面、前台服务超时 高(Google Play 强制)

二、Android 8.0(API 26)适配要点

变更 影响 适配方案
通知渠道(Notification Channel) targetSdk ≥ 26 必须创建渠道才能显示通知 使用 NotificationChannel 创建渠道
后台执行限制 对后台应用限制 Service 和 Broadcast 改用 JobIntentServiceWorkManager
安装 APK 需要权限 安装 APK 需要 REQUEST_INSTALL_PACKAGES 权限 在 Manifest 中声明权限,并引导用户授权
透明 Activity 限制 不允许透明主题的全屏 Activity 移除透明主题或改为 Dialog 样式

代码示例:创建通知渠道

kotlin 复制代码
// Android 8.0+ 必须创建通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    val channel = NotificationChannel(
        "default_channel_id",
        "默认通知渠道",
        NotificationManager.IMPORTANCE_DEFAULT
    ).apply {
        description = "默认渠道描述"
    }
    val notificationManager = getSystemService(NotificationManager::class.java)
    notificationManager.createNotificationChannel(channel)
}

三、Android 9.0(API 28)适配要点

变更 影响 适配方案
Apache HTTP 客户端移除 使用了 org.apache.http 的应用会崩溃 在 Manifest 中添加 useLibrary 'org.apache.http.legacy'
前台服务需要权限 启动前台服务需要 FOREGROUND_SERVICE 权限 在 Manifest 中声明权限
刘海屏适配 需要适配 DisplayCutout 使用 WindowInsets.getDisplayCutout()
HTTPS 网络请求限制 默认禁止明文流量(HTTP) 创建 res/xml/network_security_config.xml 允许明文流量,或全量迁移到 HTTPS

代码示例:允许明文流量(仅调试环境)

xml 复制代码
<!-- res/xml/network_security_config.xml -->
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">example.com</domain>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
    </domain-config>
</network-security-config>

<!-- AndroidManifest.xml 中 application 标签添加 -->
android:networkSecurityConfig="@xml/network_security_config"

四、Android 10(API 29)适配要点

变更 影响 适配方案
Scoped Storage(分区存储) 外部存储访问受限 使用 MediaStore 访问媒体文件
后台启动 Activity 限制 不能直接从后台启动 Activity 使用通知引导用户点击,或申请 SYSTEM_ALERT_WINDOW 权限
深色模式(Dark Mode) 系统级深色模式 适配 DayNight 主题
手势导航适配 需要处理 Window Insets 使用 ViewCompat.setOnApplyWindowInsetsListener

代码示例:兼容深色模式

kotlin 复制代码
// styles.xml(日间主题)
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <item name="colorPrimary">@color/primary</item>
    <item name="colorPrimaryDark">@color/primaryDark</item>
</style>

// colors.xml 中提供日间和夜间两套颜色
// values/colors.xml → 日间颜色
// values-night/colors.xml → 夜间颜色

五、Android 11(API 30)适配要点

变更 影响 适配方案
包可见性(Package Visibility) 查询其他应用需要声明 <queries> 在 Manifest 中添加 <queries> 元素
单次权限(One-time Permission) 位置、麦克风、摄像头支持单次授权 无需额外适配,系统自动处理
权限对话框频繁请求限制 用户在短时间内拒绝两次后,第三次不再弹出对话框 引导用户到设置页面授权
前台服务类型 需要指定前台服务类型(Android 14 强制) 提前声明 foregroundServiceType

代码示例:声明包可见性

xml 复制代码
<!-- 查询所有已安装应用(需要权限) -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />

<!-- 或精确声明需要查询的应用 -->
<queries>
    <package android:name="com.example.targetapp" />
    <intent>
        <action android:name="android.intent.action.SEND" />
    </intent>
</queries>

六、Android 12(API 31)适配要点

变更 影响 适配方案
SplashScreen API 统一启动页规范 使用 SplashScreen 兼容库
PendingIntent 必须声明可变性 不声明会崩溃 显式指定 FLAG_MUTABLEFLAG_IMMUTABLE
前台服务通知延迟 前台服务启动后通知会延迟显示 无需适配,了解行为变化即可
蓝牙权限细化 旧蓝牙权限废弃 使用 BLUETOOTH_SCAN / BLUETOOTH_CONNECT
精确闹钟权限 需要 SCHEDULE_EXACT_ALARM 权限 请求权限或使用非精确闹钟

代码示例:PendingIntent 可变性

kotlin 复制代码
val pendingIntent = PendingIntent.getActivity(
    context,
    requestCode,
    intent,
    // ✅ 必须显式指定可变性
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)

代码示例:SplashScreen 适配

kotlin 复制代码
// 在 Activity 的 onCreate 中
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    // Android 12+ 的 SplashScreen API
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        val splashScreen = installSplashScreen()
        // 保持启动页,直到应用准备好
        splashScreen.setKeepOnScreenCondition { !isAppReady }
    }
    
    setContentView(R.layout.activity_main)
}

七、Android 13(API 33)适配要点

变更 影响 适配方案
通知权限 需要动态申请 POST_NOTIFICATIONS 权限 使用 requestPermissionLauncher 请求权限
精细化媒体权限 READ_EXTERNAL_STORAGE 拆分为三个权限 使用 READ_MEDIA_IMAGES 等权限
Wi-Fi 权限变更 靠近 Wi-Fi 设备不需要位置权限 使用 NEARBY_WIFI_DEVICES 权限
Clipboard 内容隐藏 敏感内容可以隐藏在剪贴板中 使用 ClipDescription.EXTRA_IS_SENSITIVE

代码示例:请求通知权限

kotlin 复制代码
private val requestPermissionLauncher =
    registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
        if (isGranted) {
            showNotification()
        } else {
            // 引导用户到设置页面开启
        }
    }

fun checkNotificationPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.POST_NOTIFICATIONS
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
        }
    }
}

八、Android 14(API 34)适配要点

变更 影响 适配方案
前台服务类型必须声明 Manifest 中必须指定 foregroundServiceType <service> 标签中添加 android:foregroundServiceType
动态广播注册必须指定导出行为 registerReceiver() 必须传 RECEIVER_EXPORTEDRECEIVER_NOT_EXPORTED 显式指定导出行为
OpenJDK 17 行为变更 正则表达式、UUID 生成等行为变化 回归测试核心逻辑
更严格的 Intent 过滤规则 Intent 过滤器必须显式声明 exported 在 Manifest 中显式声明

代码示例:注册广播(Android 14+ 兼容)

kotlin 复制代码
val filter = IntentFilter("com.example.MY_ACTION")

// 接收其他应用的广播 → 需要导出
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
    context.registerReceiver(myReceiver, filter, Context.RECEIVER_EXPORTED)
} else {
    context.registerReceiver(myReceiver, filter)
}

// 只接收应用内部广播 → 不导出(更安全)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
    context.registerReceiver(myReceiver, filter, Context.RECEIVER_NOT_EXPORTED)
}

九、Android 15(API 35)适配要点

变更 影响 适配方案
Edge-to-Edge 强制适配 应用显示区域扩展至全屏 使用 WindowInsets 处理系统栏间距
16KB 页面大小 使用 NDK 的应用需要适配 升级 AGP 到 8.3+,重新编译 so 库
前台服务超时限制 dataSync/mediaProcessing 类型有 24 小时时长限制 改用 WorkManager 或处理 onTimeout 回调
最低 targetSdk 要求 targetSdk < 24 无法安装 升级 targetSdkVersion 到 24+
OpenJDK 17 对齐 字符串格式化等行为变更 避免使用 %0$s 等不合规格式

代码示例:Edge-to-Edge 适配(非 Compose)

kotlin 复制代码
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.root)) { v, insets ->
    val statusBar = insets.getInsets(WindowInsetsCompat.Type.statusBars())
    val navigationBar = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
    
    v.setPadding(
        navigationBar.left,
        statusBar.top,
        navigationBar.right,
        navigationBar.bottom
    )
    
    insets
}

十、Gradle 配置建议(2026 年推荐)

gradle 复制代码
// app/build.gradle
android {
    compileSdk 35
    
    defaultConfig {
        minSdk 21        // 覆盖 99%+ 设备
        targetSdk 35      // 紧跟最新版本
        multiDexEnabled true
    }
    
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    
    kotlinOptions {
        jvmTarget = '17'
    }
}

dependencies {
    implementation "androidx.core:core-ktx:1.13.0"
    implementation "androidx.activity:activity-ktx:1.9.0"
    implementation "androidx.fragment:fragment-ktx:1.7.0"
}

十一、适配优先级建议

根据应用的目标用户和业务需求,按以下优先级进行适配:

优先级 版本 理由
P0(立即适配) Android 15 Google Play 强制要求
P0(立即适配) Android 13 通知权限影响消息到达
P1(3 个月内) Android 14 前台服务类型、广播注册
P1(3 个月内) Android 12 PendingIntent 可变性(安全)
P2(6 个月内) Android 10/11 分区存储、包可见性
P3(按需适配) Android 8/9 存量设备较少

十二、参考资源


本文会持续更新,建议收藏。如果你发现某个版本的适配要点有遗漏,欢迎在评论区补充。如果本文对你有帮助,欢迎点赞收藏。

相关推荐
_祝你今天愉快2 小时前
Android 12 (AOSP) 添加自定义系统服务
android
程序员陆业聪4 小时前
AI编码提效实战:Skill、Rule与上下文工程
android
程序员陆业聪5 小时前
AI驱动需求梳理与Spec编写:让PRD自动变成技术方案
android
李艺为6 小时前
Android Studio使用switch匹配资源id时报需要常量表达式解决办法
android
YaBingSec8 小时前
玄机靶场-2024ccb初赛sc05 WP
android·运维·网络·笔记·安全·ssh
常利兵8 小时前
解锁Android嵌入式照片选择器,让你的App体验丝滑起飞
android
峥嵘life8 小时前
Android 切换用户后无法获取 MAC 地址分析解决
android·python·macos
JJay.9 小时前
Android BLE 为什么连上了却收不到数据
android
歪楼小能手9 小时前
Android16在开机向导最后添加一个声明界面
android·java·平板