一、背景
简易:需不需要懂android知识速度:打包出一个APK的速度
云打包
简易:❤❤❤❤❤速度:❤
离线打包
简易:❤❤速度:❤❤❤❤❤
总结:
云打包虽然快,但需要排队,太影响开发效率。
离线打包,打包速度1分钟左右,但需要安装相应环境和懂一点安卓知识,项目涉及的模块和原生插件都需要手动配置。
二、需求
通过Docker镜像来一键打包,配置完之后,前端人员只需要点击jenkin来打包,且支持一份代码打包多个APK出来,分发各个甲方。
三、环境
PS: 这里不使用HBuild-cli来打包,原因: 1.官方的bug维护太慢 2.cli在占用时,再次执行cli命令直接不执行
四、开始
● 基础配置
# 运行一个ubuntu镜像(24.04)
docker run -it --name uniapp_app_build -p 9300:8080 ubuntu /bin/bash
# apt安装软件包
apt update
apt install sudo
apt install vim
# ubuntu设置中文
locale -a // 查看支持的字符编码
sudo vim ~/.bashrc // 添加export LANG=C.utf-8
source ~/.bashrc
● 安装Jenkins
# 安装JDK17
sudo apt install openjdk-17-jdk
java -version
# 安装Jenkins
sudo apt install curl
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee /usr/share/keyrings/jenkins-keyring.asc > /dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt update
sudo apt install jenkins
cd /home/ubuntu/jenkins
sudo apt install wget
wget https://get.jenkins.io/war/latest/jenkins.war
sudo java -jar jenkins.war
# 查看jenkin初始密码
cat /root/.jenkins/secrets/initialAdminPassword
● 测试jenkins
1、回到本地访问jenkins:http://127.0.0.1:9300 (账号root,密码1234567890)
2、新建任务=>构建一个自由风格的软件项目=>配置=>新增构建步骤=>输入下面命令=>执行成功即可
cat /etc/os-release
java -version
● 安装Node (非必须,可跳过)
curl https://get.volta.sh | bash
export VOLTA_HOME="$HOME/.volta"
export PATH="$VOLTA_HOME/bin:$PATH"
source ~/.bashrc
volta install node@22.12.0
node -v
npm i -g pnpm
pnpm config set registry https://registry.npmmirror.com/
pnpm get
● 安装Gradle
1. 官网https://gradle.org/releases/, 下载gradle8.11.1
# 拷贝到容器里
docker cp E:\gradle-8.11.1-all.zip uniapp_app_build:/home/ubuntu/gradle
# 解压
sudo apt install unzip
unzip -O CP936 gradle-8.11.1-all.zip
# 配置Gradle环境变量
sudo vim ~/.bashrc // 添加下面两个export
# export GRADLE_HOME=/home/ubuntu/gradle/gradle-8.11.1
# export PATH=$GRADLE_HOME/bin:$PATH
source ~/.bashrc
gradle -version
● 安装AS打包环境
1. 官网https://developer.android.google.cn/studio,往下滚找到Command line tools,下载linux版本(这里用的commandlinetools-linux-13114758_latest.zip)
# 拷贝到容器里
docker cp E:\commandlinetools-linux-13114758_latest.zip uniapp_app_build:/home/ubuntu/android_studio
# 解压
unzip -O CP936 commandlinetools-linux-13114758_latest.zip
# 测试
cd /home/ubuntu/android_studio/cmdline-tools/bin
./sdkmanager --list --channel=0
# 使用该命令报错
# Error: Could not determine SDK root.
# Error: Either specify it explicitly with --sdk_root= or move this package into its expected location: /cmdline-tools/latest/
# 报错了,无法找到sdk根目录,提示说有两种解决办法:一是用–sdk_root指定路径,二是把文件夹移动到指定路径。
# 修复报错
mkdir latest
mv bin/ lib/ NOTICE.txt source.properties -t latest/
cd latest/bin/
./sdkmanager --list --channel=0
# 安卓对应的平台和构建工具
# 我的Android项目使用的是compileSdkVersion 35,buildToolsVersion “35.0.0”
./sdkmanager "build-tools;35.0.0" "platforms;android-35"
# 设置环境变量
sudo vim ~/.bashrc // 添加下面两个export
# export ANDROID_HOME=/home/ubuntu/android_studio/cmdline-tools/latest
# export PATH=$ANDROID_HOME/bin:$PATH
source ~/.bashrc
sdkmanager --version
sdkmanager --licenses
● 离线打包壳
# 拷贝到容器里 (将本地的打包壳放到容器里,如果没有就按官网的配一下)
docker cp E:\HBuilder-Integrate-AS uniapp_app_build:/home/ubuntu/AppPackageShell
# 修改下面文件
# 修改 gradle-wrapper.properties 的 distributionUrl 为 file:///home/ubuntu/gradle/gradle-8.11.1-all.zip
# 修改 local.properties 的 sdk.dir 为 /home/ubuntu/android_studio
# 修改 build.gradle 的 getVersionFromJson 的路径为 src/main/assets/apps/__UNI__9999999/www/manifest.json
# 删除旧的apk
cd /simpleDemo/build/outputs/apk/release
rm -rf simpleDemo-release.apk
# 开始打包
./gradlew clean
./gradlew build
./gradlew assembleRelease
# 打包成功即可(注意这里的输出目录是simpleDemo/build/outputs/apk/release,和AS直接打包的输出路径不同的)
● jenkins配置git和node
# 配置git
sudo apt install git
git --version
which git
# jenkins -> Manage Plugins -> 添加git插件
# 配置node
# jenkins -> Manage Plugins -> 添加NodeJS插件
# setting -> 全局工具设置 -> NodeJS 安装 -> 别名:node22,勾选自动安装,版本选nodejs22.12.0

