UniApp 本地打包通关记:Android 是地狱难度,iOS 是隐藏 BOSS
在 HBuilder 里点"运行"的时候,我以为自己已经赢了。直到有人跟我说:"打包成 APK 和 IPA 吧。"那一刻,我才知道什么叫------前面都是新手教程。
序章:一个"点一下就行"的错觉
故事的主角叫小猿。
小猿用 UniApp 写了一个 App,在 HBuilder 里跑得飞起,热更新、真机调试、云打包,样样顺畅。他一度以为:"做 App 也不过如此嘛。"
然后有一天,需求来了:"用本地打包出一个 APK 和 IPA,我要装到测试机上。"
小猿的第一反应是:"云打包不香吗?为什么要本地打包?"
答案很简单:云打包有次数限制、有排队、有平台绑定,而本地打包------自由、可控、无限次。
但自由的代价,是你要亲自面对 Gradle 和 Xcode 这两头怪兽。
于是,小猿点开了那个传说中的目录:phone-config。一场冒险,正式开始。
第一章:phone-config------那个像迷宫一样的目录
打开 phone-config 的那一刻,小猿愣住了。
text
arduino
phone-config/
├── android/ ← 安卓战场
│ ├── exh/ ← 模块名,随缘起的
│ ├── build.gradle
│ └── gradle.properties
└── ios/ ← iOS 战场
├── HBuilder-Hello/
├── SDK/
│ ├── Bundles/
│ ├── Libs/
│ └── inc/
└── Feature-iOS.xls
小猿的内心独白: "这不是打包 App,这是打包一整个 SDK 吧?"
尤其是 iOS 那边,Libs 目录里躺着 100 多个 framework 和 30 多个 .a 静态库,小猿数到第 20 个就放弃了。
第二章:Android 篇------Gradle の 试炼场
第一关:导入项目,等 Gradle 下载
打开 Android Studio,Open → 选择 phone-config/android/。
注意:千万别选 exh/ 子目录,否则你会收获一个"这个项目没有 Gradle 配置"的红色报错。
然后就是经典的 Gradle 下载环节。
小猿泡了杯咖啡,回来一看------还在转圈。
他泡了第二杯,回来一看------还在转圈。
他去上了个厕所,回来一看------还在转圈。
小猿的领悟:Gradle 下载慢,不是网速问题,是人生问题。
解决方案:在 build.gradle 里把 Maven 仓库换成阿里云镜像。
groovy
rust
repositories {
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/google' }
}
换完镜像,Gradle 从"下载一晚上"变成"下载五分钟"。
第二关:读懂 build.gradle
打开 exh/build.gradle,小猿看到了这段:
groovy
arduino
android {
compileSdkVersion 32
namespace 'com.exh.test'
defaultConfig {
applicationId "com.exh.test"
minSdkVersion 21
targetSdkVersion 32
versionCode 110
versionName "1.0.0"
}
}
小猿的解读:
- compileSdkVersion 32:用最新的 SDK 编译,时髦。
- applicationId:应用的"身份证号",一旦上架,改了就得重新上架。
- minSdkVersion 21:Android 5.0 以上都能装。
- versionCode 110:第 110 次迭代,迭代狂魔。
第三关:签名文件------App 的"户口本"
groovy
java
signingConfigs {
config {
keyAlias 'test'
keyPassword 'test'
storeFile file('test.jks')
storePassword 'test.123456'
}
}
test.jks 是签名文件,相当于 App 的户口本。
丢了它,Google Play 上架就得哭。
keyPassword 和 storePassword 是明文? 小猿看了一眼,默默决定在真实项目里用环境变量。
第四关:Manifest------权限比购物清单还长
打开 AndroidManifest.xml:
| 权限 | 用途 |
|---|---|
| CAMERA | 扫码、拍照 |
| ACCESS_FINE_LOCATION | 定位附近展会 |
| READ_EXTERNAL_STORAGE | 缓存图片 |
| CALL_PHONE | 一键联系客服 |
| INTERNET | 没它 App 直接变砖 |
四大金刚 Activity:
- MainActivity:入口,展示启动页。
- PandoraEntryActivity:DCloud 核心容器,跑 UniApp 页面。
- WXPayEntryActivity:微信支付回调。
- WXEntryActivity:微信登录回调。
小猿的发现: UniApp 的 Android 入口极其简单------MainActivity extends PandoraEntry,然后就交给 DCloud 引擎了。
就像你请了个管家,他帮你搞定了所有原生的事。
第五关:打包
bash
bash
cd phone-config/android
./gradlew assembleRelease
等了三分钟,APK 生成了。
text
arduino
hzy/release/test-release.apk
小猿激动地把 APK 装到手机上------闪退。
打开 Logcat,发现是依赖冲突。90% 的 Android 闪退,都是依赖冲突。
踩坑记录:
| 坑 | 解法 |
|---|---|
| Gradle 下载慢 | 阿里云 Maven 镜像 |
| lint fatal errors | lintOptions { abortOnError false } |
| 签名不对 | 检查 .jks 路径 |
| 安装闪退 | 看 Logcat,查依赖冲突 |
第三章:iOS 篇------Xcode の 史诗级 BOSS 战
第一关:打开 Xcode
小猿打开 phone-config/ios/HBuilder-Hello/HBuilder-Hello.xcodeproj。
Xcode 加载了 10 秒,然后弹出了几百个文件。
小猿的内心: "这不是 Hello,这是 Hell。"
第二关:control.xml------那个决定 AppID 的文件
xml
xml
<HBuilder debug="true" version="1.9.9.81653">
<apps>
<app appid="__UNI__1F19223" appver="1.0.1"/>
</apps>
</HBuilder>
appid 必须和 HBuilder 项目里的 AppID 一致。
不一致?白搭。
第三关:Feature-iOS.xls------用 Excel 当配置文件?
小猿打开 Feature-iOS.xls,看到了一堆功能模块:
| 功能 | 模块名 | 状态 |
|---|---|---|
| 微信登录 | libWXOauth.a | ✅ |
| 微信支付 | libWeChatSDK_pay.a | ✅ |
| 支付宝支付 | libalixpayment.a | ✅ |
| 高德地图 | libAMapImp.a | ✅ |
| 定位 | liblibGeolocation.a | ✅ |
| 推送 | libUniPush.a | ✅ |
小猿的内心: "DCloud 用 Excel 当配置文件?这波操作,不愧是国产框架。"
第四关:打包 IPA
模拟器调试: Cmd + R,等编译,看效果。
真机调试: 连手机,选真机,Cmd + R。
Archive 打包:
- Product > Archive。
- 等!等!等!(iOS 编译是真慢)
- Organizer 弹出,Distribute App。
- 选 App Store Connect 或 Enterprise。
常见翻车现场:
| 报错 | 原因 | 解法 |
|---|---|---|
| Multiple commands produce | 模块冲突 | 关掉 Enable Modules |
| linker command failed | 缺库 | 手动 add libraries |
| dyld: Library not loaded | 没嵌入 Framework | 勾选 Embed Framework |
小猿的感悟: Android 的报错像数学题,iOS 的报错像哲学题。
第四章:双端对比------谁更难?
| 对比项 | Android | iOS |
|---|---|---|
| 开发工具 | Android Studio | Xcode |
| 构建语言 | Groovy/Kotlin DSL | Objective-C/Swift |
| 签名机制 | .jks 密钥库 | .p12 + .mobileprovision |
| 打包产物 | .apk | .ipa |
| 编译速度 | 慢 | 更慢 |
| 常见报错 | 依赖冲突 | Linker Error |
| 精神伤害 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
小猿的结论: Android 是"难",iOS 是"难上加难"。
第五章:UniApp 本地打包的真相
打通关之后,小猿画了一张流程图:
text
arduino
HBuilder 写代码
↓
发行 → 原生App-本地打包(SDK)
↓
导出资源包 → 拷到 phone-config
↓
打开 Android Studio / Xcode
↓
配签名/证书 → 构建 → 等待 → 安装
一句话总结:
UniApp 本地打包 ≈ 你用 H5 写了 App + DCloud 给你一个原生壳 + 你把 H5 资源塞进去 + 用原生工具打包成真正的 App。
尾声:小猿的忠告
- Android 的 .jks 要放好,丢了 Google Play 上架都得哭。
- iOS 的证书要提前在 Apple Developer 配好,审核要预留 1-2 天。
- 第一次本地打包巨慢,建议喝杯奶茶、看一集动画片再回来。
- DCloud SDK 更新频繁,记得看 Release Notes。
- 遇到问题先重启 IDE,不行再 Google,还不行就------睡一觉。
最后,小猿把 APK 和 IPA 发给 PM。
PM 说: "嗯不错,不过我觉得 UI 还得改一下......"
小猿: (╯°□°)╯︵ ┻━┻
但小猿知道,下次打包,他已经不怕了。
P.S. Android 入口就一个 MainActivity extends PandoraEntry,DCloud 引擎接管了一切。就像你请了个管家,他帮你搞定了所有原生的事。
P.P.S. 但管家再厉害,签名和证书还是得你自己配。这就是本地打包的真相。