
简介面向无需完整安装 Android Studio 的 macOS 开发者这份官方命令行工具包提供基于终端完成 SDK 管理与构建分析的核心能力适用于 CI/CD 自动化、远程开发或轻量环境配置等场景。工具包共 104 个文件压缩后约 146.49MB内容以 93 个 Java 归档jar为主体为各命令提供运行时依赖同时包含 sdkmanager、avdmanager、apkanalyzer、lint、profgen、screenshot2 等可执行脚本分别覆盖 SDK 组件下载与更新、虚拟设备管理、APK 信息解析、代码静态检查、性能配置生成和界面截图等任务基本形成一条完整的命令行工具链。另有属性配置、说明文档等辅助文件便于开发者快速了解各项命令的用途与调用方式。目前已有 200 人学习下载适合希望摆脱 IDE 束缚、在纯终端下搭建 Android 构建环境的开发者也可直接嵌入脚本完成批量 SDK 组件安装与产物分析显著提升自动化效率。1. macOS 上的 Android 命令行工具不装 IDE 也能跑通 SDK 全流程如果你和我一样在 mac 上只想要一个轻量的 Android 开发环境或者要给 CI 机器配一套不带图形界面的构建工具链那么 Android 命令行工具commandlinetools-mac-11076708-latest.zip就是那包后悔药。它本质上是 Android Studio 里那套 SDK 管理能力的命令行版本解压后就能拿到 sdkmanager、apkanalyzer、avdmanager、lint 这些真正干活的命令。不需要安装几个 GB 的 IDE不需要反复点向导一个 zip 解压、配好 JAVA_HOME就能把 SDK 平台包、构建工具、模拟器镜像全部拉下来。这篇笔记从我实际拆包和配置的经历出发把每个工具的用法、参数和我在 mac 上踩过的坑一次说清楚。2. 装好第一步sdkmanager 与命令行环境配置2.1 解压与目录结构bin 下的命令和 lib 下的 jar 各管什么下载下来的 zip 包我一般放在~/android/cmdline-tools下解压后第一件事是看目录结构。bin/目录里躺着sdkmanager、apkanalyzer、avdmanager、lint这几个可执行脚本真正的实现都在lib/目录的一堆 jar 里。这也是命令行工具和 Android Studio 最大的差别没有 IDE 外壳所有功能都是脚本加 Java 进程直接调用。lib/下的 jar 不是摆设每个都对应一块能力。r8.jar是代码缩减和混淆引擎kotlin-compiler-mvn.jar和kotlin-reflect-1.9.0.jar说明工具链里内置了 Kotlin 编译与反射支持tools.lint-checks.jar是 lint 静态检查的检查器集合proto.jar、bcprov-jdk15on-1.67.jar、guava-31.1-jre.jar则是序列化、加密算法和通用工具库的运行时依赖。也就是说这套工具内部自己就是一套完整的 Java 应用集群只是把入口暴露成了命令行脚本。文件在工具链里的角色sdkmanager管理 SDK 平台、构建工具、系统镜像的下载与卸载apkanalyzer解析 APK读取 manifest、dex、资源、文件大小avdmanager创建和管理 Android 虚拟设备AVDlint静态代码检查输出 HTML/XML 报告r8.jar代码缩减与混淆引擎被 Gradle 或命令行调用tools.lint-checks.jarlint 的内置检查器实现需要注意一点这个包解压之后默认不会自动出现在PATH里而且不同版本的命令行工具对目录名有要求。新版工具会从cmdline-tools/latest/bin下读取命令所以我解压后会把文件夹重命名成latest再在环境变量里指过去。maven 配环境变量那套经验在这里不适用因为 SDK 的命令行工具不依赖ANDROID_SDK_ROOT去定位自身它只要求你知道自己把 zip 放哪了。2.2 PATH 与 JDK 17mac 上最容易翻车的一环命令行工具是 Java 应用所以 JDK 是第一道门槛。这个版本的 commandlinetools 需要 JDK 17如果你的机器上只有一个老版本的 JDK 8 或 11运行sdkmanager --list时会直接报类找不到或者版本不支持的错。我一般用 Homebrew 装 Zulu 17装完之后用/usr/libexec/java_home -v 17拿路径这个命令是 mac 上定位 Java 版本最省事的办法。# 在 ~/.zshrc 里追加以下内容 export JAVA_HOME$(/usr/libexec/java_home -v 17) export ANDROID_HOME$HOME/android/sdk export PATH$PATH:$ANDROID_HOME/cmdline-tools/latest/bin source ~/.zshrc配置逻辑分三段JAVA_HOME解决 Java 运行时来源ANDROID_HOME是 SDK 包的安装根目录PATH把 bin 下的四个命令暴露给终端。值得强调的是Android Studio 默认把 SDK 装在~/Library/Android/sdk但命令行工具并不强制要求这个路径你可以自定义到任意目录只要后续所有工具都引用同一个ANDROID_HOME就行。配置完成后用java -version和which sdkmanager各验证一次。很多 mac 用户在这步翻车是因为把配置写进了.bash_profile但系统默认 shell 是 zsh根本不读这个文件。我在第 4 章避坑部分会再展开讲这个问题。2.3 sdkmanager 参数详解装包、看版本、签协议sdkmanager 是整个工具链的入口几乎所有 SDK 组件都由它下载。第一次运行先执行--list看看远端有哪些包这一步同时会验证 JDK 环境是否正常。列表输出很长我一般会 grep 关键字比如只看平台包就用sdkmanager --list | grep platforms;。# 列出所有可用包 sdkmanager --list # 安装平台、构建工具和平台工具 sdkmanager --install platforms;android-34 build-tools;34.0.0 platform-tools # 接受所有开源协议的许可 sdkmanager --licenses这里的包名格式是组件的类型;版本号platforms;android-34代表 Android 14 的 SDK 平台build-tools;34.0.0是构建工具版本。--licenses是必跑的一步新装的 SDK 目录里没有任何许可记录不执行的话后面用到aapt2、zipalign这类工具时会反复弹交互确认在脚本环境里直接卡死。--install可以同时传多个包名不要一个个装速度慢而且容易中途断掉。装完之后检查目录结构$ANDROID_HOME下应该出现platforms/android-34、build-tools/34.0.0、platform-tools三个目录。如果之后要用模拟器还需要再装一个emulator包和对应的系统镜像这个在下一章的 avdmanager 部分具体说。3. 四个高频工具实操apkanalyzer、avdmanager、r8 与 lint 的参数与输出解读3.1 apkanalyzer不打开 Android Studio 也能拆 APKapkanalyzer 是我在 macOS 上用得最频繁的工具它读 APK 的方式比 IDE 里的 Build Analyze APK 更直白适合在 CI 上验证产物。它的大部分子命令针对 APK 的单一维度设计比如看版本信息和最低支持版本用apk summary看 manifest 里的权限、组件用manifest print分析方法数和类数用dex packages。# 查看 APK 的基础信息版本号、SDK 版本、包名 apkanalyzer apk summary app-release.apk # 打印 AndroidManifest.xml 内容 apkanalyzer manifest print app-release.apk # 列出 dex 中的所有类、方法数判断是否接近 64K 方法数上限 apkanalyzer dex packages app-release.apkapk summary的输出会直接给出packageName、versionName、minSdkVersion、targetSdkVersion这几个字段适合做产物校验脚本的输入。manifest print输出的是可读文本不是二进制 XML适合快速确认某个权限是不是真的被合并进了最终包。dex packages输出的包名列表可以配合 grep 排查某个第三方 SDK 是否被完整打包进去比如怀疑推送 SDK 被打进 release 包时直接apkanalyzer dex packages app-release.apk | grep push一步定位。区别在于IDE 里的 APK 分析器只能看一个包命令行工具可以写进循环批量分析几十个渠道包这是它真正的价值所在。参数上需要注意部分子命令支持--human-readable让大小显示成 KB/MB 而不是字节写报告脚本时我一般都会加上避免在脚本里再做一次单位换算。3.2 avdmanager命令行创建模拟器avdmanager 做的事情是创建和管理 Android 虚拟设备对应 Android Studio 里的 Device Manager。但 IDE 里创建模拟器是图形化点选命令行下需要用-k参数指定系统镜像的包名包不存在时它会直接报错而不是自动下载。这个设计经常让人误以为命令写错了实际上是系统镜像没装。# 安装一个 arm64 架构的 Android 14 模拟器镜像 sdkmanager --install system-images;android-34;google_apis;arm64-v8a # 创建名为 ci_test 的 AVD使用 Pixel 6 设备定义 avdmanager create avd -n ci_test -k system-images;android-34;google_apis;arm64-v8a -d pixel_6 # 列出所有已创建的 AVD avdmanager list avd镜像包名的格式是system-images;平台版本;镜像类型;架构。Apple Silicon 的 mac 选arm64-v8aIntel 芯片的 mac 选x86_64选错架构会在启动模拟器时提示 HVF无法加载。-d pixel_6指定设备皮肤和分辨率配置这个参数不是必填但建议指定否则默认设备是 1280x720 的小屏跑起来之后 UI 布局跟真实机型差很远。创建完 AVD 只是第一步启动它还需要emulator包。sdkmanager --install emulator后直接执行emulator -avd ci_test就能拉起一个带界面的模拟器窗口。在 CI 环境下可以用-no-window -no-audio让它无头运行跑 UI 自动化测试时这是个常用组合。3.3 r8代码缩减与 keep 规则的写法r8 是 Android 构建链里的混淆和缩减引擎在命令行工具包里以lib/r8.jar形式存在。日常开发中它由 Gradle 插件调用但在命令行工具放这么个 jar意味着你可以脱离 Gradle 独立给一个 jar 或 APK 做代码缩减。我用它最多的场景是验证混淆规则——某个第三方库的 keep 规则写没写对不需要跑整个打包流程直接对产物 jar 执行一遍 r8 就能看出来。# 把 lib 下所有 jar 拼成 classpath避免缺依赖 CP$(ls $ANDROID_HOME/cmdline-tools/latest/lib/*.jar | tr \n :) # 对 input.jar 做 release 混淆输出到 out 目录 java -cp $CP com.android.tools.r8.R8 \ --release \ --output out \ --pg-conf proguard-rules.pro \ --lib $ANDROID_HOME/platforms/android-34/android.jar \ input.jar--release表示 release 模式会同时做代码缩减和资源优化--pg-conf指定混淆规则文件就是常见的那种-keep规则--lib指向 android.jar这是编译期库r8 需要它来解析 Android API 的类引用不会被打进输出包。规则文件里最常见的写法是保留某个包下的全部类-keep class com.example.demo.** { *; } -dontwarn java.lang.invoke.**-keep后面的类名模式决定了哪些类在混淆后保持原名反射调用的类、被注解处理的类、native 方法所在的类通常都要 keep。我第一次用 r8 时只写了一个包名结果运行时框架用反射找类找不到报ClassNotFoundException从那以后我都把反射入口列进规则文件再跑一次 r8 验证。这里顺便说一句lib/里的bcprov-jdk15on-1.67.jar和guava-31.1-jre.jar是 r8 运行时的加密和通用库依赖如果只把r8.jar放进 classpath会报NoClassDefFoundError上面脚本里把整个 lib 目录拼进 classpath 的做法就是为了规避这个问题。3.4 lint把静态检查接进打包流程lint 是 Android 生态里绕不开的静态检查工具tools.lint-checks.jar提供了检查器的实现。命令行工具自带的 lint 和 Android Studio 里那个 Lint 检查是同一套引擎不同的是它可以完全脱离 IDE 运行输出统一的报告文件适合接进打包流水线。# 对 app/src 目录做 Correctness 和 Security 检查输出 HTML 报告 lint --check Correctness,Security --html lint-report.html app/src--check后面的参数是检查项 ID多个用逗号分隔。Correctness覆盖空指针、资源引用错误这类会影响运行的问题Security覆盖明文流量、不安全的加密算法这类安全短板。--html指定报告输出路径也可以换成--xml生成机器可读的 XML 报告。app/src是源码目录的路径lint 会自动识别AndroidManifest.xml和 java/kotlin 源码。lint 的输出里每个问题会标注严重级别Error和Warning是最常见的两种。比如检测到ObsoleteSdkInt会给出警告检测到UnusedResources会给出提示。在脚本里我一般用退出码判断结果lint 检查到 Error 级别的问题时退出码非零流水线可以直接在那一环拦截发布。这里有个实用技巧--check可以重复传参比如--check Correctness --check Security比逗号写法更清晰多个检查项组合时优先用这种方式。4. 避坑手册JDK 版本、环境变量与模拟器镜像的五个排查记录4.1 sdkmanager 报错找不到 JAVA_HOME现象在 mac 上刚解压完命令行工具运行sdkmanager --list直接提示找不到java或报JAVA_HOME为空。原因命令行工具是 Java 程序需要从JAVA_HOME或系统PATH里定位 JVM。mac 自带的java命令可能是 Apple 的旧版本也可能你只装了 JRE 没装 JDK而工具要求 JDK 17。解决先执行/usr/libexec/java_home -V看机器上有哪些 JDK如果只有 17 就按 2.2 节的方式设置JAVA_HOME。如果没有 17用 Homebrew 安装 Zulu 17 后再配置配置完务必重新打开终端或手动source ~/.zshrc。4.2 输入 sdkmanager 提示 command not found现象环境变量配置写好了当前终端也能echo $PATH看到cmdline-tools/latest/bin但新开一个终端窗口就找不到命令。原因mac 默认 shell 是 zsh读的是~/.zshrc而我在第一次配置时把 export 写进了~/.bash_profile。新开的 zsh 终端根本不会加载 bash 的配置文件。解决把配置统一放到~/.zshrc末尾。如果像我一样已经写错了地方可以直接在.zshrc里加一行source ~/.bash_profile但更干净的做法是删除重复配置只保留一份环境变量定义。从那以后我每次改完环境配置都会新开一个终端验证不直接复用旧会话。4.3 avdmanager create avd 报 Missing platform现象用avdmanager create avd -k system-images;android-34;google_apis;arm64-v8a创建 AVD命令报Error: Missing platform或类似的镜像找不到错误。原因system-images和platforms是两个独立的包只装了platforms;android-34不代表有对应的系统镜像。avdmanager 创建 AVD 时不会自动下载镜像它只会检查本地是否存在。解决先用sdkmanager --list确认system-images;android-34;google_apis;arm64-v8a这个包名完整存在再执行sdkmanager --install单独安装。装完后再跑一次avdmanager list avd确认设备被识别最后用emulator -avd启动验证。4.4 lint 运行报 SDK 平台缺失现象lint 对项目执行检查时输出类似failed to find target android-34或No such file: android.jar的错误。原因lint 解析工程时需要读取编译目标对应的android.jar来建立 API 索引。如果$ANDROID_HOME/platforms/android-34没有安装它就找不到这个文件。很多人以为 lint 只分析源码忽略了它对 SDK 平台包的依赖。解决检查工程的build.gradle里的compileSdk版本然后执行sdkmanager --install platforms;android-版本号安装对应平台。安装完成后再跑 lint一般就能正常运行。如果还报错用lint --version确认命令行工具的 lint 版本比工程要求的 AGP lint 版本新。4.5 macOS 解压后 bin 下的脚本没有执行权限现象解压commandlinetools-mac-11076708-latest.zip后执行sdkmanager提示Permission denied或者 mac 弹出无法打开因为无法验证开发者的对话框。原因zip 包内脚本的 Unix 执行权限在解压时没有被完整保留或者文件被 macOS 的 Gatekeeper 标记了 quarantine 属性。新版 mac 系统对这个属性尤其敏感。解决先给脚本目录补上执行权限chmod x $ANDROID_HOME/cmdline-tools/latest/bin/*。如果仍然提示开发者验证问题对命令行工具根目录执行xattr -dr com.apple.quarantine移除隔离属性。这个操作只影响当前目录下的文件不会改动系统其他位置安全上没有问题。5. 进阶技巧把 lint、r8 和 apkanalyzer 固化成一条 build-check.sh5.1 一个脚本解决日常重复劳动命令行工具单独用都不难难的是把这几个工具串成一条流水线。我现在在 mac 上验证一个新到的 Android 工程会直接跑一个build-check.sh把环境检测、平台检查、APK 分析、lint 检查一次做完。这个脚本的思路是先确认基础环境再验证工具链最后输出报告。#!/bin/bash set -euo pipefail echo [1/4] 检查环境变量 test -n $JAVA_HOME || { echo JAVA_HOME 未设置; exit 1; } test -n $ANDROID_HOME || { echo ANDROID_HOME 未设置; exit 1; } TOOLS_BIN$ANDROID_HOME/cmdline-tools/latest/bin echo [2/4] 检查目标平台 PLATFORMplatforms;android-34 $TOOLS_BIN/sdkmanager --list | grep $PLATFORM || { $TOOLS_BIN/sdkmanager --install $PLATFORM } echo [3/4] 分析 APK 产物 $TOOLS_BIN/apkanalyzer apk summary app-release.apk $TOOLS_BIN/apkanalyzer dex packages app-release.apk dex-packages.txt echo [4/4] 执行 lint 检查 $TOOLS_BIN/lint --check Correctness,Security --html lint-report.html app/src echo build-check 完成报告见 lint-report.htmlset -euo pipefail是脚本的保险丝任何一个命令失败就立即终止不允许脚本带着错误继续跑。第 2/4 步的 grep 是个小技巧--list输出里包含目标平台就跳过安装不包含就自动安装避免每次重复执行无用的下载动作。第 3/4 步的 apkanalyzer 输出重定向到文件方便后续脚本继续读取内容做断言。5.2 用退出码和产物验证工具是否正常脚本跑完不等于工具链正常还要看产物。我先检查lint-report.html的文件大小为空或只有几 KB 说明 lint 大概率报错了再打开 dex-packages.txt 看方法数和类数是否合理。最直接的办法是把 apkanalyzer 的 summary 输出里几个关键字段抽出来对比上一个版本的基线值比如包体大小从 50MB 涨到 80MB这在合并代码之前就该被发现。这种把命令行工具串成脚本的方式比手动逐条执行命令可靠得多。我经历过一次教训某次升级构建工具版本后lint 报告生成根本不提示错误但文件为空我盯着终端看了十分钟才意识到是新版 lint 把输出目录解析成了相对路径从那以后我每次跑完脚本都会强制检查报告文件的字节数确认产物真实存在再继续后续步骤。这套 macOS 命令行工具链的价值就在这里单看每个工具都不复杂组合起来才是一套可以反复使用的机械化流程。希望帮到你。本文还有配套的精品资源点击获取