介绍
- 云打包使用官方提供的服务,方便简单;但打包需要等待,依赖网络环境。
- 离线打包使用本地环境,本地打包生成APK,无需等待打包速度快,可锁定SDK版本。版本对照参考
基本流程
- 下载安装 HBuilderX,创建一个uniapp的基础项目
- 申请签名证书
- 下载android studio 下载地址
- 使用android studio安装android sdk
- 下载uniapp android SDK,版本要和HBuilderX版本保持一致 下载地址
- 使用uniapp android SDK构建/配置出一个uniapp android项目工程
- 使用HBuilderX生成uniapp项目的打包资源
- 将生成的uniapp项目打包资源复制到android项目工程,执行打包命令生成apk
uniapp离线打包key
- 安装HBuilderX后, 创建项目, 生成项目的APPID。新生成的APPID表明该项目创建在HBuilderX当前登录人dcloud账号下。
- 登录dcloud开发者后台dev.dcloud.net.cn
- 在
我的应用
中找到对应APPID的项目进入应用管理 Android云端证书-创建证书
创建证书各平台信息
新增平台信息,选择android平台,录入包名、SHA1、MD5、SHA256,后三项信息可以在证书详情
中找到,保存提交后即可生成离线打包key
配置android开发环境
准备jdk环境
推荐使用1.8版本
- 官网下载地址:oracle.com/java/techno...
- 以mac为例选择对应芯片类型SDK的.dmg文件下载
- 双击dmg根据提示一步步安装
- 终端中执行
java -version
检查是否安装成功 - 终端中执行
/usr/libexec/java_home -V
查看JDK下载地址 - 配置环境变量(zsh修改~/.zshrc文件)
plain text
编辑文本可以使用vim ~/.bash_profile
打开文件后按i进入编辑模式,编辑完成后按esc退出编辑模式,输入:wq保存并退出
具体可查看vim使用
- 在
~/.bash_profile
中添加下面两行,替换自己真实路径
bash
export JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home"
export PATH="$JAVA_HOME/bin:$PATH"
- 执行
source ~/.bash_profile
使改动立即生效 - 执行
echo $JAVA_HOME
检查是否生效
准备android studio
- 官网下载地址:developer.android.google.cn/studio
- 选择对应版本的安装包下载,根据提示进行安装
- Hedgehog版本的AS为例,在选择项目窗口的右上角进入
SDK Manager
,或者进入项目界面进入Settings-Languages & Frameworks-Android SDK-SDK Platforms
选择Android 11.0(R) API Level 30
的SDK进行安装
配置android工程
生成打包资源
- 在HBuilderX中选择项目
发行-原生App本地打包-生成本地打包App资源
plain text
如果不能生成并提示账号问题
检查当前HBuilderX登录账号是否有该APPID项目的权限
他人创建的项目需要项目创建人授权
找不到创建人可考虑重新生成APPID(注意查看风险提示)
左下角可以切换账号
示例目录生成的资源在dist目录下,是因为该项目是使用cli模式创建的,非cli模式项目生成资源在unpackage/resources目录下,具体查看HBuilderX控制台输出。
准备基础android项目
- 项目工程基于uniapp android SDK创建,下载的sdk版本应该与HBuidlerX版本保持一致 下载地址
- 以3.96版本SDK为例,包含以下目录
plain text
|-- HBuilder-Hello App离线打包演示应用
|-- HBuilder-Integrate-AS 集成uni-app的最简示例
|-- SDK SDK库文件目录
|-- Feature-Android.xls Android平台各扩展Feature API对应的详细配置
|-- Readme.txt 版本说明文件及注意事项
|-- UniPlugin-Hello-AS uni原生插件开发示例
- 基于
HBuilder-Integrate-AS
示例创建自己的android项目构建工程 - 使用android studio 打开HBuilder-Integrate-AS目录,等待编译完成
plain text
如果编译失败,依赖没有安装成功,可以尝试更换网络环境(🪜)
或者在根级build.gradle中配置阿里镜像源[https://developer.aliyun.com/mvn/guide]
如果是"Your build is currently configured to use Java 17.0.7 and Gradle 6.5"
说明工程配置的sdk和Gradle版本不匹配
- 选择升级gradle;修改file-Project Structure-Project-Gradle Version的版本
- 选择降级java;修改settings-Build Execution deployment-Build Tools-Gradle-Gradle JDK的中的java版本
配置工程
- 打开刚才准备的基础工程,在左上角切换为Android视图
- 将生成的离线打包资源复制到
simpleDemo-assets-apps
目录下,删除示例的__UNI__A
目录 - 修改文件
simpleDemo/assets/data/dcloud_control.xml
文件中的appid
,修改为uniapp项目的APPID,也是离线打包资源的目录名 - 修改
simpleDemo/src/main/res/values/strings.xml
文件中的app_name
,这个就是apk安装后显示的应用名称 - 修改
simpleDemo/manifests/AndroidManifest.xml
文件中的dcloud_appkey
,修改为前面步骤中生成的离线打包key(在dcloud后台中查看) - AS切换为project 视图,在dcloud后台下载之前申请的云端证书,防止在
simpleDemo
模块目录下,示例项目的.jks秘钥文件可以删除
实际上你可以将证书放在任何安全的地方,在打包时选择证书即可
- 修改
simpleDemo
模块下的build.gradle
文件,包名、秘钥别名、秘钥密码可以在dcloud后台中查看 - 执行打包操作
- 打包成功 将.apk文件安装到模拟器中尝试
- 至此项目配套的android打包工程就已经配置完成,以后每次打包只需要替换
生成的打包资源
文件和修改build.gradle
中的版本号versionCode``versionName
即可
常见问题
- app打不开,apk体积过大 查看abiFilters配置是否匹配,参考阅读blog.csdn.net/yearningsee...
- 未使用到的依赖过多导致包体积过大,根据实际需要删减android工程中的依赖,可以参照官方文档中各个模块的依赖进行修改nativesupport.dcloud.net.cn/AppDocs/use...
- 生成打包资源复到android工程后还需要手动修改android工程中的版本号 在
build.gradle
文件中,可以添加一个函数自动读取打包资源中的manifest.json
文件,然后在版本号配置里调用函数自动读取
java
// 头部添加依赖
import groovy.json.JsonSlurper
import org.json.JSONException
import org.json.JSONObject
// 调用读取json方法,传参根据实际修改
JSONObject appConfig = readManifest("__UNI__6DBB581")
println("版本号:" + appConfig.version.code.toString())
versionCode appConfig.version.code
versionName appConfig.version.name
// 读取manifest.json方法
JSONObject readManifest(appPath){
try {
def appConfigJsonFile = file("${rootDir}/simpleDemo/src/main/assets/apps/${appPath}/www/manifest.json")
def appConfigJson = new JsonSlurper().parseText(appConfigJsonFile.text)
return appConfigJson
} catch (IOException | JSONException e) {
e.printStackTrace()
}
return null
}
- 打包生成apk文件根据版本号自动重命名,默认打包的apk名称总是
simpleDemo-release.apk
可以写一段代码实现根据版本号/时间来重命名
java
android.applicationVariants.configureEach { variant ->
variant.outputs.configureEach {
def createTime = new Date().format("yyyyMMddHHmm", TimeZone.getTimeZone("GMT+08:00"))
def fileName = "app_v${defaultConfig.versionCode}_${createTime}.apk"
outputFileName = fileName
}
}