简介:Android SDK (SDK Platforms)-android-34-ext10.zip 是一份针对 Android 34 平台定制 SDK 组件的离线扩展包,面向需要搭建或补全 Android 开发环境的开发者、测试人员及需要复现构建配置的一线应用与系统工程师。资源标签为 AndroidSDK,内容与 android-34-ext10 扩展版本对应,可用于离线安装 SDK Platforms 组件、补充 API 等级接口与系统镜像描述,也可作为理解 SDK 目录结构与构建工具的参考素材。压缩包共 2000 个文件,以 1974 个 xml 为主,辅以 22 个 html 与 4 个 txt;xml 主要承载平台 API 描述、资源定义及设备配置,html 为文档说明页,txt 则记录版本信息或安装说明,包体整体约 60.15MB,结构紧凑便于快速部署。该资源已有 353 人学习使用。获取后可离线查阅 Android 34 平台的 API 等级定义、权限声明及组件清单,尤其适合网络受限环境下的 SDK 补全、模拟器构建与编译环境复现。
1. 打开 Android Studio 却拉不下 android-34-ext10.zip:这个包到底卡在哪
很多人第一次见到 android-34-ext10.zip 这个文件名,是在国内网络环境下用 Android Studio 配置 SDK 时:SDK Manager 的 SDK Platforms 列表里,"Android SDK Platform 34" 旁边还有一个带着 "(ext10)" 后缀的条目,勾选它就会触发下载一个名为 android-34-ext10.zip 的压缩包。运气好时秒下,运气差时进度条停在 40% 不动,最后报错 "SDK component installation failed",而 Gradle 同步又反复提示找不到platforms;android-34-ext10。这个 zip 不是普通的补丁包,而是 API 34 的扩展平台包,用于编译依赖 SDK 扩展级别(Extension Level)10 的应用。本篇就来拆开这个文件,讲清楚它的机制、离线安装步骤、Gradle 侧的配置方法,以及最容易让人翻车的几个场景。
2. android-34-ext10 的定位:为什么 API 34 有两个 SDK 平台包
2.1 扩展级别机制从哪来:Android 11 之后,新 API 不再依赖整机升级
在 Android 10 及以前,Google 想让 App 用上一个新 API,通常要等手机厂商推进系统升级,厂商不推,开发者就只能看着 API 列表干瞪眼。从 Android 11(API 30)开始,系统引入了 SDK Extension 机制:把一部分新 API 塞进独立的框架扩展模块里,厂商只需更新这个模块,App 就能在新系统上调用新版 API,不需要整个系统版本跳变。这个机制在 Android 12、12L、13 里一路延续,到 Android 14(API 34)时,Google 已经将扩展级别推到了 10。android-34-ext10这个平台包,就是 API 34 的第 10 个扩展快照。
SDK Manager 里同时出现两个 34,并不是 bug。基础的platforms;android-34对应的是 Android 14 发布时的原始 API surface,而platforms;android-34-ext10则是在那个 surface 之上叠加了后续由扩展机制追加的 API stub。对平时只做常规 View、Room、Retrofit 开发的团队来说,基础包就够用;但如果你在代码里调到了@RequiresExtension(10)注解标记的方法或类,编译时就缺不了 ext10 这个包。
2.2 两个平台包在目录结构和内容上的差异
安装后,两个包分别位于 SDK 根目录下的platforms/android-34和platforms/android-34-ext10。我的习惯是用tree -L 1快速确认一下,观察它们的差异。基础包里是一个完整的 android.jar 加 build.prop、package.xml 和 data 目录;ext10 包的目录结构看起来差不多,但 android.jar 的体积通常会更大一些,因为里面补充了扩展 API 对应的类和方法签名。
不过要明白一件事:ext10 包里的 android.jar 是编译期使用的 stub 文件,只包含公共 API 的签名和注解信息,不含可执行代码。运行时最终调用的是设备上系统分区里的 framework 实现。换句话说,即使你本地装好了 ext10 包,也只能保证编译期认识这些新 API,设备端是否真的支持,还要看设备厂商有没有做对应扩展模块的 ODM 实现。这就是为什么 Google 在文档里反复强调:"在 manifest 中声明所需扩展级别"。
2.3 判断当前 SDK 是否已经包含 ext10 的检查命令
在深入安装之前,建议先对当前环境做一次摸底。以下命令在 macOS/Linux 的终端里运行,Windows 用户把sdkmanager换成sdkmanager.bat。
echo "ANDROID_HOME=${ANDROID_HOME:-<未设置>}" echo "ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT:-<未设置>}" ls "${ANDROID_HOME}/platforms" 2>/dev/null || ls "${ANDROID_SDK_ROOT}/platforms" "${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" --list_installed 2>/dev/null | grep "android-34"这段逻辑是:先打印两个常见的环境变量,确认 SDK 根目录在哪;再列出 platforms 目录下已经装了哪些平台包;最后通过sdkmanager --list_installed把已安装的包列表过滤出包含android-34的行。如果最后一步输出里有platforms;android-34-ext10,说明机器上已经准备好了,不需要重复安装;如果只有platforms;android-34,那 Gradle 构建里只要出现compileSdkExtension = 10,就会立刻报错。
另外要留意一个点:部分团队的 CI 机器会从项目仓库里根据local.properties的sdk.dir指定 SDK 路径,如果ANDROID_HOME和ANDROID_SDK_ROOT都没有设置,上面脚本的第一行会打印未设置,这时就要以local.properties为准。这类环境变量优先级问题,后面避坑章里专门说。
3. 离线安装 android-34-ext10:从拿到 zip 到 Android Studio 识别
3.1 前置检查:确认 cmdline-tools 版本与目录权限
安装前先确认两件事。一是 cmdline-tools 要能正常工作,许多旧项目里用的是android命令(早已废弃),装着 tools 目录;新式做法是cmdline-tools/latest。如果本机只有一个旧版命令行工具,建议先用 Android Studio 的 SDK Manager 升级 cmdline-tools。
二是目录权限。macOS 和 Linux 下,sdkmanager安装组件会往$ANDROID_HOME/platforms下写入新目录;如果 SDK 装在了/usr/local/share/android-sdk这类需要 root 权限的路径,就会遇到 "Permission denied"。我一般会用编辑器的终端把 SDK 根目录属主改为当前用户,而不是用 sudo 去跑 sdkmanager,否则后面 Android Studio 写缓存还会出权限错乱。Windows 下同理,用管理员身份运行 PowerShell 装一次,之后就不用再提权了。
3.2 方式一:sdkmanager 在线安装,不碰 zip
最省事的方式是直接让 sdkmanager 从 Google 仓库拉取platforms;android-34-ext10:
"${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" "platforms;android-34-ext10"命令执行过程中会走 HTTP 下载,包体大约几十 MB,取决于当时的 revision。成功后sdkmanager --list_installed里就能看到这一项,package.xml 也会一并写入,Android Studio 之后做 SDK 检查时能正常识别。这种方式对网络稳定、不需要内网离线部署的场景最合适,唯一的问题就是下载链路可能超时。如果你需要反复在十几台机器上装同样的环境,用在线方式就很浪费时间,这时就该走离线 zip 路线。
3.3 方式二:手动解压 zip 并放到 SDK 根目录
假设你已经通过某种渠道拿到了 android-34-ext10.zip,比如内网镜像、同事的缓存目录,或是临时用稳定网络手动下载。放置路径有个关键规则:解压后的内容要能直接让platforms/android-34-ext10成为一个合法平台包目录。我一般会这样做:
SDK_ROOT="${ANDROID_HOME:-${ANDROID_SDK_ROOT}}" mkdir -p "${SDK_ROOT}/platforms/android-34-ext10" unzip android-34-ext10.zip -d "${SDK_ROOT}/platforms/android-34-ext10" ls -l "${SDK_ROOT}/platforms/android-34-ext10"这里有个很容易搞错的地方:有些 zip 包内部会自带一层顶层目录,比如android-34-ext10/套在外面,解压时如果不加-j(junk paths),就会变成${SDK_ROOT}/platforms/android-34-ext10/android-34-ext10/android.jar,导致目录结构深度多了一层。正确姿势是先解压到一个临时目录,观察实际结构,再把内容移动到目标目录。上面命令里-d指定了目标目录,但如果 zip 本身带顶层目录,就要改用unzip android-34-ext10.zip -d /tmp/ext10再整体移动。
安装完成后,${SDK_ROOT}/platforms/android-34-ext10/下应当能看到android.jar、build.prop、package.xml(如果有)和data目录。光有 android.jar 还不够,构建工具还会读 package.xml 来确认组件版本和许可状态,所以下一步必须处理这个问题。
3.4 补上 package.xml:让 Android Studio 承认这个包是已安装状态
手动解压通常会遇到一个尴尬:zip 里可能根本没有 package.xml,或者有但内容不完整。这个文件是 SDK Manager 的"安装清单",缺了它,Android Studio 的 SDK Manager 界面里对应条目不显示勾选状态,命令行执行sdkmanager --list_installed也搜不到这个组件,Gradle 构建却又能直接编译(因为它只按路径找 android.jar)。这种"半黑匣子"状态最耽误排查。
常见做法是:在一台能够联网的机器上用sdkmanager --install "platforms;android-34-ext10"正常安装一次,然后把该机器的platforms/android-34-ext10/package.xml拷贝到离线环境对应的目录里。package.xml 里包含组件路径、版本号、许可哈希和文件清单,不同 revision 的包,哈希和文件清单会不同,所以不要从网上随便找一份就用。
cp /tmp/ref-sdk/platforms/android-34-ext10/package.xml \ "${SDK_ROOT}/platforms/android-34-ext10/package.xml"执行完后,重新打开sdkmanager --list_installed,应能看到platforms;android-34-ext10。如果之前 Android Studio 正开着 SDK Manager,要点一下 Refresh 或干脆重启 Android Studio,它才会重新扫描 SDK 目录。这一步属于典型的"明明文件都放好了,界面却装看不见",别急着怀疑路径写错,先刷新再看。
3.5 在 Android Studio 的 SDK Platforms 界面确认勾选状态
打开 Android Studio,进入 Settings / Appearance & Behavior / System Settings / Android SDK,切到 SDK Platforms 标签页,勾选右下角的 "Show Package Details"。列表里会出现两个 Android 14 平台:
- Android SDK Platform 34
- Android SDK Platform 34 (ext10)
如果 ext10 那一项已经显示 "Installed",说明离线安装成功。如果没有,优先检查 package.xml 是否存在以及 path 字段是否为platforms;android-34-ext10,其次检查目录名称是否完全一致,ext10大小写、下划线等细节都会导致识别失败。
另外注意一件事:Android Studio 的 SDK Manager 并不会自动帮你加载手动放置的组件到正在运行的工程里。在 Gradle sync 之前,最好 Clean Project 一次,否则 build 目录里的旧编译产物会让误报继续存在,干扰你判断是否真的装好。
4. 在构建配置里真正用上 ext10:compileSdkExtension 的同步设置
4.1 Gradle 侧必须同时设置 compileSdk 和 compileSdkExtension
装了 ext10 平台包,并不代表 Gradle 构建就自动使用它。AGP 在编译时需要明确知道两点:基础平台是什么、扩展级别是多少。只写compileSdk = 34而缺少compileSdkExtension = 10,AGP 会使用默认的扩展级别,该级别通常低于 10。此时如果代码里调用了 ext10 的 API,编译器会报Call requires API level 34 (current min is 34), actual extension level is 5之类的信息。
以 Kotlin DSL 为例,一个能使用 ext10 的build.gradle.kts片段:
android { compileSdk = 34 compileSdkExtension = 10 defaultConfig { minSdk = 26 targetSdk = 34 } }compileSdk告诉 AGP 使用 API 34 的基础 android.jar;compileSdkExtension = 10告诉它额外叠加扩展级别 10 的 API。这里的minSdk不需要跟着改成 34,因为扩展机制是向后兼容的,设备端基于模块更新来提供能力,而不是要求系统整体版本够高。targetSdk与本次讨论也没有直接关系,它影响的是系统兼容性行为。
从 AGP 8.1 开始,compileSdkExtension这个 DSL 属性就是稳定的。如果你用的是更老的 AGP 7.x,就要考虑升级构建工具链了,否则即使装好了 ext10 平台包,Gradle 同步时也会报不认识这个属性。
4.2 验证编译时实际使用的扩展级别:加一个任务打印
配置改好后,怎么确认构建时真的走了 ext10?常见做法是利用 AGP 的androidComponentsAPI,在 Gradle 配置阶段注册一个任务,打印每个变体的编译 SDK 信息。我一般会在根项目的build.gradle.kts里临时加这样的代码:
androidComponents { onVariants(selector().all()) { variant -> println("variant=${variant.name}, compileSdk=${variant.compileSdkVersion}") } }运行./gradlew :app:assembleDebug时,会在配置阶段看到类似compileSdk=android-34-ext10的输出,说明编译用的 SDK platform 里包含了扩展级别信息。如果想更精确地拿到扩展级别数值,可以在模块级build.gradle.kts里注册任务:
tasks.register("printSdkInfo") { doLast { println("compileSdk=${android.compileSdk}") println("compileSdkExtension=${android.compileSdkExtension}") } }然后执行./gradlew printSdkInfo。这个任务在配置阶段结束后读取 android block 的最终值,两个输出分别对应你在构建文件里填写的数字。若输出compileSdkExtension=null,说明 AGP 版本不支持或在配置阶段没有对该变体执行计算,需要把任务的执行时机放到afterEvaluate里。
4.3 三种常见误配置的差别:minSdk、targetSdk 与 extension level
不少新手会把compileSdkExtension和minSdk混为一谈,这里做个小对比:
| 配置项 | 控制什么 | 典型取值 | 与 ext10 的关系 |
|---|---|---|---|
| minSdk | App 最低可安装的系统版本 | 26 | 无关,设备必须满足系统版本,但不要求扩展级别 |
| targetSdk | 系统以哪个版本的行为规则来运行 App | 34 | 无关,影响运行时兼容行为 |
| compileSdk | 编译时使用哪个基础 SDK 平台 | 34 | 基础依赖 |
| compileSdkExtension | 编译时叠加哪个扩展级别的 API | 10 | 直接决定是否用到 ext10 包 |
有一种典型场景是:targetSdk = 34、compileSdk = 34,但compileSdkExtension没有写,于是项目编译通过,运行也正常,直到某天你在某台设备上遇到NoSuchMethodError,才发现新调用的 API 其实来自 ext10。这个坑在 Android 14 的进程加大背景下升级时特别容易踩到。
5. 避坑手册:android-34-ext10 安装与使用的 5 类常见问题
5.1 现象:只装了基础包,Gradle 报错 "Failed to find target with hash string 'android-34-ext10'"
在报错列表里看到这一行时,说明 Gradle 已经识别出项目需要扩展平台包,但本机 SDK 里没有。原因通常是 SDK Manager 里勾选了 ext10 但下载失败,进度条中断;或编译脚本里写死了compileSdkExtension = 10,而团队其他成员只装过基础包。解决方法是先跑sdkmanager --list_installed | grep android-34,确认缺的是哪个包,然后执行sdkmanager "platforms;android-34-ext10"补装。如果在线失败,就按第 3 节的离线流程操作。另外检查一下项目的local.properties,确认sdk.dir指向的 SDK 根目录和命令行操作的是同一个,两条 SDK 路径并存是最常见的隐性原因。
5.2 现象:zip 解压放置后,SDK Manager 里仍显示未安装
文件明明在platforms/android-34-ext10下,android.jar 也能打开,但 Android Studio 的 SDK Manager 界面就是不勾选。原因几乎都是 package.xml 缺失或内容不匹配。Android Studio 扫描 SDK 组件时,会逐个目录读取 package.xml 并校验许可证状态,没有这个文件就认为组件未安装。解决方法是按照 3.4 节,从已正常安装的机器上复制 package.xml 过来。注意不要复制完就完事,还要确认 XML 里的path属性是platforms;android-34-ext10,一旦 path 写成了别的(比如从其他组件复制的),界面依然识别不了。
5.3 现象:命令行sdkmanager --list_installed找不到 ext10,但 Gradle 能编译
这是个典型的"假装好"状态:Gradle 按目录路径找 android.jar,只要能找到就继续编译;而 sdkmanager 按 package.xml 记录判断组件是否安装,两者判断标准不同。如果只想让编译通过,不理会命令行工具的输出也没问题,但后续一旦执行sdkmanager --licenses或 SDK 修复,缺失的 package.xml 会导致组件被当成损坏项清理掉。我的建议是遇到这种不一致,第一时间补 package.xml,别等 CI 镜像做缓存时再来排查。
5.4 现象:AGP 升级后compileSdkExtension突然失效
升级 Android Gradle Plugin(比如从 8.0 升到 8.5)后,原先能用的扩展 API 编译不通过,提示requires extension level 10。原因在于 AGP 对扩展级别的默认值处理发生过变化,旧版本可能自动使用了较高的默认级别,新版本则更保守,只取基础级别。项目里compileSdkExtension没显式声明或写在gradle.properties里被覆盖时,就会出现这种翻车。解决方法是把compileSdkExtension = 10显式写进所有用到扩展 API 的模块build.gradle.kts,不要依赖 AGP 的隐式默认值。
5.5 现象:Windows 下解压后 android.jar 损坏,或提示文件长度不够
某些 Windows 解压工具路径太长会截断,或者下载不完整导致 zip 内部校验失败。常见表现为解压过程最后报错,但 android.jar 仍然生成,看文件大小却发现跟预期差几 KB。解决方法是先核对下载文件的 SHA-256,和源站已安装机器上 package.xml 里的<checksum>比对;如果一致,则换 7-Zip 解压并确保输出路径短,不要直接解压到桌面带中文的深层目录里。之后再在 SDK 根目录下重新做一次目录对齐。
6. 把 android-34-ext10 固化进 CI 镜像:一条命令完成离线预置
6.1 离线预置脚本设计
当团队需要反复在本地、CI 容器里准备 Android 构建环境时,最怕的就是每次都走一遍在线下载。我习惯的做法是把 android-34-ext10.zip 和对应的 package.xml 放进一个内网文件服务,预置脚本只做三件事:检测目标目录是否存在;不存在则解压并补 package.xml;最后打印安装结果。
#!/usr/bin/env bash set -euo pipefail SDK_ROOT="${ANDROID_HOME:-${ANDROID_SDK_ROOT:?请先设置 ANDROID_HOME 或 ANDROID_SDK_ROOT}}" EXT_ZIP="/opt/sdk-cache/android-34-ext10.zip" EXT_SRC="/opt/sdk-cache/package.xml" TARGET="${SDK_ROOT}/platforms/android-34-ext10" if [[ ! -d "${TARGET}/android.jar" ]]; then mkdir -p "${TARGET}" tmpdir="$(mktemp -d)" unzip -q "${EXT_ZIP}" -d "${tmpdir}" if [[ -f "${tmpdir}/android-34-ext10/android.jar" ]]; then cp -R "${tmpdir}/android-34-ext10/." "${TARGET}/" else cp -R "${tmpdir}/." "${TARGET}/" fi cp "${EXT_SRC}" "${TARGET}/package.xml" rm -rf "${tmpdir}" fi "${SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager" --list_installed | grep "platforms;android-34-ext10"脚本里的参数说明:EXT_ZIP与EXT_SRC指向内网缓存路径,TARGET是 SDK 根目录下的平台包目录。第一层if判断android.jar是否存在,避免重复解压;解压到临时目录后,根据 zip 是否包含顶层目录决定拷贝方式,这样无论 zip 打包结构如何都能对齐目录。最后一行执行sdkmanager --list_installed,如果 package.xml 补得正确,输出里会出现对应条目,这条命令同时起到了验证作用。
6.2 用最小工程做最终验证
预置完成后,最可靠的验证方式不是看界面,而是跑一次真实编译。拉下一个 compileSdk = 34、compileSdkExtension = 10 的最小工程,执行命令行构建:
./gradlew :app:compileDebugKotlin --refresh-dependencies如果编译输出没有Failed to find target一类的报错,说明 android-34-ext10 已经被正确加载。之后正常进行测试、签名和打包流程即可。我在不同团队的 CI 迁移里遇到过很多类似的坑,这类扩展平台包的预置问题归根结底都是"目录放对、package.xml 补对、编译配置写对",三件事各做一次,后面就再不会因为这十来 MB 的包反复折腾了。这套方法同样适用于 android-33-ext5、android-34-ext10 等所有带扩展级别的平台包。希望这篇笔记能帮你在 Android SDK 的组件管理上少走一段弯路。
本文还有配套的精品资源,点击获取