Android 17:API 级别 37 的开发者指南——现在你需要构建什么

Android 17:API 级别 37 的开发者指南------现在你需要构建什么

跨设备接力、EyeDropper、应用气泡、ART 性能提升和相机 API 将改变您在 2026 年构建 Android 应用的方式。

如果你的 Android 应用能够在使用过程中,将应用的精确状态从手机无缝传输到平板电脑,那会怎样?这并非 Google I/O 大会上才会出现的功能,而是今天在 Android 17 Beta 2 中正式发布的 API!

Android 17(API 级别 37)看起来是近年来影响最大的 Android 版本之一。它给人的感觉就像是面向消费者的一次重大更新,但对于开发者而言,它却包含了大量的底层架构变更,需要开发者重新评估应用的架构。以下列出了一些重要的 API 和行为变更,并附有示例代码。

新版本发布节奏:Canary 是你最好的新朋友

这或许在我们深入研究 API 之前就已经知道了,但作为一项结构性变化,了解这一点仍然很有意义。

谷歌已用持续发布渠道 Canary 取代了之前的开发者预览模式 GPIO。功能和 API 一旦通过内部质量审核,就会立即发布到 Canary 版本中,不再按季度发布。这就是谷歌对待 Chrome 开发的方式,至少对于持续集成 (CI) 运行人员来说,这是一个合理的改变。

这意味着无需再手动刷机(因为 Canary 支持 OTA 更新)。虽然稳定版预计要到 2026 年第二季度才会发布,但平台稳定性早在 3 月份就已经实现了------这意味着最终的 API 大部分已经锁定。

结论: 立即将 Canary 版本添加到您的测试矩阵中

1. 接力 API --- 实现跨设备连续性的最佳方案

这是应用开发者的一项核心功能。借助全新的 Handoff API,您可以指定应用的状态,以便在其他设备(例如平板电脑)上恢复运行。用户启用此功能后,系统会同步应用状态,CompanionDeviceManager并在用户附近设备的启动器中显示切换建议。

Handoff 功能可以实现原生应用之间的切换,并且(如果目标设备上没有原生应用)还可以回退到 Web 应用------体验不会中断。

所以,实际操作中,选择加入的过程是这样的:

kotlin 复制代码
// Declare what state can be handed off --- keep it lean and serializable
override fun onResume() {
    super.onResume()

    val handoffState = bundleOf(
        "article_id" to currentArticle.id,
        "scroll_position" to binding.scrollView.scrollY,
        "read_progress" to readingProgressPercent
    )

    // Register your handoff payload with the system
    HandoffManager.getInstance(this).setHandoffState(
        activityName = this::class.java.name,
        state = handoffState,
        // Web fallback if receiving device doesn't have the app installed
        webFallbackUri = Uri.parse("https://yourapp.com/article/${currentArticle.id}")
    )
}

override fun onPause() {
    super.onPause()
    HandoffManager.getInstance(this).clearHandoffState()
}

设计原则 1:切换负载应小巧且可序列化。它类似于上下文深度链接,而非完整的状态转储。在 onCreate 事件中检查 Intent.ACTION_HANDOFF,以区分切换启动和冷启动。

2. 应用气泡------一种房地产窗口模式

气泡窗口模式(与消息气泡 API 完全独立)提供了一个浮动界面。用户可以通过长按启动器中的应用图标来启用它。为了在大屏幕和折叠屏设备上组织多个气泡,我们在任务栏中提供了一个气泡栏。

这对于生产力应用、参考工具以及任何用户希望在运行其他应用时保持打开状态的应用都至关重要。为了流畅地处理这种情况,接下来需要进行以下更改:您的 Activity 应该能够适应任意窗口大小。

3. 高度符合 API 37 标准(强制性)

不再提供退出选项。Android 17(软件分辨率 > 600dp,大屏设备也将移除)已移除开发者退出屏幕方向和调整大小限制的选项。如果您之前屏蔽了平板电脑布局android:screenOrientation="portrait",现在该功能将失效。

需要改进的地方:
  • 在你的清单中删除android:screenOrientation"and"android:resizeableActivity="false"
  • 尽管在多种尺寸的自由窗口模式下进行了测试
  • 使用 Jetpack WindowManager 实现自适应布局WindowSizeClass
kotlin 复制代码
// The right approach: adaptive layout via WindowSizeClass
@Composable
fun ArticleScreen(windowSizeClass: WindowSizeClass) {
    when (windowSizeClass.widthSizeClass) {
        WindowWidthSizeClass.Compact -> {
            // Single-column phone layout
            ArticleSinglePane()
        }
        WindowWidthSizeClass.Medium,
        WindowWidthSizeClass.Expanded -> {
            // Two-pane layout for tablets and foldables
            ArticleTwoPane()
        }
    }
}

4. 摄像头 API --- 实时更改输出,无需中断会话

CameraCaptureSession 在 Android 17 上现在有了 updateOutputConfigurations() 函数。这允许您添加和删除输出表面,而无需重新配置整个会话。

