Android 17 最后一个 Beta 发布,7 件事必须现在做

前言

就在刚刚,Google 推送了 Android 17 Beta 4 ,这是 Android 17 最后一个预定 Beta ,意味着特性基本全部定型,离正式版只差一次点击「Promote」。

这篇是一份工程师视角的「Beta 4 体检报告」,让你一次看清:

  • 哪些是必须立刻修的硬骨头特性
  • 哪些是可以慢慢再用的新feature
  • 哪些是你压根不用管的

特性概览-本次变更

把 Android 17 整体分成三类:

  • 1:🟢 值得用的新能力 --- Memory Limits、Anomaly Profiling、PQC Keystore、照片选择器宽高比、RAW14、后量子 APK 签名
  • 2:🔴 必须适配的破坏性变更 --- 大屏强制适配、本地网络阻止、System.load() 只读、证书透明度默认开、后台音频加固
  • 3:🧪 实验性/边缘特性 --- 桌面互动画中画(iPiP)、Handoff API、UWB 室内导航、Dynamic Font Fallback

对多数 App 来说,3 个必须适配项 + 1 个内存监控接入,就是这次升级的全部工作量。


🆕 Beta 4 新增:两个重要新能力

Beta 4 是稳定性 Beta,按惯例不应该加新 API。但 Google 破例加了两个 ------因为它们都是为了帮你排查自己应用的稳定性问题

🚨 App Memory Limits:系统开始给你划红线

从 Android 17 开始,系统会根据设备总 RAM ,给每个 App 设定一个动态的内存上限。超过上限,应用直接被杀。

官方原话是「目前的限制比较保守」,意思是:

  • 不会动不动就杀你
  • 主要针对极端内存泄漏会把整个系统拖下水的异常行为(界面卡顿、电量暴跌、连锁杀进程)。

工作流程

怎么判断自己被杀是因为 Memory Limiter?

只要看 ApplicationExitInfo.getDescription() 里有没有 "MemoryLimiter" 字样:

kotlin 复制代码
val am = context.getSystemService(ActivityManager::class.java)
val exitInfos = am.getHistoricalProcessExitReasons(
    /* packageName = */ null,
    /* pid = */ 0,
    /* maxNum = */ 10
)

exitInfos.forEach { info ->
    if (info.description?.contains("MemoryLimiter") == true) {
        // ⚠️ 被系统内存限制杀掉了
        Log.w("ExitTracker", "Killed by MemoryLimiter, rss=${info.rss}")
        // 👉 上报到监控后台
        reportKilledByMemoryLimiter(info)
    }
}

怎么在「被杀之前」抓到现场?

Google 给的正解是触发式 Profiling (Trigger-based profiling),用新的 TRIGGER_TYPE_ANOMALY 监听内存异常,在系统真正杀你之前,先把 heap dump 抓下来:

kotlin 复制代码
val profilingManager = applicationContext
    .getSystemService(ProfilingManager::class.java)

val triggers = arrayListOf(
    ProfilingTrigger.Builder(
        ProfilingTrigger.TRIGGER_TYPE_ANOMALY // 👈 关键:异常触发
    ).build()
)

val executor: Executor = Executors.newSingleThreadExecutor()
val callback = Consumer<ProfilingResult> { result ->
    if (result.errorCode == ProfilingResult.ERROR_NONE) {
        // ✅ 抓到了 heap dump / 堆栈采样
        uploadProfile(result.resultFilePath)
    }
}

profilingManager.registerForAllProfilingResults(executor, callback)
profilingManager.addProfilingTriggers(triggers)

更省心的办法

Android Studio Panda 把 LeakCanary 集成到了 Profiler 里,变成一个独立任务,点一下就能联动源码定位泄漏点。这是我最近三个月最愿意推荐给团队 Android 新人的调试方式。

✅ 评价

这是个温柔但必修的特性。温柔,是因为 Google 先用保守策略上线,留出观察期;必修,是因为一旦「温柔期」结束,没做内存治理的 App 会被一锅端。

📡 Anomaly Profiling:异常发生前就拿到现场

TRIGGER_TYPE_ANOMALY 不只是监控内存,它是 Android 17 新增的设备侧异常检测服务 ,能自动识别以下几类「异常行为」:

  • 1:过多 Binder 调用(excessive binder calls) --- 抓一份 Binder 事务的堆栈采样 profile
  • 2:过度内存使用(excessive memory usage) --- 抓一份应用的 heap dump
  • 3:未来可能扩展 到 CPU、I/O、电量异常(参考 Beta 1 已引入的 KILL_EXCESSIVE_CPU_USAGE / OOM / COLD_START 触发器)

