简介:面向 Android 应用开发者的 android-33 平台资源包,对应 Android 13(API 33)版本,适合需要在该版本下编译、调试与兼容性测试的初中级开发者使用。压缩包共约 2000 个文件,以 1974 个 xml 资源描述文件为主,辅以 22 个 html 说明页面与少量 txt 文本,整体约 60.84MB,解压后放入 SDK 的 platforms 目录即可被 Android Studio 等 IDE 识别选用。资源围绕平台库、API 文档与系统接口展开,可帮助读者补齐目标版本平台文件、核对 API 级别差异,并在构建与调试中验证应用对 Android 33 特性的兼容情况。已有 857 人学习下载,适合作为多版本 SDK 环境搭建与版本适配的参考素材。
1. 拿到 android-33 这个 SDK 包,先搞清楚它到底解决什么问题
做 Android 构建的人大概都遇到过这种场面:CI 上跑得好好的流水线,换台机器./gradlew assembleDebug直接报Failed to find target with hash string 'android-33',或者 Android Studio 弹窗提示 SDK Platform 缺失、compileSdkVersion 33无法解析。这类报错十有八九不是代码问题,而是本地或构建机上缺了 android-33 这个平台包。它属于 Android SDK 里的 Platform 组件,对应 API Level 33,提供android.jar、平台资源、aapt2依赖的框架资源以及构建时需要的元数据。没有它,任何把compileSdk或targetSdk指向 33 的工程都编不过。这篇笔记面向需要离线部署、批量配置构建环境、或者被 SDK 版本卡住的 Android 开发者,把这份资源的组成、安装路径、验证方式和常见翻车点拆开讲清楚,让你拿到包就能落地,而不是对着报错猜。
2. android-33 包里到底装了什么:目录结构与构建链路定位
2.1 从 SDK 根目录看 Platform 包的真实构成
很多人把 android-33 当成一个“安装包”,其实解压后它就是一个标准目录,落在$ANDROID_SDK_ROOT/platforms/android-33/下面。判断一个 Platform 包是否完整,看这几个关键文件就够了:
| 文件/目录 | 作用 | 缺失后的典型表现 |
|---|---|---|
android.jar | 编译期 API 存根,所有import android.*的符号来源 | 编译报cannot find symbol,大量 android 包类找不到 |
package.xml | SDK 管理器识别该平台的元数据 | sdkmanager 列表里看不到 android-33,AGP 报 target 不存在 |
build.prop | 平台版本、API Level、代号等属性 | 构建工具读取版本信息失败 |
data/ | 平台资源、字体、布局等框架资源 | aapt2 链接资源阶段报错 |
optional/ | 可选组件(如android.jar的附加存根) | 一般不影响基础编译,特定 API 才需要 |
source.properties | 平台来源与版本标识 | 版本校验异常 |
这里要区分一个容易混淆的点:android-33 是Platform,不是Build-Tools,也不是Platform-Tools。Build-Tools 提供aapt2、d8、zipalign这些可执行工具,Platform-Tools 提供adb、fastboot。三者版本独立,缺 Platform 只影响编译期的 API 解析,不会让adb devices失效。反过来,Build-Tools 版本过低也可能导致新平台资源处理失败,所以排查时要把这两条线分开看。
2.2 为什么 compileSdk 33 必须匹配这个包
AGP(Android Gradle Plugin)在配置阶段会拿compileSdkVersion去 SDK 目录里找对应 hash 的平台。hash 的命名规则是android-<API Level>,33 就对应android-33。找到之后,AGP 把android.jar塞进编译 classpath,同时把平台资源目录交给 aapt2 做资源链接。如果目录名不对,比如手动解压成了android-33-ext或者platforms/33,AGP 就认不出来,报的错还是那句Failed to find target with hash string 'android-33'。所以安装时目录名必须严格是android-33,这一点在离线拷贝场景里特别容易翻车。
另一个常被忽略的是package.xml。有些精简版 SDK 包为了减小体积把package.xml删了,解压后目录结构看着齐全,但 sdkmanager 不认,AGP 在某些版本下也会因为读不到元数据而判定平台无效。我一般拿到包先ls platforms/android-33/package.xml,没有就直接判定这个包不能用于正式构建环境。
2.3 版本边界:33 和 34、32 的兼容关系
API 33 对应 Android 13,targetSdk 33会触发一批行为变更,比如通知权限POST_NOTIFICATIONS需要运行时申请、细化的媒体权限拆分。这些是运行时行为,和 SDK 包本身无关,但选型时要清楚:装 android-33 是为了编译,不是为了自动获得 33 的行为适配。工程里compileSdk 33配targetSdk 33是常见组合,但compileSdk 34配targetSdk 33也完全合法,前者只决定你能调用哪些 API,后者决定运行时行为开关。所以如果你的工程只是被compileSdkVersion 33卡住,装这个包就够;如果还想用 34 的新 API,那得另外装 android-34,两者可以共存于platforms/下,互不覆盖。
3. 把 android-33 装进构建环境:命令行、Gradle 与离线三条路径
3.1 用 sdkmanager 在线安装与校验
最省事的方式还是走 sdkmanager,前提是构建机能访问 SDK 仓库。先确认 sdkmanager 位置,通常在$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/或旧版的tools/bin/:
# 列出已安装和可安装的 platform 包,确认 android-33 是否在列 sdkmanager --list | grep "platforms;android-33" # 安装 android-33 平台包,--sdk_root 显式指定 SDK 根目录避免装错位置 sdkmanager --sdk_root="$ANDROID_SDK_ROOT" "platforms;android-33" # 安装后复查,输出里应出现 platforms;android-33 且无 update available 标记 sdkmanager --list_installed | grep "platforms;android-33"--sdk_root这个参数建议每次都带上。血泪经验是:机器上如果同时存在 Android Studio 自带 SDK 和命令行单独装的 SDK,不指定 root 时 sdkmanager 可能装到另一个目录,Gradle 却读的是local.properties里那个,结果就是“明明装了还是报找不到”。--list_installed比--list更适合做校验,因为它只列已装项,输出短,脚本里好判断。
3.2 在 Gradle 里锁定 compileSdk 与 SDK 路径
装好包之后,工程侧要保证compileSdk指向 33,并且 SDK 路径解析正确。模块级build.gradle常见写法:
android { namespace 'com.example.demo' compileSdk 33 defaultConfig { applicationId "com.example.demo" minSdk 24 targetSdk 33 versionCode 1 versionName "1.0" } }compileSdk 33是硬约束,AGP 会据此找platforms/android-33。minSdk 24和targetSdk 33是运行时边界,和平台包安装无关,但三者要一起看:minSdk高于平台包支持范围、或者targetSdk超过compileSdk,AGP 都会给警告甚至报错。SDK 路径则优先读local.properties的sdk.dir,其次读环境变量ANDROID_SDK_ROOT/ANDROID_HOME。CI 上我一般不用local.properties(它不该进版本库),而是显式导出环境变量:
# CI 脚本里固定 SDK 根目录,避免依赖机器默认配置 export ANDROID_SDK_ROOT=/opt/android-sdk export PATH="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$ANDROID_SDK_ROOT/platform-tools:$PATH" # 验证 Gradle 实际解析到的 SDK 路径,排查“装错目录”类问题 ./gradlew -q android:properties 2>/dev/null | grep -i sdk最后那条命令不是所有 AGP 版本都支持,更稳的替代是./gradlew --info assembleDebug看日志里打印的 SDK location。参数上要留意:ANDROID_SDK_ROOT在新版工具里已逐步取代ANDROID_HOME,两者同时存在且不一致时,不同工具读取优先级不同,统一成一个值能省掉很多玄学问题。
3.3 离线包手动落位与完整性检查
内网构建机、隔离环境里没法走 sdkmanager,就得手动把 android-33 目录拷进platforms/。步骤不复杂,但顺序和校验不能省:
# 1. 确认目标 SDK 根目录存在 platforms 子目录 mkdir -p "$ANDROID_SDK_ROOT/platforms" # 2. 解压离线包,确保解压后目录名严格为 android-33 unzip android-33.zip -d "$ANDROID_SDK_ROOT/platforms/" # 3. 校验关键文件是否齐全,缺一个都可能导致构建失败 for f in android.jar package.xml build.prop source.properties; do test -f "$ANDROID_SDK_ROOT/platforms/android-33/$f" \ && echo "OK $f" || echo "MISS $f" done # 4. 用 aapt2 快速验证平台资源可读(Build-Tools 需已安装) "$ANDROID_SDK_ROOT/build-tools/33.0.2/aapt2" dump resources \ "$ANDROID_SDK_ROOT/platforms/android-33/android.jar" > /dev/null && echo "aapt2 OK"第 3 步的循环检查是我每次离线部署必跑的,package.xml和source.properties是最容易被精简包删掉的两个文件。第 4 步用 aapt2 读android.jar是个低成本冒烟测试,能提前暴露 jar 损坏或截断的问题,比等到 Gradle 编译到一半才报错强。注意 Build-Tools 版本号按实际安装填,别照抄。
4. 构建报错排查:android-33 相关的五类高频翻车
4.1 现象:Failed to find target with hash string 'android-33'
原因通常有三种:平台包根本没装、装到了别的 SDK 根目录、目录名被改过。解决顺序是先ls $ANDROID_SDK_ROOT/platforms/看有没有android-33,再对比 Gradle 日志里打印的 SDK location 是否和这个根目录一致,最后检查目录名有没有多余后缀。三者都对还报错,就看package.xml是否存在且内容里的 API Level 是 33。
4.2 现象:编译期大量 cannot find symbol,指向 android.* 类
原因多半是android.jar不完整或被替换成了空壳。有些第三方“精简 SDK”会把 jar 裁掉一部分。解决是用unzip -l android.jar | wc -l看条目数量,正常应在数万级别,明显偏少就是被裁过,换完整包。另一个可能是 classpath 里混入了别的平台 jar,检查依赖树里有没有误引入的android.jar副本。
4.3 现象:sdkmanager 列表里看不到 android-33,但目录明明在
原因是缺package.xml或该文件格式与当前 cmdline-tools 版本不匹配。解决是优先用 sdkmanager 重装覆盖;离线环境则从同版本完整包里补回package.xml。注意不要从高版本平台包里随便拷一个package.xml过来改 API Level,字段结构对不上时 sdkmanager 会直接忽略该目录。
4.4 现象:资源链接阶段 aapt2 报错,提示找不到框架资源
原因是data/目录缺失或权限不对。data/res下的框架资源是 aapt2 链接时解析@android:引用的来源。解决是确认platforms/android-33/data/res存在且可读,容器环境里还要注意挂载权限,只读挂载一般没问题,但属主错误可能导致读取失败。
4.5 现象:本地能编,CI 报 SDK 版本不一致
原因是 CI 上ANDROID_HOME和ANDROID_SDK_ROOT指向不同目录,或者 Gradle 缓存了旧的 SDK 路径。解决是统一环境变量、清理~/.gradle/caches里与 SDK 定位相关的缓存,并在 CI 脚本开头打印一次实际 SDK 路径做留痕。这个坑很隐蔽,因为报错信息不会告诉你它读的是哪个目录。
5. 进阶:把 android-33 固化进可复现的构建镜像
单机装一次不算本事,团队里十几台构建机、每次换 CI runner 都要重来一遍才叫麻烦。我的习惯是把 SDK 安装收敛成一个幂等脚本,配合校验和固定版本,让“装 SDK”这件事从手工操作变成构建流程的一部分。核心思路是:平台包用固定 URL 或内网制品库地址,下载后校验 SHA-256,解压到固定路径,跑一遍完整性检查,任何一步失败就整体失败,不留半装状态。
#!/usr/bin/env bash set -euo pipefail SDK_ROOT="${ANDROID_SDK_ROOT:?must set ANDROID_SDK_ROOT}" PKG_URL="https://internal.example/sdk/android-33.zip" # 内网制品库地址 EXPECTED_SHA256="<填入实际校验值>" TMP_ZIP="$(mktemp /tmp/android-33.XXXX.zip)" # 下载并校验,校验不过直接退出,避免把坏包铺进 SDK 目录 curl -fsSL "$PKG_URL" -o "$TMP_ZIP" echo "$EXPECTED_SHA256 $TMP_ZIP" | sha256sum -c - # 幂等落位:先删旧目录再解压,保证不会残留半旧半新文件 rm -rf "$SDK_ROOT/platforms/android-33" unzip -q "$TMP_ZIP" -d "$SDK_ROOT/platforms/" rm -f "$TMP_ZIP" # 落位后强制校验,缺文件即失败 for f in android.jar package.xml build.prop source.properties; do test -f "$SDK_ROOT/platforms/android-33/$f" || { echo "missing $f"; exit 1; } done echo "android-33 installed and verified at $SDK_ROOT"这段脚本里几个参数值得说清楚。set -euo pipefail保证任何一步非零退出都中断,避免“下载失败但继续解压空目录”这种假成功。sha256sum -c是防坏包的关键,内网传输、对象存储分片都可能出问题,校验和是唯一可靠的后悔药。rm -rf先删后解压是为了幂等,重复执行结果一致,不会因为上次残留的旧文件让校验误判通过。EXPECTED_SHA256必须每次制品更新时同步改,建议把它和包地址一起放进版本库的配置文件,而不是硬编码在脚本里。
验证层面,除了文件存在性,我还会在镜像构建的最后跑一次最小工程的assembleDebug,用真实构建链路做端到端确认。这一步比任何单点检查都可信,因为它同时验证了 Platform、Build-Tools、AGP 三者的配合。镜像里再固定JAVA_HOME和 Gradle 版本,整套环境就基本可复现了。
从那以后我每次给新构建机配环境,都强制先跑一遍这个幂等脚本加最小工程编译,再让业务流水线接入,宁可多花五分钟,也不在“环境问题还是代码问题”上反复扯皮。希望帮到你。
本文还有配套的精品资源,点击获取