● jenkins打包配置


# 安装依赖
npm config set registry https://registry.npmmirror.com/
npm i pnpm -g
pnpm config set registry https://registry.npmmirror.com/
pnpm i
# 打包-删除旧的
rm -rf dist
# 打包-APP离线打包资源
npm run build:app-android
# 压缩为wgt
cd ./dist/build/app
zip -r ../../项目名称.wgt ./*
# APP离线打包资源拉到AS的壳
rm -rf /home/ubuntu/AppPackageShell/HBuilder-Integrate-AS/simpleDemo/src/main/assets/apps/__UNI__9999999/www/*
mv ./dist/build/app/* /home/ubuntu/AppPackageShell/HBuilder-Integrate-AS/simpleDemo/src/main/assets/apps/__UNI__9999999/www/
# 删除旧的APK
cd /home/ubuntu/AppPackageShell/HBuilder-Integrate-AS/simpleDemo/build
rm -rf outputs
# 打包APK
cd /home/ubuntu/AppPackageShell/HBuilder-Integrate-AS
./gradlew assembleRelease
#移动APK和wgt到/home/ubuntu/outputs
mv /home/ubuntu/AppPackageShell/HBuilder-Integrate-AS/simpleDemo/build/outputs/apk/release/*.apk /home/ubuntu/outputs
mv /root/.jenkins/workspace/jenkins的任务名称/dist/*.wgt /home/ubuntu/outputs
# 请求接口,上传到服务器
# response=$(curl -s -X POST -F "files=@/root/.jenkins/workspace/jenkins的任务名称/dist/项目名称.wgt" -H 'Accept: application/json' https://xxxxxx.com/xxxxx/upload)
# echo "Response: $response"
至此结束,即可使用jenkins来一键打包,当有多个apk要打,就复制壳,改改jenkin即可
其它问题
- 将容器打成镜像,大概有6G,看看如何缩减一下。
- 打成镜像会丢失jenkins配置哦,看看如何弄弄就好。
- 打成镜像之后,下面方式启动就好
docker run -it –name uniapp_app_build_v1 -v /e/docker_build_uniapp_apk/outputs:/home/ubuntu/outputs -p 9300:8080 uniapp_app_build:v1 /bin/bash -c “java -jar /home/ubuntu/jenkins/jenkins.war & tail -f /dev/null”
优化
● uniapp离线打包,build.grade动态设置版本号
def getVersionFromJson(type) {
def versionFile = file('/src/main/assets/apps/__UNI__96926FC/www/manifest.json')
if (!versionFile.exists()) {
throw new GradleException("version.json not found")
}
def versionJson = new groovy.json.JsonSlurper().parseText(versionFile.text)
println "versionJson: ${versionJson}"
println "versionJson.version.name: ${versionJson.version.name}"
println "versionJson.version.code: ${versionJson.version.code}"
if ("versionName" == type) {
return versionJson.version.name
} else if ("versionCode" == type) {
return versionJson.version.code.toInteger()
}
}
android {
defaultConfig {
versionName getVersionFromJson("versionName")
versionCode getVersionFromJson("versionCode")
}
}
● uniapp离线打包,设置打包APK名称
android {
android.applicationVariants.all{ variant ->
variant.outputs.all{
def createTime = new Date().format("YYYYMMddhhmm", TimeZone.getTimeZone("GMT+08:00"))
def fileName = "Driver_v${defaultConfig.versionName}_${createTime}.apk"
outputFileName = fileName
}
}
}