关键点在于:它是在系统准备对你动手之前触发的。也就是说,你有机会在被杀、被限流、被降级之前,拿到一份「第一现场」的 profile。

这种能力过去只有大厂自研的 APM 平台(Bugly、Sentry、字节的 Kanas 等)能做到,而且多半要 hook framework。现在 Google 直接把它做成了系统 API,中小团队也能白嫖。

✅ 评价

这是 Android 监控生态一次底层能力下沉 。未来 12 个月内,几乎所有国内 APM 厂商都会把 ProfilingManager 作为标配接入。


🔴 Breaking Changes:五个必须适配的行为变更

以下五项变更,只要你 targetSdk = 37(Android 17),不迁移就会出问题。按影响面从大到小排列。

① 大屏可调整性强制启用

这是 Android 17 整代最大的 Breaking Change,从 Beta 1 就已经定型。

一旦你的应用 targetSdk = 37 ,在 sw ≥ 600dp 的大屏设备 上,以下清单属性全部失效

  • 1:android:screenOrientation(你锁的竖屏?系统不理)
  • 2:android:resizeableActivity(你声明不可调整大小?系统不理)
  • 3:android:minAspectRatio / android:maxAspectRatio(你锁的宽高比?系统不理)

豁免条件只有两个:

  • ① 设备 sw < 600dp
  • ② 应用 android:appCategory="game"

这意味着:所有非游戏 App 都要把「多尺寸、多方向、多宽高比」做成默认能力。Compose 里就是 WindowSizeClassLookaheadScopeadaptive 系列;View 体系就是 SlidingPaneLayout、fragment-based 多面板。

迁移最小成本清单

  • 1:用 WindowSizeClass 按 Compact/Medium/Expanded 三档布局

  • 2:列表详情页改成 SupportingPaneScaffold(material3-adaptive)

  • 3:对话框/底部弹层在大屏用 ModalBottomSheet(sheetMaxWidth = ...)
  • 4:视频/相机类应用测试横竖屏无缝切换,不要依赖 Activity recreate

我的判断:这件事 Google 催了三年(从 12L 开始),现在终于硬来了。别找借口,平板 + 折叠屏 + 车机 + ChromeOS 已经是不可忽视的体量,做不做是商业问题,不是技术问题。

② 本地网络访问默认阻止

targetSdk = 37 的应用,默认无法访问同一 LAN 内的其他设备 (包括投屏、局域网打印、智能家居控制、P2P 传输等场景)。

场景 旧做法 Android 17 做法
投屏 / DLNA 扫描 SSDP 广播 引导用户用系统 Picker
局域网打印 直接 mDNS 查询 申请 ACCESS_LOCAL_NETWORK
智能家居 App 广播 + socket 申请 ACCESS_LOCAL_NETWORK
文件快传 / AirDrop 类 P2P socket 申请 ACCESS_LOCAL_NETWORK

权限属于 NEARBY_DEVICES 权限组,用户在系统授权面板里看到的是「附近设备」。申请示例:

xml 复制代码
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.ACCESS_LOCAL_NETWORK" />
kotlin 复制代码
// 运行时请求
val request = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { granted ->
    if (granted) startLocalDiscovery()
    else showRationaleDialog() // ⚠️ 用户拒绝时给出场景说明,不要直接退出
}
request.launch(Manifest.permission.ACCESS_LOCAL_NETWORK)

Google 强烈建议:能用系统 Picker 就用 Picker(比如 MediaRouter、CompanionDeviceManager、Nearby Share),只有确实需要长期扫描局域网的才申请权限。原因很朴素------用户对「附近设备」权限越来越敏感,一次差评就能让拒绝率涨一倍。

✅ 评价

对 IoT、投屏、文件传输这几类应用是大事;对普通业务 App 几乎无感。

System.load() 要求只读

Android 14 引入了「Safer Dynamic Code Loading」,要求 DEX / JAR 在加载时必须标记为只读(setReadOnly())。Android 17 把这条约束扩展到了原生库.so)。

任何通过 System.load() 加载的 .so,如果文件没被标记为只读,直接抛 UnsatisfiedLinkError

kotlin 复制代码
// ❌ 旧代码:从可写目录直接 load,Android 17 上崩溃
val soFile = File(cacheDir, "plugin.so")
downloadTo(soFile)
System.load(soFile.absolutePath) // 💥 UnsatisfiedLinkError

// ✅ 新代码:下载完 → 标记只读 → 再 load
val soFile = File(cacheDir, "plugin.so")
downloadTo(soFile)
soFile.setReadOnly() // 👈 关键一步
System.load(soFile.absolutePath)

