ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Android命令行工具实战:sdkmanager配置与避坑指南

Android命令行工具实战:sdkmanager配置与避坑指南 简介Android安卓命令行工具commandlinetools-linux-13114758-latest.zip是一份面向Linux开发者的轻量级SDK管理资源。它省去安装完整Android Studio的负担适用于习惯命令行操作、或在自动化构建与持续集成环境中批量管理SDK组件的开发者尤其适合资源受限的服务器或容器场景。压缩包共包含一百零八个文件体积约一百五十七兆核心目录为cmdline-tools内含sdkmanager、avdmanager、apkanalyzer、lint等可执行程序另有九十五个jar库用于支撑编译、APK分析与代码检查功能。已有二百八十四人浏览学习。完成解压与路径配置后开发者可通过sdkmanager按需获取平台、NDK、模拟器等组件灵活定制精简环境也能借助d8、r8、retrace等工具完成DEX编译、代码压缩与混淆堆栈还原。整体结构清晰适合具有一定Linux基础、希望摆脱大型IDE并能快速搭建Android开发链路或自动化流水线的工程师有效提升SDK管理的可控性与可配置性。1. 命令行工具不装 Android Studio 也能把 SDK 玩明白在一台只有 2G 内存的 Linux 服务器上跑 Android 打包任务第一反应是装个 Android Studio装完就后悔了——IDE 本身就要占 1G 多内存再开 Gradle 和模拟器机器直接卡死。Android 命令行工具commandlinetools就是为这种场景准备的它只是 SDK 管理的最小内核核心是一个叫 sdkmanager 的命令负责下载平台、构建工具、NDK 这些组件全程不碰 IDE。这个 zip 解压后配置好环境变量就能跑适合三类人CI/CD 流水线里需要自动化装 SDK 的、在无图形界面的服务器上做构建的、以及单纯不想被 Android Studio 绑架的 Linux 老用户。下文从解压讲起把 sdkmanager 和它几个兄弟工具的实际用法过一遍最后给出我踩过的坑位清单。2. 解压与目录结构cmdline-tools 的嵌套约定与 PATH 配置2.1 zip 里有什么bin 与 lib 的分工解压后第一眼看到的是cmdline-tools这个顶层目录里面是两个子目录bin和lib。搞清楚这两个目录的分工后面所有问题都好理解。bin目录放的是可执行脚本也就是你真正会在命令行里敲的命令。这个包里常见的入口有sdkmanager、avdmanager、apkanalyzer、lint、d8、r8每一个都对应一套独立的命令行工具。它们本质上是 shell 脚本加 Java 启动器通过lib目录下的 jar 包来运行。lib目录就是另一套风景了密密麻麻全是 jar 文件。项目正文里列的那一串——r8.jar、dk8相关的框架、kotlin-compiler-mvn.jar、intellij-core-mvn.jar、bcprov-jdk18on-1.79.jar、proto.jar、tools.lint-checks.jar、kotlin-reflect-2.1.0.jar——全都躺在lib里。简单说sdkmanager是 Java 写的跑起来需要这些依赖其中r8.jar是 R8 混淆器的本体bcprov是 Bouncy Castle 加密库kotlin-compiler-mvn.jar和kotlin-reflect-2.1.0.jar是 Kotlin 编译相关的运行时。日常使用不需要手动碰这些 jar但理解了这一点你就知道为什么这台机器必须先装 JDK——命令行工具的启动过程本质上就是java -jar。2.2 解压到标准位置并配置环境变量解压这个 zip 有一个非常容易翻车的细节zip 内部已经包含了cmdline-tools这层目录而你最终要的目录结构是你的SDK目录/cmdline-tools/latest/bin/sdkmanager。也就是说不能直接解压到 SDK 根目录了事必须在cmdline-tools下面再套一层latest。我一般这样处理mkdir -p ~/android-sdk/cmdline-tools unzip commandlinetools-linux-13114758_latest.zip -d /tmp/cmdtools mv /tmp/cmdtools/cmdline-tools ~/android-sdk/cmdline-tools/latest export ANDROID_HOME~/android-sdk export PATH$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH sdkmanager --version第一段命令先把 zip 解压到临时目录然后把里面的cmdline-tools整体挪到~/android-sdk/cmdline-tools/latest。这个latest名字不是随便起的sdkmanager启动时会在 SDK 根目录下找cmdline-tools/latest这个固定路径来定位自己的依赖如果目录名不对它连自己都找不到。后面两行是环境变量ANDROID_HOME指向 SDK 根目录PATH里加了两个位置一个是cmdline-tools/latest/bin让sdkmanager、avdmanager这些命令全局可用另一个是platform-tools虽然这个目录现在还不存在装完 platform-tools 组件后adb、fastboot会出现在这里提前加进 PATH 省得再改。最后执行sdkmanager --version验证。正常情况下会输出类似13114758这样的版本号。如果报command not found先去检查 PATH 写没写对如果报 Java 相关的错误说明 JDK 环境有问题这个坑在第 5 章细说。3. sdkmanager 组件管理从 list 到 licenses 的完整链路3.1 组件清单与版本通道平台、构建工具和模拟器镜像的区别sdkmanager是整个命令行工具包的核心它的职责是管理 SDK 组件。理解它之前先要理解 Android SDK 的组件体系——它们不是一个大包而是按功能拆成几十个独立组件每个组件有独立的版本号互相之间有依赖关系。组件标识作用典型用途platform-toolsadb、fastboot、e2fsdroid 等调试工具连接设备、刷机、调试platforms;android-34某个 API 级别的 Android 平台编译时指定 targetSdkbuild-tools;34.0.0aapt2、zipalign、dx/d8 等构建工具打包、资源编译、dexsystem-images;android-34;google_apis;x86_64模拟器系统镜像创建 AVD 运行模拟器ndk;27.0.xNDK 原生开发工具链C/C 代码交叉编译cmdline-tools;latest命令行工具自身通过它管理上面所有组件第一次接触的人最容易混淆的是platforms和build-toolsplatforms是编译时要链接的 Android 框架接口build-tools是实际干活儿的编译工具。装一个 Android 项目常见的最小组合是platform-tools加一个platforms;android-XX加一个匹配的build-tools;XX。模拟器镜像只有在需要跑模拟器时才装服务器上纯打包场景可以完全跳过。版本通道用--channel参数控制0是稳定版1是测试版2是 alpha 版3是 canary 版。我一般固定用0CI 环境里追新版本纯属自找麻烦。3.2 安装、接受许可与卸载稳定复现的五个命令sdkmanager的使用就是一个命令走天下先查、再装、最后处理许可证。下面是一套我在自动化脚本里常用的流程# 查看所有可用的组件grep 过滤出你要的版本 sdkmanager --list | grep platforms;android-34 # 首次安装必须先接受所有许可证yes 自动确认 yes | sdkmanager --licenses # 按需安装多个组件写在同一行 sdkmanager platform-tools platforms;android-34 build-tools;34.0.0 # 卸载用 --uninstall sdkmanager --uninstall build-tools;33.0.2 # 查看当前已安装的所有组件 sdkmanager --list_installed第一行的--list会输出两大段installed packages 和 available packages输出很长用grep过滤是常态。第二行的--licenses是装任何组件之前必须先过的关卡Android SDK 的许可证协议需要逐个确认yes |管道可以一次性全部接受接受后的记录会写入$ANDROID_HOME/licenses目录之后重装或者其他用户在同目录下操作都不需要再确认。第三行是安装命令的推荐写法多个组件包名用空格分隔写在同一条命令里sdkmanager会按依赖顺序自动处理比一条条装更快也更不容易出错。最后两行一个是卸载一个是核对已装列表CI 脚本里跑完安装后执行一次--list_installed确认结果是值得养成的习惯。装完组件后$ANDROID_HOME下会出现platforms、build-tools、platform-tools等目录。此时验证安装是否成功直接检查关键二进制是否存在即可ls $ANDROID_HOME/platform-tools/adb ls $ANDROID_HOME/build-tools/34.0.0/aapt2如果这两个文件在说明组件安装成功并且目录结构正常。如果报错说找不到包大概率是包名敲错了——Android 的包名格式是类型;版本这种分号分隔的写法用sdkmanager --list输出里的完整名字不要自己拼接。4. bin 目录工具箱avdmanager、apkanalyzer 与 d8/r8 的实战边界4.1 avdmanager无界面模拟器的创建与配置sdkmanager管安装avdmanager管模拟器。很多人以为命令行环境就用不上模拟器实际上在 CI 里跑 instrumented 测试、或者在没桌面的 Linux 机器上做 UI 自动化都得靠命令行创建 AVD。先安装系统镜像再创建 AVD这是固定的两步sdkmanager system-images;android-34;google_apis;x86_64 avdmanager create avd \ -n ci_test \ -k system-images;android-34;google_apis;x86_64 \ -d pixel_5 \ --force第一行安装模拟器需要的系统镜像system-images后面的三段分别是 API 级别、镜像类型google_apis带 Google 服务default不带、CPU 架构。服务器上如果没有硬件虚拟化支持选x86_64镜像可能在启动时翻车备选方案是arm64-v8a但速度会慢不少。第二行是创建 AVD 的命令-n是 AVD 名字-k指定系统镜像包名必须和第一步安装的镜像完全一致-d指定设备配置用avdmanager list device可以查看所有可选设备--force表示同名 AVD 直接覆盖。创建完成后AVD 的配置会写入~/.android/avd目录。用命令行启动模拟器需要emulator命令而这个命令来自emulator组件sdkmanager emulator $ANDROID_HOME/emulator/emulator -avd ci_test -no-window -no-audio -no-boot-anim -no-window是无头模式服务器上必须加这个参数否则模拟器会尝试打开 X 窗口直接崩溃。启动后等待系统 boot 完成才能继续测试判断 boot 完成的标准做法是轮询sys.boot_completed这个系统属性但这个脚本细节放到最后一章讲。4.2 apkanalyzer不装 IDE 也能拆解 APKapkanalyzer是一个经常被忽略但非常好用的工具它的定位是替代 Android Studio 里的 Build Analyze APK 功能。在命令行环境里分析一个 APK它的效率比手动解压看二进制高得多。# 查看 APK 基本信息包名、版本号、最低 SDK apkanalyzer apk summary app-release.apk # 查看 APK 的清单文件内容 apkanalyzer manifest print app-release.apk # 列出 APK 中所有的 dex 文件并统计方法数 apkanalyzer dex packages app-release.apk第一条命令的输出包含package_name、version_code、version_name、min_sdk、target_sdk这些字段CI 里做版本校验直接解析这个输出就行。第二条把AndroidManifest.xml的二进制格式转换成人可读的 XML 打出来适合检查权限声明、Activity 组件、签名信息。第三条统计方法数多 dex 的 APK 超过 65536 个方法会爆在检查分包配置时这一条很有用。这个工具对脚本自动化特别友好输出是稳定的纯文本不涉及 GUI。我在做 APK 的合规检查脚本时就是靠它批量扫描权限清单比逐个解压看 XML 快一个数量级。4.3 d8/r8 与 lib 目录从 class 到 dex 的最后一步项目正文里那一串 jar 文件这里的r8.jar值得单独说一下。R8 是官方推荐的混淆和压缩工具它把 ProGuard 的混淆规则、资源压缩、dex 转换整合成一步操作。d8则是把 Java class 文件编译成 Android 可执行的 dex 文件它是老工具dx的替代品。# 用 d8 把 class/jar 转成 dex d8 --release \ --lib $ANDROID_HOME/platforms/android-34/android.jar \ --output build/dex/ \ build/classes/classes.jar # 用 r8 做混淆 裁剪 转 dex r8 --release \ --lib $ANDROID_HOME/platforms/android-34/android.jar \ --output build/dex/ \ --pg-conf proguard-rules.pro \ build/classes/classes.jar--release表示生产模式会做优化和混淆d8 跳过混淆只做优化--lib指定 Android 平台的 jar这是编译时解析 Android API 依赖用的路径里的android-34需要和已安装的平台版本对应--pg-conf是 ProGuard 规则文件R8 完全兼容 ProGuard 的规则语法。输出目录里生成的classes.dex就是 APK 里核心的可执行文件。至于bcprov-jdk18on-1.79.jar、proto.jar、kotlin-reflect-2.1.0.jar这些它们都是这些工具运行时的依赖库比如bcprov是 Bouncy Castle 加密算法实现proto.jar是 Protocol Buffers 序列化支持。正常使用完全不需要手动加载它们bin目录下的启动脚本会处理。了解它们的作用是为了排错——如果某个工具报ClassNotFoundException或者 NoClassDefFoundError那就是lib目录不完整或者被清理掉了。5. 命令行工具避坑指南目录层级、JDK 版本与许可证的五个坑5.1 sdkmanager 报错 not foundcmdline-tools 的 latest 嵌套陷阱现象解压后直接执行sdkmanager --version终端提示找不到命令或者报类似SDK manager not found的错误。原因这个 zip 解压出来的顶层目录就是cmdline-tools如果把它直接放在 SDK 根目录下比如~/android-sdk/cmdline-tools/bin/sdkmanager没有中间的latest那层结构sdkmanager脚本会尝试基于自身路径计算 SDK 根目录找不到cmdline-tools/latest这个约定路径就罢工了。解决按第 2 章的方式把解压出来的cmdline-tools移到~/android-sdk/cmdline-tools/latest。一个快速判断目录结构是否正确的命令find ~/android-sdk -name sdkmanager -type f正常输出应该是~/android-sdk/cmdline-tools/latest/bin/sdkmanager如果路径里没有latest这一段就是结构不对。5.2 Unsupported class file major versionJDK 版本太老现象执行sdkmanager或apkanalyzer时直接抛java.lang.UnsupportedClassFileVersionError或者UnsupportedClassVersionError后面跟着一个 major version 的数字。原因命令行工具是用当前版本的 JDK 编译的新版 cmdline-tools 要求 JDK 17 起步机器上装的是 JDK 8 或 JDK 11 就跑不起来。major version 65 对应 JDK 2164 对应 JDK 2061 对应 JDK 17看到 65 还报错说明 JVM 版本更老。解决安装 JDK 17并把JAVA_HOME明确指过去。Ubuntu/Debian 上常见做法是sudo apt install openjdk-17-jdk export JAVA_HOME/usr/lib/jvm/java-17-openjdk-amd64 export PATH$JAVA_HOME/bin:$PATH java -version重点确认java -version显示的是 17 或更高版本。如果机器上有多个 JDK光改 PATH 不够JAVA_HOME也必须同步改很多 Java 启动脚本优先读JAVA_HOME。5.3 Failed to install packages许可证没接受现象执行sdkmanager platforms;android-34报错提示Failed to install packages核心信息是licenses相关或者直接问你是不是接受某个 license。原因新装的 SDK 根目录下没有licenses目录也没有任何已接受的许可证记录。sdkmanager在安装任何组件前都会检查许可证状态没通过就直接拒绝安装。解决先执行一次yes | sdkmanager --licenses把当前 SDK 根目录下所有许可证一次性接受。接受后$ANDROID_HOME/licenses目录下会生成android-sdk-license文件。如果重装了 SDK 目录许可证文件会丢失需要重新接受CI 环境里每次从零构建时这条yes |命令必须放在安装命令之前。5.4 adb command not foundPATH 里没有 platform-tools现象sdkmanager正常组件也装了但执行adb devices提示command not found。原因adb不在cmdline-tools里它属于platform-tools组件安装在$ANDROID_HOME/platform-tools目录。PATH 里只加了cmdline-tools/latest/bin没加platform-tools自然找不到。解决把$ANDROID_HOME/platform-tools加进 PATH。同时建议确认环境变量是 export 出去的子 shell 和脚本里都能继承export PATH$ANDROID_HOME/platform-tools:$PATH adb --version如果加了 PATH 还是找不到检查ANDROID_HOME本身是否为绝对路径不要用~这种 shell 才会展开的符号——在cron或 CI 的非交互 shell 里~经常不展开导致路径失效。5.5 下载中断后重来sdkmanager 没有断点续传现象下载某个组件到 80% 时网络断了sdkmanager报错退出。重新执行同样的命令它不会接着下载而是从头再来然后又在差不多的地方断掉形成死循环。原因sdkmanager的下载机制没有断点续传功能每次中断后临时文件被清理重试只能重新下载整个组件包。对于system-images这种动辄上 GB 的组件这个问题特别折磨人。解决没有完美的命令内方案我的惯用做法是把下载和安装分成两段。在 CI 脚本里写一个重试循环单次下载失败就等几秒重来并限制重试次数防止死循环for attempt in 1 2 3; do sdkmanager system-images;android-34;google_apis;x86_64 break echo Download failed, retry $attempt/3... sleep 10 done另一个办法是提前确认依赖完整再执行安装sdkmanager对已有组件会跳过下载所以重试不会浪费已经装在磁盘上的东西。如果网络环境实在差优先装体积小的核心组件把system-images放到网络好的时间段单独装。6. 无头服务器一键脚本把整套 Android SDK 装进一个 bash 脚本最后给一个我在 CI 和新机器上反复用的完整脚本它把一个最小可用的 Android 构建环境塞进一个 bash 脚本里适合 Ubuntu/Debian 系的 Linux 服务器。核心思路是三段式装 JDK、解压命令行工具、装构建组件。#!/bin/bash set -euo pipefail SDK_ROOT${ANDROID_HOME:-$HOME/android-sdk} CMDTOOLS_VERSION13114758 # 1. 安装 JDK 17 if ! command -v java || [[ $(java -version 21 | head -1) ! *17* ]]; then sudo apt-get update sudo apt-get install -y openjdk-17-jdk unzip fi export JAVA_HOME/usr/lib/jvm/java-17-openjdk-amd64 # 2. 检查并安装 cmdline-tools if [ ! -x $SDK_ROOT/cmdline-tools/latest/bin/sdkmanager ]; then mkdir -p $SDK_ROOT/cmdline-tools wget -q https://dl.google.com/android/repository/commandlinetools-linux-${CMDTOOLS_VERSION}_latest.zip -O /tmp/cmdtools.zip unzip -q /tmp/cmdtools.zip -d /tmp/cmdtools mv /tmp/cmdtools/cmdline-tools $SDK_ROOT/cmdline-tools/latest fi # 3. 安装构建组件 yes | $SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --licenses /dev/null $SDK_ROOT/cmdline-tools/latest/bin/sdkmanager \ platform-tools \ platforms;android-34 \ build-tools;34.0.0 echo Android SDK is ready at $SDK_ROOT这个脚本有四个关键设计。第一set -euo pipefail是 bash 脚本的保险丝任何一条命令失败立即退出避免在坏环境里继续跑出一堆莫名单错误。第二JDK 版本检查用java -version的输出字符串判断只认 17不满足就装这样脚本可以重复执行。第三cmdline-tools的安装做了存在性判断已经装过就直接跳过整个脚本天然幂等。第四sdkmanager 用绝对路径调用不依赖 PATH 是否配置完整这在刚拉下来的新机器上特别有用——脚本里我顺手把 PATH 省略了让读者看到它并不是必须的。顺便说一下这是我对这个工具整体印象还不错的一个原因整个 Android 命令行生态从下载到构建没有一个环节要求你在终端之外做任何手工操作。Android Studio 把这一切包装成了图形界面而 commandlinetools 把这些都还原成了原始的、可脚本化的命令。有一次我在新机器上配环境照着旧笔记一条条敲命令结果sdkmanager一直报错折腾了半小时才发现是上次手滑把目录结构搞错了少了一层latest。从那以后我每次在新机器上装 Android 环境都直接跑一遍脚本从解压到sdkmanager --version输出版本号全程不手工改路径再也没被这种低级错误卡过。希望这个脚本和前面这些坑位记录能帮你少走几步弯路。本文还有配套的精品资源点击获取
返回列表