Android 开发者官网的隐藏页面和工具
Android 开发者官网的隐藏页面和工具
developer.android.com 这个域名,大部分开发者每天打交道的就是那几样:API 参考文档、Jetpack 库的版本说明、偶尔查查 Material Design 的规范。但 Google 在这个域名下塞了不少东西,有些页面藏得挺深,有些工具明明很有用却几乎没人提。这篇东西把我这些年翻文档时偶然撞见的、或者从 Google 工程师推特和 issue tracker 里挖出来的一些角落整理一下,不保证全面,但都是我自己用过或者至少亲手点进去看过的。
那个很多人没见过的 `/studio/profile` 路径
Android Studio 的性能分析器文档主入口大家都知道,但 Google 在 developer.android.com/studio/profile 下面维护了一套相当完整的性能测量指南,而且这部分内容更新频率和深度往往超过主文档。比如 profile/android-profiler 这个页面,不只是教你点哪个按钮,而是详细解释了 CPU Profiler 的三种采样机制——Instrumented、Sampled、和 Trace System Calls——分别在什么场景下会丢数据。
真正隐蔽的是 developer.android.com/studio/profile/baselineprofiles 这个路径。Baseline Profiles 这个功能从 Android 13 开始推,但文档入口藏得很别扭。大部分开发者第一次听说可能是通过 Jetpack 的 Macrobenchmark 库,但那个库的文档只教你写测试代码,怎么把生成的 profile 打包进 APK、怎么验证是否生效、Play Store 云端 profile 和本地 profile 的优先级关系,这些细节全在这个独立页面里。我去年帮一个团队做启动优化,按 Jetpack 文档生成了 .baseline 文件,但包体积没变化,启动也没快。翻到这个页面才发现,AGP 7.3 之前需要手动配置 android.baselineProfile.enabled,而且只有 androidTest 目录下的 Macrobenchmark 才会自动触发 profile 生成,单元测试目录下的不会。这个区分在 Jetpack 库的文档里提都没提。
同路径下还有个 profile/memory 子页面,里面关于 Native Memory Profiler 的说明值得看。Android Studio 对 native 层的内存分析一直比较弱,这个页面坦白说了限制:只支持 Android 10 以上设备,而且如果应用使用了自定义 allocator 或者开启了 MTE(Memory Tagging Extension),数据会完全不准确。这种"我们告诉你这玩意不好使"的诚实,在官方文档里不多见。
兼容性框架的开关页面
developer.android.com/reference/android/app/compat/CompatChanges 这个类文档本身没什么,但文档里埋了一个链接指向 developer.android.com/guide/app-compatibility compatibility-framework,这个页面讲的是 Android 11 引入的兼容性变更框架。简单说,Google 把以前那些"某个 API 在 Android X 版本行为变了"的东西,做成了一个可查询、可开关的系统。
页面上有个很实用的命令行工具说明:adb shell am compat enable/disable <change_id> <package_name>。每个行为变更都有唯一的 change ID,比如 170668199 对应的是 Android 12 中对 PendingIntent 的可变性要求。这个机制的真正价值在于测试:你可以在 Pixel 设备上,针对单个应用开关某个行为变更,看应用会不会崩。以前这种测试需要准备多台设备或者刷不同版本,现在一台 Android 12 的 Pixel 就能模拟 Android 11 的行为。
但这个页面的坑也很明显。它列出的 change ID 并不完整,完整的列表在 AOSP 源码的 frameworks/base/core/java/android/app/compat/ChangeId.java 里,官网文档只挑了"我们认为开发者最可能关心的"一部分。而且 am compat 命令在 Android 11 上需要 root,Android 12 以后才开放给普通 adb。我有一次在非 Pixel 设备上试这个命令,发现厂商 ROM 把相关接口阉割了,完全没反应。页面底部的小字提到了"部分设备可能不支持",但字体小到几乎看不见。
安全中心的那堆检查清单
developer.android.com/security 这个一级路径存在感很低,但下面的内容密度很高。security/best-practices 不是泛泛而谈,而是按组件类型拆分:Activity 的 exported 属性怎么配、Service 的 intent-filter 和 permission 的组合陷阱、ContentProvider 的 path permission 粒度控制。每个小节都有具体的错误配置示例和对应的攻击向量说明。
更隐蔽的是 security/security-crypto 这个页面,讲的是 Jetpack Security 库。这个库封装了 Android Keystore 系统,提供 EncryptedFile 和 EncryptedSharedPreferences。文档里有个细节很容易忽略:在 Android 9 及以下,如果设备没有硬件安全模块(TEE 或 StrongBox),库会回退到基于 Tink 的软件实现,但密钥仍然加密存储在文件系统上。这意味着 root 后的设备上,密钥材料是可提取的。页面中间偏后的位置有个"Known Issues"小节,明确说了 Android 10 之前 EncryptedSharedPreferences 的 MultiProcessFactory 有竞态条件,多进程写入可能丢数据。这个限制导致我们一个项目最终放弃了这个库,改用自己封装的 ContentProvider 做跨进程同步。
同路径下还有个 security/apksigning 页面,除了常规的 v1/v2/v3/v4 签名方案说明,还详细解释了 APK Signature Scheme v3 的 key rotation 机制。这是 Android 9 引入的,允许应用在更新时更换签名密钥,但要求旧密钥对新密钥做交叉签名。页面提供了 apksigner 命令的具体参数,以及 apksigner rotate 子命令的用法。实际操作中,这个轮换需要规划好:第一次发布用旧密钥签,同时嵌入新密钥的证书;第二次发布用新密钥签,但保留旧密钥的交叉签名;第三次才能完全切换到新密钥。很多开发者以为 rotate 一次就能换密钥,结果 Play Store 上传时报错,就是因为没理解这个三阶段流程。
游戏开发文档里的非游戏工具
developer.android.com/games 路径看起来和游戏相关,但里面有些东西通用开发者也能用。games/optimize 下面的 "Frame Pacing" 文档,讲的是 Android 的 Swappy 库,原本用于游戏渲染的帧率平滑,但任何需要稳定 SurfaceFlinger 交互的应用都能用。文档里有个关键参数 SWAPPY_SWAP_INTERVAL,控制是否强制对齐显示器的刷新周期。我们在一个视频播放器项目里引入了这个库,解决了特定设备上 SurfaceView 渲染的抖动问题,代价是增加了 1-2 帧的延迟。
games/sdk/memory-advice 这个页面更冷门,介绍的是 Android Memory Advice API,一个 C++ 库,用于在运行时查询系统的内存压力状态。接口很简单:MemoryAdvice_getMemoryState() 返回 OK、APPROACHING_LIMIT 或 CRITICAL。但这个库不是通过 Maven 或者 NDK 标准渠道分发,需要从 github.com/android/games-sdk 单独克隆构建。页面上的集成说明写了 CMake 的 add_subdirectory 方式,但没提预编译二进制。实际项目中,我们花了半天时间才搞定这个库的交叉编译,因为文档假设你已经熟悉 Google 的游戏 SDK 构建系统。
那些会跳转的短链接和工具页
Google 在开发者文档里埋了不少 g.co 或者 d.android.com 的短链接,有些指向的工具页面没有正常的导航入口。比如 d.android.com/perfd 会跳转到 CPU Profiler 的详细文档,但主文档树里很难找到这个入口。
developer.android.com/studio/write/lint 这个页面值得专门提。Lint 的官方文档分散在各个角落,这个页面算是汇总,但更重要的是它解释了如何编写自定义 Lint 规则。从 Android Studio 3.0 开始,自定义 Lint 规则的工程结构变了,需要单独创建一个 Java 或 Kotlin 模块,应用 com.android.lint 插件,而不是像以前那样在 Android 模块里写。页面上有个完整的 build.gradle 示例,以及 IssueRegistry 和 Detector 的实现模板。但文档里的示例代码用的是旧的 PSI API,实际开发中需要参考 lint-checks 源码里的新 API,比如 UElementHandler 而不是 JavaElementVisitor。这个脱节导致我第一次写自定义 Lint 时,按文档代码编译不过,翻了半天源码才找到替代方案。
developer.android.com/studio/test/espresso-test-recorder 这个工具页面,讲的是 Android Studio 内置的 Espresso 测试录制器。这个功能在 4.1 版本引入,但存在感极低,因为录出来的测试代码质量很差,满屏的 Thread.sleep 和绝对坐标点击。不过页面底部有个"Limitations"小节,诚实列出了七个已知限制,包括不支持 WebView、不支持跨应用测试、录制期间不能旋转屏幕等。这种文档至少省了你亲自踩坑的时间。
废弃但还能访问的页面
Google 很少真正删除页面,更多是加横幅提示废弃。developer.android.com/topic/libraries/data-binding 这个页面还在,虽然 Jetpack Compose 已经主推了两年。页面顶部的大红横幅告诉你"考虑迁移到 Compose",但下面的内容完整保留。对于还在维护旧项目的开发者,这个页面比翻历史版本文档方便。
developer.android.com/jetpack/androidx/releases/room 这种版本说明页面,每个版本都有独立的 URL,不会被覆盖。Room 2.4.0 引入的 autoMigrations 功能,2.5.0 改动的 FTS4 中文支持,2.6.0 的 Kotlin Multiplatform 实验性支持,这些变更分散在不同版本的页面里。Google 不提供跨版本的变更汇总,所以升级大版本时,需要手动翻多个页面。我通常的做法是用 site:developer.android.com/jetpack/androidx/releases/room "2.5" 这种搜索语法,配合时间范围,比用站内搜索准确。
developer.android.com/ndk 路径下的 ndk/guides/graphics/ 子页面,Vulkan 和 OpenGL ES 的文档都在,但更新频率明显低于上层 API。Vulkan 的 VK_ANDROID_external_memory_android_hardware_buffer 扩展说明,在 NDK r25 的文档里和实际头文件对不上,因为文档更新滞后于 NDK 发布。这种时候只能以头文件和源码为准,文档仅供参考。
设计规范里的技术实现细节
developer.android.com/design 和 developer.android.com/reference/com/google/android/material 这两个路径,很多人当纯设计文档看,但里面埋了不少实现细节。Material Design 3 的 ColorScheme 动态取色算法,在 design/material-you 页面里有简化的伪代码说明,解释了如何从壁纸提取主色调、次色调、以及如何处理低饱和度图片的 fallback 逻辑。这个算法在 Android 12 的 com.android.systemui.monet 包里有完整实现,但官方文档里的简化版足够理解原理。
reference/com/google/android/material/datepicker 这个页面,Material DatePicker 的文档,详细说明了 dateValidator 的回调时机。这个回调在日历翻页时就会触发,不只是最终选择时,所以如果你在里面做网络请求校验可用日期,需要考虑性能。文档里建议用 CalendarConstraints 预过滤,而不是依赖运行时校验。这个细节不读文档很难发现,因为大部分示例代码都简化了这部分。
design/ui-ux 路径下的 large-screens 页面,讲的是平板和折叠屏适配。这个页面在 2022 年大改过,增加了 WindowSizeClass 的正式定义,以及 Jetpack WindowManager 的 WindowMetricsCalculator。但页面里的示例代码仍然使用旧的 Display.getRealSize() 方法获取屏幕尺寸,而这个 API 在 Android 11 开始被标记为 deprecated,推荐用 WindowMetrics。这种文档内部的不一致,需要读者自己交叉验证。
发行和分发的隐藏入口
developer.android.com/distribute 这个一级路径,内容比 google/play 少,但有些东西只有这里能找到。distribute/best-practices/launch/launch-checklist 是一个完整的发布前检查清单,从应用签名、版本号规则、到目标 API 级别要求,逐项列出。这个清单不是强制性的,但 Play Store 的自动审核会参考这些项目。我们有一次更新被拒,理由是"未正确处理备份和恢复",就是清单里第 17 项的内容,但审核邮件没提具体是哪一项,翻到这个清单才定位问题。
distribute/console 路径下的 pre-launch-report 页面,讲的是 Play Console 的预启动测试。这个测试用 Firebase Test Lab 的 Robo 测试 crawler 跑你的应用,截图并报告崩溃。页面里有个重要细节:Robo 测试对登录流程的处理有限,如果你的应用启动需要 OAuth 或者短信验证码,crawler 会卡住,测试覆盖率极低。文档建议提供测试账号或者使用 Google Sign-In 的测试模式,但很多企业应用的认证流程更复杂,这个测试基本形同虚设。
distribute/marketing-tools 这个页面很多人没点进去过,里面提供了 Play Store 商品详情页的 A/B 测试工具,以及应用图标、截图的规范检查器。图标检查器会验证你的 PNG 是否包含正确的安全边距、是否使用了禁止的透明通道、以及在不同设备上的缩放效果。这个工具是网页版,不需要上传应用到 Play Console,开发阶段就能用。但检查结果和 Play Console 的最终审核偶尔不一致,因为审核端会额外检查动态内容(比如根据设备地区切换的图标)。
训练课程的残留和更新
developer.android.com/courses 这个路径下,Google 放了一些结构化课程,但完成度参差不齐。courses/android-basics-kotlin 这个系列面向初学者,内容比较基础。但 courses/advanced-training 下面的部分章节,比如 "Background work with WorkManager" 和 "Paging library",代码示例用的是比当前稳定版旧一两个版本的 API,比如 LiveData 而不是 Flow,PagingDataAdapter 而不是 PagingDataAdapter 的 AsyncPagingDataDiffer 变体。这些课程页面底部有最后更新日期,但字体很小,容易忽略。我一般不推荐团队新人直接跟这些课程,而是让他们看库的官方文档和 codelabs。
codelabs 是另一个独立路径 developer.android.com/codelabs,和 courses 分开。Codelab 的更新频率通常更高,因为每个都是独立的,不需要维护课程间的依赖关系。codelabs/jetpack-compose-basics 这个页面,Compose 的入门 codelab,最近一次更新是在 2023 年底,跟上了 Material3 的默认主题。但同路径下的 codelabs/advanced-jetpack-compose 仍然使用 Material2 的 colors 和 typography,和当前 Android Studio 模板生成的默认代码不一致。
参考文档里的实现注释
developer.android.com/reference 这个庞大的 API 参考,除了接口说明,偶尔能看到一些实现细节。android/os/Looper 的文档里,关于 quit() 和 quitSafely() 的区别,解释了消息队列的排空机制:quit() 直接丢弃未处理消息,quitSafely() 只保证当前正在处理的消息完成,后续消息仍然可能丢失。这个行为和很多人直觉理解的"安全退出"不一样,文档特意用加粗字体强调了这一点。
android/view/Choreographer 的文档,关于 postFrameCallback 的回调时机,说明了它和 VSYNC 信号的关系,以及如果回调执行时间超过一个帧周期,会跳过下一帧的回调而不是延迟。这个细节对做自定义动画的开发者很重要,因为这意味着你不能在 FrameCallback 里做阻塞操作,否则不是掉一帧,而是连续掉多帧。
java/util/concurrent/Executors 这个 Java 标准库的文档,在 Android 开发者网站上有一份拷贝,但底部加了 Android 特有的注释。比如 newCachedThreadPool() 的文档,Android 版本额外说明"这个线程池在 Android 上可能导致内存泄漏,因为线程在空闲 60 秒后才会销毁,而应用生命周期可能短得多"。这种平台特定的注释,在标准 Java 文档里找不到。
一些个人常用的搜索技巧
最后说点方法论。developer.android.com 的站内搜索质量一般,我通常用 site:developer.android.com 配合 Google 搜索。一些技巧:搜 site:developer.android.com "Added in API level 31" 可以找到某个版本引入的所有 API;搜 site:developer.android.com/jetpack/androidx/releases "bug fix" 可以定位到具体哪个版本修复了某个问题。
另一个技巧是关注 URL 里的版本号。Android 文档支持 ?hl=zh-cn 这种语言参数,也支持 ?version=11 这种版本过滤。比如 developer.android.com/about/versions/11?version=11 会只显示 Android 11 特有的内容,过滤掉后续版本的补充。这个参数在文档页面之间跳转时有时会丢失,需要手动加回去。
还有些页面完全没有中文翻译,或者翻译质量很差。developer.android.com/training/testing 下面的 Espresso 和 UI Automator 文档,中文版的代码示例经常混用中英文标点,导致复制粘贴后编译错误。这种时候切回英文版更可靠,URL 里把 zh-cn 换成 en 就行。
这些隐藏页面和工具,大部分不会出现在你的日常浏览路径里,但遇到特定问题时,它们往往比 Stack Overflow 上的二手答案更准确。Google 的文档组织方式比较分散,同一个主题的内容可能拆在多个路径下,需要养成翻相关链接的习惯。当然,文档本身也有滞后和错误,最终还是要以源码和实际测试为准。