受影响最多的是热修复框架、插件化框架、动态下发 so 的游戏引擎。如果你用的是 Tinker、Robust、Shadow、VirtualAPK 这类第三方,必须检查其是否已升级。

我的判断:这是安全策略的继续收紧,方向绝对正确。动态代码加载在过去几年是恶意攻击的主要入口,能堵一点是一点。

④ 证书透明度(CT)默认启用

Android 16 时,证书透明度(Certificate Transparency)是 opt-in;Android 17 里,它默认启用

影响面小但要注意:如果你的应用访问的域名使用了未登记到 CT 日志的证书(常见于内网自签名、私有 PKI),TLS 握手会失败。

排查清单:

  • 1:公网 HTTPS 接口 --- 99% 无影响(主流 CA 都会提交 CT)
  • 2:内网接口 / 企业证书 --- 用 openssl x509 -in cert.pem -text -noout | grep -i "CT Precertificate" 检查
  • 3:测试环境自签名 --- 用 networkSecurityConfig<domain-config cleartextTrafficPermitted="false"><trust-anchors>...</trust-anchors></domain-config> 显式信任

⑤ 后台音频加固(Beta 4 调整版)

Beta 2 就已经引入了后台音频的严格约束:后台不允许随便播放、申请焦点、改音量。Beta 4 基于开发者反馈做了两处调整:

  • 1:targetSdk gating --- while-in-use FGS 的强制执行会判断 targetSdk,避免把老应用也搞崩
  • 2:闹钟音频豁免 --- 闹钟类应用的后台音频交互不再受限

这两项调整释放了一个信号:Google 不是要一刀切,而是按「场景合理性」精修。闹钟是用户主动设置的、必须响的;而「广告自动播音」这种才是真要干掉的对象。

对音乐、播客、导航、IM 等有合法后台音频需求的应用,迁移路径是:

  • 1:用 MediaSession + MediaStyle 通知声明自己是媒体应用
  • 2:用 ForegroundServiceType = mediaPlayback 声明服务类型
  • 3:在 Manifest 里声明 FOREGROUND_SERVICE_MEDIA_PLAYBACK 权限
  • 4:非媒体场景(如游戏 BGM)走 AudioAttributes.USAGE_GAME 而不是 USAGE_MEDIA

🟢 值得关注的其他改进

除了上面「必修 + 新能力」,Android 17 还堆了一批值得抽时间看一眼的小东西。

后量子密码学(PQC)进 Keystore

Android 17 Keystore 开始支持 NIST 标准化的 ML-DSA (Module-Lattice-Based Digital Signature Algorithm),目前暴露两个变体:ML-DSA-65ML-DSA-87

java 复制代码
KeyPairGenerator generator = KeyPairGenerator.getInstance(
        "ML-DSA-65", "AndroidKeyStore");
generator.initialize(
    new KeyGenParameterSpec.Builder(
        "my-key-alias",
        KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY
    ).build()
);
KeyPair keyPair = generator.generateKeyPair();

密钥完全在设备的安全硬件 (StrongBox / TEE)中生成和使用,对量子计算机攻击具备抗性。配合 Beta 3 引入的 v3.2 APK 签名方案(经典 ECDSA + ML-DSA 混合签名),Android 生态的「后量子迁移路线图」正式启动。

我的判断:普通业务应用今年内基本用不上;但银行、支付、密钥管理、身份认证类产品应该开始规划「PQC-ready」技术栈。量子威胁不是科幻,NIST 已经把时间表排到了 2030 年前。

其他值得扫一眼的 API

按「可能踩到的概率」排序:

  • 1:AlarmManager.setExactAndAllowWhileIdle 新回调变体 --- 用 OnAlarmListener 替换 PendingIntent,省电 + 省代码
  • 2:动态系统字体回退(Dynamic Font Fallback) --- 系统字体支持增量更新,不用等 OS 大版本
  • 3:OpenJDK 21 / 25 集成 --- Stream.gatherers、结构化并发 StructuredTaskScopeScopedValue 都能用了
  • 4:RemoteViews.setViewPadding 支持 DP/SP --- 微件开发终于不用只能传 px
  • 5:照片选择器宽高比自定义(1:1 → 9:16) --- 头像/封面选择体验升级
  • 6:ImageFormat.RAW14 --- 相机类应用高端机型画质档
  • 7:Activity 配置更改优化 (Beta 1 引入,容易遗漏) --- 键盘、触摸屏、颜色模式等配置变更默认不再重启 Activity ,依赖重启的要加 android:recreateOnConfigChanges
  • 8:android:usesCleartextTraffic 即将废弃 --- 有用明文 HTTP 的赶紧迁移到 Network Security Config