如果您曾经在使用相机应用时遇到过镜头切换延迟,您就会明白这有多重要。过去,切换目标(例如从预览切换到录制)实际上需要断开并重建会话,这会带来明显的延迟。从 2023 年 10 月起,您可以使用此 API 完全避免这种开销。结合已确认的 H.266/VVC 编解码器支持,您将拥有一个功能更强大的相机堆栈。

5. EyeDropper API --- 系统级颜色选择器

系统级 EyeDropper API 允许您的应用从屏幕上显示的任何位置选择颜色,而无需请求屏幕截图权限。

这用简洁且作用域明确的 API 取代了以前繁琐的权限管理,非常适合设计工具、照片编辑器和主题应用程序等。

kotlin 复制代码
// Trigger system EyeDropper --- no screen capture permission needed
val eyeDropper = EyeDropper(this)

eyeDropper.open(
    executor = mainExecutor,
    listener = { result ->
        val pickedColor = result.color
        // Apply to your UI --- update theme, canvas, or user preference
        viewModel.setAccentColor(pickedColor)
    }
)

6. 静态最终垃圾回收和分代垃圾回收的强制执行

今年秋季通过任何应用程序:两次运行时级别更改

分代垃圾回收: Android 17 为 ART 的并发标记压缩垃圾回收器添加了分代垃圾回收功能------新生代垃圾回收开销较大,因此我们希望它能更频繁地执行,同时降低与全堆回收相比的资源消耗。减少滚动和动画时的卡顿,无需修改代码。

阻止对静态 final 字段进行反射覆盖:面向 API 37 及更高版本的应用程序无法使用反射修改静态 final 字段。这样做会抛出 IllegalAccessException 异常。使用 JNI 的 SetStaticField 方法进行更改会立即崩溃。

检查你的第三方库依赖项------一些较旧的依赖注入框架,甚至一些模拟库,都是需要特别注意的典型例子。所以,在持续集成(CI)发现问题之前,务必运行./gradlew lint测试。targetSdk 37

7. 隐私:联系人选择器 + 一次性密码锁定

即将发布的文章:Android 联系人选择器:一种保护用户隐私的标准化方式,让用户可以通过这种方式与您的应用分享特定联系人。您的应用只需指定所需的数据字段(例如电话号码、电子邮件地址),用户即可选择特定的联系人------这样您的应用就只能访问这些数据,而不会访问用户的整个通讯录。

在所有需要进行简单查找的地方,请使用此 API 代替 READ_CONTACTS 权限请求。这不仅能更好地展现用户体验,还能以更轻量级的方式向用户传达您对隐私的重视。

安全方面:如果应用拥有短信读取权限,但未通过域名验证确认其并非正确的 OTP 接收方,则该 WebOTP 格式的短信将在三小时后才能访问。这会影响所有面向 API 37 的应用发送的、非 WebOTP 格式的 OTP 短信。

如果你的应用涉及 OTP,请立即迁移到 SMS Retriever API 或 WebOTP,而不是等到用户开始报告验证码始终无法收到的错误之后再迁移。

8. ProfilingManager:用于现场调试的系统触发器

ProfilingManager新增了 Android 17 中的三个系统触发器。

  • TRIGGER_TYPE_COLD_START
  • TRIGGER_TYPE_OOM
  • TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE

这些功能允许您在特定时间点自动捕获性能分析跟踪信息,例如启动性能、内存压力事件和 CPU 崩溃等情况。在调试版本中连接这些功能,即可在 QA 测试遇到极端情况时自动捕获跟踪信息。这大大简化了内存问题的重现过程。

虽然它并非 Android 系统视觉效果最惊艳的版本(或许 Level Up 才是),但却是近年来最注重开发者体验的版本之一。Handoff API 本身就开启了一种全新的多设备用户体验模式,而 Android 系统本身并没有提供完整的解决方案。再加上强制适配大屏幕设计,以及 ART 中的分代垃圾回收机制,基于 API 37 正确构建的应用体验将会显著提升。

测试版现已推出,平台稳定,无需等待。

相关推荐
yuhuofei202121 小时前
【Python入门】Python中字符串相关拓展
android·java·python
dalancon21 小时前
Android Input Spy Window
android
dalancon1 天前
InputDispatcher派发事件,查找目标窗口
android
我命由我123451 天前
Android Framework P3 - MediaServer 进程、认识 ServiceManager 进程
android·c语言·开发语言·c++·visualstudio·visual studio·android runtime
天才少年曾牛1 天前
Android14 新增系统服务后,应用调用出现 “hidden api” 警告的原因与解决方案
android·frameworks
赏金术士1 天前
Jetpack Compose 底部导航实战教程(完整版)
android·kotlin·compose
随遇丿而安1 天前
第5周:XML 资源、样式和主题,真正解决的是“页面以后还改不改得动”
android
zh_xuan1 天前
Android 获取系统内存页大小:sysconf(_SC_PAGESIZE) 与 JNI 实现
android·jni·ndk·内存页大小
fundroid1 天前
Google I/O 2026 | Android 全面进化:从操作系统到“智能中枢”
android·jetpack compose·google i/o 2026
zh_xuan1 天前
Android 复用 .so 库:通过 jniLibs 集成预编译二进制库(获取 Page Size )
android·jni·ndk·内存页大小