Unity3D打包APK:SDK Tools 26.1.1配置排错
简介:Android SDK Tools 26.1.1 是面向 Unity 2018/2019 开发者的 Android 打包环境工具包,主要解决旧版 Unity 导出 APK 时 SDK 组件缺失、版本不兼容、配置步骤繁琐等问题,适合需要稳定复现打包流程的初中级移动开发人员。压缩包共 1828 个文件、约 146.29MB,以 jar 库文件、png 与 gif 界面及文档插图、properties 和 xml 配置、html 与 css 帮助文档为主,另含 exe 可执行程序、bat 批处理脚本与 java 源码,较完整地保留了 SDK Manager、Adb、Zipalign 等核心组件的原始目录层级。目前已有 2833 人学习下载。解压后可挂接到 Unity 的 SDK 路径,便于对照 SDK Manager 补齐平台与构建工具、借 Adb 完成真机安装与调试、用 Zipalign 优化 APK 体积和启动速度,也为排查版本兼容问题提供了可核对的组件清单。
1. 版本先对再动手:Unity3D 打包 apk 为什么卡在 26.1.1 这个 rar 上
一位同事把 Unity3D 打包 apk 的活儿丢过来,Unity 装好了、工程能跑,唯独 Build 按钮一按就红。他翻遍tools目录找SDK Manager.exe,找不到,怀疑 rar 包残缺。其实 25.3.0 之后图形版 SDK Manager 就被移除了,26.1.1 只剩tools\bin\sdkmanager.bat这一条命令行入口,网上大量截图教程对它完全失效。这份 SDK Tools 26.1.1 体量不大,价值在于“底座干净”:platform-tools、build-tools、platforms 三块料按需补,路径自己定,不和 Unity 自带的 OpenJDK 冲突。适合还在维护 2017/2018 老工程、要给渠道单独出包、或 Unity 装在离线机器上的人。装岔了只有两种下场:External Tools 里 SDK 路径标红,或者 Gradle 跑到一半告诉你 build-tools 不存在。下面按我装过十几台机器的顺序走一遍。
2. 解压与环境前置:路径、JDK 8 和两个必须设的变量
这套东西失败率最高的地方不在命令,而在动手之前的三个决定:解压到哪、用哪个 JDK、环境变量怎么设。这三件事定错了,后面sdkmanager会以各种看不懂的报错回敬你,而且报错信息指向的位置往往和真实原因差着十万八千里。
2.1 解压位置:一根路径只放一个 SDK 根
rar 解出来是一个tools文件夹。这个tools的上一级才是 SDK 根目录,sdkmanager后续下载的platform-tools、build-tools、platforms、licenses全都会生成在根目录下,和tools平级。所以解压时别直接解到D:\Android\sdk\tools\tools,那是最经典的一层套娃。
我的习惯是固定成D:\Android\sdk,tools就躺在里面:
D:\Android\sdk\ ├── tools\ # 26.1.1 解压出来的本体 │ ├── bin\sdkmanager.bat │ ├── bin\avdmanager.bat │ └── lib\ ├── platform-tools\ # 后面用 sdkmanager 装出来 ├── build-tools\29.0.3\ ├── platforms\android-29\ └── licenses\路径里有三样东西是雷:空格、中文、以及很长的目录层级。sdkmanager.bat内部有大量未加引号的路径拼接,C:\Users\张三\我的文档\新建文件夹\sdk这种路径大概率在下载到一半时报一个和路径毫不相关的错误。老工程常见做法是直接把 SDK 放到盘符根下的英文短目录,路径总长控制在 60 字符以内,能省掉后面一大半玄学问题。
另外,解压工具别用那种会自动“优化”长路径的老版本压缩软件,解压完数一下tools\lib下的 jar 数量,太少就是被截断了。
2.2 JDK 选型:26.1.1 只认 Java 8
26.1.1 的sdkmanager和avdmanager是基于 Java 8 编译的批处理封装,喂给它 JDK 11 或 17,最典型的报错是:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema原因不复杂:JAXB 这组包在 Java 11 里从 JDK 标准库中移除了,而sdkmanager解析仓库 XML 恰恰依赖它。所以要么装 JDK 8,要么别用这套命令行工具。JDK 8 我一般选jdk1.8.0_202这类后期小版本,装在默认目录,路径里带空格也没关系——JAVA_HOME由系统处理,不进sdkmanager的路径拼接逻辑。
Unity 这边有个分水岭:2019.2 之后编辑器自带 OpenJDK,路径在Editor\Data\PlaybackEngines\AndroidPlayer\OpenJDK,External Tools 里勾上 “JDK Installed with Unity” 就完事,不需要额外装。2017/2018 的老 Unity 没有自带 JDK,必须自己装一个 8,并在 External Tools 里手动指过去。两套 JDK 同时存在于一台机器上完全没问题,只要 Unity 里指的和JAVA_HOME指的不是互相打架的版本就行。
2.3 环境变量:ANDROID_HOME 和 ANDROID_SDK_ROOT 都设上
# 管理员身份运行 PowerShell;路径按自己实际解压位置改 [Environment]::SetEnvironmentVariable("ANDROID_HOME", "D:\Android\sdk", "Machine") [Environment]::SetEnvironmentVariable("ANDROID_SDK_ROOT", "D:\Android\sdk", "Machine") [Environment]::SetEnvironmentVariable("JAVA_HOME", "C:\Program Files\Java\jdk1.8.0_202", "Machine") # PATH 里追加 platform-tools 和 JDK 的 bin,注意别把 tools\bin 也加进去 $p = [Environment]::GetEnvironmentVariable("Path", "Machine") $p += ";D:\Android\sdk\platform-tools;C:\Program Files\Java\jdk1.8.0_202\bin" [Environment]::SetEnvironmentVariable("Path", $p, "Machine")两个 SDK 变量都设,是为了兼容两代工具:老的 Gradle 插件和一部分 Unity 版本读ANDROID_HOME,新的命令行工具读ANDROID_SDK_ROOT,只设一个就会出现“命令行能找到 SDK、Unity 说找不到”的诡异局面。
PATH里只加platform-tools,不要加tools\bin。一旦加了,系统里那个sdkmanager.bat会全局可用,但它启动时会去抢java命令的解析顺序,机器上同时装了多个 JDK 时很容易调到错的版本上。要跑sdkmanager就老老实实写全路径。
设完开一个新窗口验证,别在旧窗口里试:
java -version # 期望输出 java version "1.8.0_202" echo %ANDROID_HOME% # 期望输出 D:\Android\sdkjava -version输出不是 1.8 开头,后面所有步骤都不用往下走,先解决 JDK 顺序问题:多半是PATH里C:\Program Files\Common Files\Oracle\Java\javapath排在前面,把它挪到 JDK 的 bin 之后。
3. 用 sdkmanager 补齐三件套:platform-tools、build-tools、platforms
26.1.1 解压出来只有tools一个目录,它本身不含打包能力。Unity 出 apk 真正依赖的是三样东西:platform-tools(adb、fastboot)、build-tools(aapt、aapt2、zipalign、apksigner)、platforms(对应 API 级别的android.jar)。这三样要自己用sdkmanager拉下来。
3.1 先确认 sdkmanager 自己能起来
别看这一步简单,我第一次装就卡在这儿:批处理闪一下就没了,什么都不打印,怀疑是包坏了。实际是 JDK 没配对。
# 全路径调用,避免 PATH 里有同名命令干扰 D:\Android\sdk\tools\bin\sdkmanager.bat --version # 版本能打出来,再看它能不能读到远程仓库清单 D:\Android\sdk\tools\bin\sdkmanager.bat --list--version只验证本地 Java 环境和批处理封装是否正常,不联网;--list会去拉仓库索引,能列出Available Packages和Installed packages两大段就说明网络和路径都没问题。如果--list卡住不动或者报Warning: Failed to download ...,先换一个时间点重试,sdkmanager不支持断点续传,中断了直接重跑整条命令即可。
有个细节值得记一笔:--sdk_root参数在 26.x 里是显式指定根目录的,不写的话工具会以tools的上一级作为默认根。因为我们的目录摆法是对的,不写也能跑;但如果你机器上有多个 SDK 副本,每次都显式带上--sdk_root,否则很容易出现“装了但 Unity 那边看不到”的情况,因为装到另一个根里去了。
3.2 版本对照:Unity 版本决定 build-tools 装哪个
这一步最容易翻车的地方是版本乱配。Unity 每个大版本对 build-tools 和 compileSdk 都有隐含预期,装高了装低了都可能报Failed to find Build Tools revision xx.x.x。下面是我在几台机器上实际跑通过的组合,不是官方推荐表,是踩出来的:
| Unity 版本 | targetsdk / compileSdk | build-tools | JDK |
|---|---|---|---|
| 2017.4 LTS | android-26 | 26.0.1 | JDK 8 外装 |
| 2018.4 LTS | android-28 | 28.0.3 | JDK 8 外装 |
| 2019.4 LTS | android-29 / 30 | 30.0.3 | 自带 OpenJDK |
| 2020.3 LTS | android-30 | 30.0.3 | 自带 OpenJDK |
| 2021.3 LTS | android-32 | 32.0.0 | 自带 OpenJDK |
原则就一条:build-tools的主版本号尽量跟platforms的 API 级别一致,实在不行高一点点,别低。装低了aapt2会缺参数,Unity 那侧表现为 Gradle 构建时莫名其妙的资源链接失败,日志里根本看不出是版本问题。
3.3 一条命令装齐,再单独处理许可证
# 以 Unity 2019.4 为例;--sdk_root 显式指定,避免装错根目录 D:\Android\sdk\tools\bin\sdkmanager.bat --sdk_root=D:\Android\sdk ^ "platform-tools" ^ "build-tools;30.0.3" ^ "platforms;android-30" # 装完接受许可证,Unity 打包前必须有 licenses 目录 D:\Android\sdk\tools\bin\sdkmanager.bat --sdk_root=D:\Android\sdk --licenses命令里的包名是分号分隔的固定格式,build-tools;30.0.3不能写成build-tools-30.0.3,也不能只写build-tools(不写版本号会装最新版,往往和你的 Unity 对不上)。platform-tools和platforms;android-30没有歧义,直接写。
--licenses会连续抛出好几屏协议,一路输y回车到底。这一步跳过的人特别多,症状是 Unity 打包时在 Gradle 阶段报:
You have not accepted the license agreements of the following SDK components跑完--licenses之后,D:\Android\sdk\licenses\下会多出几个无扩展名的文本文件,那才是许可证真正落地的标志。如果只跑了--licenses但目录里还是空的,说明当前用户对该目录没有写权限,把 SDK 目录挪到非系统盘再试。
装完再跑一次--list_installed,三件套都在列表里,这一章就算过了。
4. 接进 Unity:External Tools 的三条路径与 Gradle 参数
SDK 装好了不等于 Unity 认。Unity 侧要填三个路径,改两个设置,其中任何一个填错都表现为同一句Unable to locate Android SDK。这一章把每个输入框该填什么、为什么填这个,挨个说清楚。
4.1 External Tools:三条路径各指到哪一层
打开Edit > Preferences > External Tools(macOS 是 Unity > Preferences),Android 区块有四个位置:SDK、JDK、NDK、Gradle。
SDK 填的是根目录,也就是D:\Android\sdk,不是D:\Android\sdk\tools,也不是D:\Android\sdk\platform-tools。Unity 校验这个路径的方式是看目录下有没有tools子目录,指到tools本身它就认为这是无效路径。
JDK 分两种情况:勾了 “JDK Installed with Unity” 就不读路径,用编辑器自带的;没勾就填 JDK 根目录C:\Program Files\Java\jdk1.8.0_202,不是...\bin,也不是...\jre。填到jre上在部分版本里能过校验,但真正打包时会因为缺javac失败,属于拖到很后面才暴露的坑。
NDK 只有用 IL2CPP 出包时才需要,Mono 后端可以留空。填法是 NDK 根目录——里面有ndk-build.cmd那一层。Unity 2019 之后一般用自带的,路径形如Editor\Data\PlaybackEngines\AndroidPlayer\NDK。手工装的 NDK 版本和 Unity 期望的对不上时,IL2CPP 编译会报一堆undefined reference,那种错误看起来像代码问题,其实是 NDK 版本问题。
Gradle 一栏,2019 之后建议勾 “Gradle Installed with Unity”,让编辑器用自带的那份,省掉版本匹配的麻烦。只有需要定制构建流程、或者公司内部有规定版本时才手动指。
4.2 Publishing Settings:Build System 与两个必须改的参数
Player Settings > Publishing Settings里,Build System 选Gradle,不要选 Internal。Internal 是早期给调试用的,现在很多第三方 SDK 的 aar 根本不吃这一套,出包后在真机上各种初始化失败。
勾上 Custom Main Gradle Template 之后,工程里会生成Assets/Plugins/Android/mainTemplate.gradle,把编译版本钉死,不让它去猜:
// Assets/Plugins/Android/mainTemplate.gradle 片段 android { compileSdkVersion 30 // 必须和本地 platforms\android-30 对上 buildToolsVersion "30.0.3" // 必须和 build-tools\30.0.3 对上 defaultConfig { minSdkVersion 22 // 老机型兼容,按渠道要求调 targetSdkVersion 30 // 上架渠道一般要求跟 compileSdk 一致 } }compileSdkVersion和buildToolsVersion这两个值一旦和本地 SDK 目录里的实际版本不一致,Gradle 会尝试自己去下载对应版本,离线机器上就是直接失败。所以我的习惯是:本地装什么版本,模板里就写什么版本,一个字都不差。minSdkVersion决定能装到多老的机器上,targetSdkVersion决定渠道的兼容行为,这两个值改动前先跟渠道要求对一遍,别凭感觉写。
同一目录下还有一个gradleTemplate.properties,出包内存不够时加上这一行:
# 资源多的工程容易 OOM,默认 1G 常常不够 org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8-Dfile.encoding=UTF-8这半句在 Windows 上很关键。工程里有中文资源名时,缺了它 Gradle 会用系统默认编码去读,出包后资源名乱码或者直接找不到,日志里报的是resource not found,查半天查不到编码上。
4.3 版本一致性自查:改完别急着 Build
改完上面这些,先做一次静态自查,比直接 Build 快得多:compileSdkVersion、targetSdkVersion与platforms目录名对得上;buildToolsVersion与build-tools子目录名对得上;External Tools 里 SDK 根目录下有platform-tools、build-tools、platforms三个文件夹;licenses目录非空。四条全过,出包成功率会高很多。这四条我在每台新机器上都会过一遍,两分钟的事,能省掉半小时看日志。
5. 避坑与排查:五个真实翻车点,从解压一路到出包
下面五条是我印象最深的,按“现象、原因、解决”记,遇到同款直接对号入座。
5.1 装 SDK 阶段的三条
第一条:找不到 SDK Manager.exe,以为包坏了。现象:解压后在tools目录里反复找图形界面,只看到一堆 bat 和 jar。原因:25.3.0 起图形版 SDK Manager 已被移除,26.1.1 只提供命令行工具,网上带截图的老教程对应的是 25.2.5 及更早版本。解决:别找图形界面了,直接用tools\bin\sdkmanager.bat,把--list和--install当成新的操作习惯;确实需要图形界面的话,只能另找 25.2.5 的包,但那个版本装不了新 API。
第二条:sdkmanager 一跑就抛 NoClassDefFoundError。现象:命令行闪退,或者输出javax/xml/bind/annotation/XmlSchema找不到。原因:当前java是 JDK 11 或更高,JAXB 已从标准库移除。解决:装 JDK 8,把JAVA_HOME指过去,并检查PATH里javapath那条是否排在前面;改完必须开新窗口。
第三条:下载到一半失败,或者装完目录是空的。现象:sdkmanager输出一堆Warning: Failed to ...,build-tools目录建出来了但里面没东西。原因:多半是路径含中文或空格,导致解压和写入时的路径拼接断裂;也可能是下载中断,这个工具不支持断点续传。解决:把整个 SDK 根目录挪到D:\Android\sdk这种纯英文短路径,删掉装了一半的目录重跑;重跑前先确认磁盘剩余空间,build-tools加platforms通常要占掉 1G 以上。另外留意杀毒软件的隔离区,aapt2.exe被误杀的案例不少,表现是编译时报aapt2 not found,去隔离区恢复并加白名单即可。
5.2 打包阶段的两条
第四条:Unity 报 Unable to locate Android SDK。现象:External Tools 里路径明明填了,Build 时还是提示找不到 SDK。原因:路径多套了一层或少了层——最常见是指到tools或者platform-tools,而不是根目录;其次是根目录下缺platforms文件夹,Unity 的校验逻辑会因此判定无效。解决:SDK 一栏填D:\Android\sdk,确认下面三个子目录齐全;改完关掉 Unity 重开,这个路径有缓存,不重启不生效。
第五条:Gradle build failed,日志里是 Unsupported class file major version 55。现象:编译到一半失败,日志关键字是Unsupported class file major version,后面跟个数字。原因:Gradle 版本和 JDK 版本不匹配,55 对应 Java 11,而 Unity 2019 自带的 Gradle 5.x 只认到 Java 8。解决:把 External Tools 里的 JDK 换回 8,或者勾上 “JDK Installed with Unity” 用自带的那份;如果工程里自定义了 Gradle 版本,注意 Gradle 6.x 才支持 Java 11,两边必须配套。
6. 装完怎么验证:四条命令确认这套 SDK 真能出包
装完不等于能用。我的验证分两层:先用命令行确认 SDK 自身完整,再用 Unity 出一版真机包,两层都过才算收工。
第一层,四条命令,一条都不能省:
# 1. 已安装组件清单,三件套必须同时出现 D:\Android\sdk\tools\bin\sdkmanager.bat --list_installed # 2. adb 版本和设备识别,插一台开了调试的手机看有没有序列号 adb version adb devices # 3. 出包之后回查 apk 的包名、版本号和最低 API D:\Android\sdk\build-tools\30.0.3\aapt dump badging app-release.apk | findstr "package" # 4. 校验签名,确认用的是自己的 keystore 而不是调试签名 D:\Android\sdk\build-tools\30.0.3\apksigner verify --print-certs app-release.apk| 检查项 | 期望结果 | 不对时先看哪里 |
|---|---|---|
--list_installed | 列出 platform-tools、build-tools、platforms 三项 | 是否漏了--sdk_root,装到别的根目录去了 |
adb devices | 出现设备序列号且状态是 device | platform-tools 版本太老,或手机没授权调试 |
aapt dump badging | 打印 package name、versionCode、sdkVersion | build-tools 版本和工程里写的对不上 |
apksigner verify | 输出签名者信息,无 WARNING | 用了默认调试 keystore,或签名配置未生效 |
aapt那条我特意加了findstr过滤,因为完整输出有几十行,第一眼只需要确认包名和版本号跟工程里设的一致。这一步的价值在于:Unity 编辑器里显示的应用名和最终 apk 里的包名,完全是两回事,中途改过 Bundle Identifier 的话很容易出现两者不一致,装到手机上覆盖不掉旧版本。
第二层,Unity 侧走一遍真机:Build 出 apk,adb install -r app-release.apk装上,打开看首屏能不能起来。只验证安装成功不够,有些资源加载问题要进到主场景才暴露。第一次启动慢是正常的,Gradle 要解压和 dex 优化,别急着判定失败。
我踩过最冤的一次是签名校验过了、安装也成功,但渠道那边退回来说版本号没变——查下来是versionCode写在自定义 Gradle 模板里被覆盖了,aapt dump badging一跑就能看见,当时偏偏跳过了这一步。从那以后我每次出包前都强制走一遍这四条命令,两分钟,比事后翻构建日志、被渠道打回重来划算太多。资源就是标题里那个 rar,解压、设变量、补三件套、填路径,照着顺序来一遍基本就通了。希望帮到你。
本文还有配套的精品资源,点击获取