最后这两条是潜在杀手 。Activity 不重启这件事,很多 App 会用 onConfigurationChanged 以外的途径(比如检测 Resources.getConfiguration() 变化)做分支,一旦重启路径断了,UI 就会出现「深色模式切换后颜色不对」「键盘弹出后布局错乱」这类隐蔽 bug。建议全量回归一次。


🚀 升级路径:这三周该怎么做

从今天到 I/O 2026 正式版,三周左右。给一个落地到的计划:

Week 1 --- 兼容性摸底(不改代码)

  • 1:用 Android Studio Panda + Beta 4 Emulator 跑全功能回归
  • 2:开启 Compatibility Framework(设置 → 开发者选项 → 应用兼容性变更),逐个打开 Android 17 的变更开关观察崩溃
  • 3:在 CI 里加一条「target 37」的灰度任务,只编译不发布

Week 2 --- Breaking Change 修复

  • 1:大屏可调整性 --- 如果是非游戏类 App,必须做响应式布局
  • 2:本地网络 --- 清点所有 DatagramSocket / MulticastSocket / mDNS,按需申请权限
  • 3:System.load() --- 用 grep 扫全部模块,补 setReadOnly()
  • 4:Activity 配置变更 --- 关键页面加 android:recreateOnConfigChanges

Week 3 --- 新能力接入 + 发布

  • 1:接入 ApplicationExitInfo 上报 MemoryLimiter 标识到监控后台
  • 2:接入 ProfilingManager.TRIGGER_TYPE_ANOMALY,异常时拉 heap dump
  • 3:灰度 10% 用户发布 targetSdk = 37 版本,盯住 Crash/ANR 大盘 48 小时
  • 4:正式版推送后 24 小时内提交全量

别等正式版再动。Beta 4 = 稳定性 Beta,此时跑出来的 Crash 几乎就是正式版会遇到的 Crash。早一周做,就能省下线上一次紧急回滚。


版本节奏-全面了解

Android 17 从 Beta 1 到 Beta 4,节奏比往年更紧凑:

  • 1:Beta 1 --- 2026 年 2 月 13 日,奠定本代最核心的 Breaking Change(大屏可调整性、Activity 配置变更优化)
  • 2:Beta 2 --- 2026 年 2 月 26 日,引入 ACCESS_LOCAL_NETWORK 权限、NPU 特性声明、SMS OTP 保护
  • 3:Beta 3 --- 2026 年 3 月 26 日,平台稳定性(Platform Stability)里程碑,API 界面锁定
  • 4:Beta 4 --- 2026 年 4 月 16 日,最后一个 Beta,新增 App Memory LimitsAnomaly Profiling Triggers

按 Google 的历史节奏,正式版大概率在 Google I/O 2026(5 月中旬)同期发布 。也就是说,从今天算起,你手上最多还有 3 周的「免费窗口」------在 Beta 4 上把兼容性、崩溃率、ANR 全部跑一遍,正式版推送那天就能不慌。

这不是一个可以「等正式版出了再说」的版本。大屏可调整性、本地网络、后台音频,任何一项没适配,都是线上 Crash 或用户差评。


最后

Android 17 Beta 4 的信号很明确:这代系统的关键词是「收敛」,不是「扩张」

  • 收敛【大屏】 :不再让你用一个 screenOrientation="portrait" 把平板用户挡在门外。
  • 收敛【安全】 :本地网络默认关、动态代码只读、证书透明度默认开、后量子签名上线。
  • 收敛【稳定性】: Memory Limits 划红线、Anomaly Profiling 提前预警、LeakCanary 进 Studio。

这些都不是让 App 更强的特性,而是让整个 Android 生态更健康的规则


📎 参考资料

相关推荐
ooseabiscuit1 小时前
Laravel 9.x重磅升级:PHP8新特性全解析
android
帅次1 小时前
深入 MaterialTheme:掌握 ColorScheme 与 Typography 的设计核心
android·kotlin·gradle·android jetpack·compose
阿巴斯甜2 小时前
必看2
android
名不经传的养虾人2 小时前
什么是API中转站?开发者如何通过API网关低成本调用GPT/Claude/Gemini
ai编程·ai模型·token中转站·ai账单·省钱
重生之小比特2 小时前
【MySQL 数据库】复合查询
android·数据库·mysql
用户86022504674722 小时前
Jetpack Activity 完整示例教程
android
沸点小助手3 小时前
「掘友五一大赏沸点」获奖名单公示|本周互动话题上新🎊
openai·ai编程·沸点
小马过河R3 小时前
从官方定义读懂智能体的时代分量
人工智能·语言模型·大模型·llm·agent·ai编程·多模态