Jenkins 构建 Unity 打包 .apk 同时生成 .aab

Jenkins 构建 Unity 打包 .apk 同时生成 .aab

Android App Bundle简称 AAB,想了解更多关于 AAB 的知识,请看官网 https://developer.android.google.cn/guide/app-bundle/faq?hl=zh-cn

APK 打包部分在复用上一篇 Jenkins 构建 Unity打包APK

一、新建一个 Pipeline 任务

添加 Pipeline 脚本 jenkins_scripts\Pipeline\android_distribute_pipeline

// Android Distribute 打包 apk
pipeline {agent anystages {stage('Test Parameter') {steps {script {// shell 脚本目录ANDROID_DISTRIBUTE_SHELL_PATH="${env.WORKSPACE}/jenkins_scripts/shell/android_distribute.sh"// 给 shell 脚本添加权限并执行sh "chmod +x ${ANDROID_DISTRIBUTE_SHELL_PATH} && ${ANDROID_DISTRIBUTE_SHELL_PATH}"}}}}
}

添加 Shell 脚本 jenkins-script\shell\ci_android_distribute.sh

#!/bin/sh#!/bin/bashecho "this is android_distribute.sh"
# 输出工作目录
echo "WORKSPACE=${WORKSPACE}"# Unity 安装目录
UNITY_PATH=/Applications/Unity/Hub/Editor/2022.3.26f1/Unity.app/Contents/MacOS/Unity
# Unity 项目目录 Assets、Library、ProjectSettings 文件夹在 PROJECT_PATH 路径下
PROJECT_PATH="${WORKSPACE}/Project"
# bundleTool 路径 https://developer.android.com/tools/bundletool?hl=zh-cn
BUNDLE_TOOL_PATH="${WORKSPACE}/jenkins_scripts/Tools/bundletool-all-1.18.0.jar"# 通过 export 将变量标记为环境变量,并传递给 Unity 使用
# 导出到 Unity 后都是 字符串
# 在 Unity 中通过 string value = Environment.GetEnvironmentVariable(key); 获取
# bool 类型的传递过去是字符串 "true" 和 "false"
export WORKSPACE_PATH="${WORKSPACE}"
export EXPORT_PATH="${WORKSPACE}/Export"
export KEY_STORE_PATH="${WORKSPACE}/jenkins_scripts/Tools/user.keystore"
# 生成的 apk 名字
export APK_NAME="${JOB_BASE_NAME}_${BUILD_ID}_${BRANCH_NAME:18}.apk"
# 生成的 apk 路径
export EXPORT_APK_PATH="${EXPORT_PATH}/${APK_NAME}"
# 生成 .aab 文件
export BUILD_AAB="true"
# aab 生成路径
export GOOGLE_PLAY_AAB_PATH="${EXPORT_PATH}/googlePlay.aab"
# build-apks 命令从aab 生成的 apk 组路径
OUT_PUT_APKS_PATH_1="${EXPORT_PATH}/output_1.apks"
# extract-apks 从 OUT_PUT_APKS_PATH_1的APK 集中提取设备专用 APK
OUT_PUT_APKS_PATH_2="${EXPORT_PATH}/output_2.apks"
# extract-apks 使用的设备规范 JSON
SAMSUNG_S9_PATH="${WORKSPACE}/jenkins_scripts/Tools/Samsung_S9.json"    echo "UNITY_PATH=${UNITY_PATH}"
echo "PROJECT_PATH=${PROJECT_PATH}"
echo "BUNDLE_TOOL_PATH=${BUNDLE_TOOL_PATH}"
echo "APK_NAME=${APK_NAME}"
echo "EXPORT_APK_PATH=${EXPORT_APK_PATH}"
echo "BUILD_AAB=${BUILD_AAB}"
echo "GOOGLE_PLAY_AAB_PATH=${GOOGLE_PLAY_AAB_PATH}"
echo "OUT_PUT_APKS_PATH_1=${OUT_PUT_APKS_PATH_1}"
echo "OUT_PUT_APKS_PATH_2=${OUT_PUT_APKS_PATH_2}"
echo "SAMSUNG_S9_PATH=${SAMSUNG_S9_PATH}"# 下面是调用 Unity 的命令
# 在 Assets 文件夹下任意目录 创建文件夹 Editor
# 新建 PojectExport.cs  删除继承 MonoBehaviour   
# 添加一个 public static void Export() 方法
# 下面命令通过 PojectExport.Export 调用
$UNITY_PATH -projectPath $PROJECT_PATH \
-buildTarget android \
-executeMethod ProjectExportApk.ExportApkAndAAB \
-logfile - \
-batchMode -quit \
-GMModeecho "Export apk and aab success"#BundleTools
java -jar ${BUNDLE_TOOL_PATH} build-apks --bundle=${GOOGLE_PLAY_AAB_PATH} --output=${OUT_PUT_APKS_PATH_1}
java -jar ${BUNDLE_TOOL_PATH} extract-apks --apks=${OUT_PUT_APKS_PATH_1} --output-dir=${OUT_PUT_APKS_PATH_2} --device-spec=${SAMSUNG_S9_PATH}echo "this is android_distribute.sh end"# ProjectExportApk.ExportApkAndAAB 方法中生成 .apk 和 .aab 文件
# Android 上线 Google Play 只需要将生成的 .aab 上传到 GooglePlay 即可# bundletool 命令的作用,官方文档 https://developer.android.com/tools/bundletool?hl=zh-cn
# java -jar ${BUNDLE_TOOL_PATH} build-apks --bundle=${GOOGLE_PLAY_AAB_PATH} --output=${OUT_PUT_PATH} 
# 作用是使用 bundletool 工具从 Android App Bundle(.aab 文件)生成 APK 集合
# 并将生成的 APK 集合打包成一个名为“APK set archive”的文件,文件扩展名为 .apks
# 这个命令会将指定的 .aab 文件转换为 APK 集合,并将结果输出到指定的路径(OUT_PUT_PATH)。# java -jar ${BUNDLE_TOOL_PATH} extract-apks --apks=${OUT_PUT_PATH} --output-dir=${OUT_APKS_PATH} --device-spec=${SAMSUNG_S9_PATH} 
# 作用是从之前生成的 APK 集合(.apks 文件)中提取出针对特定设备配置的 APK
# --device-spec 参数指定了一个 JSON 文件(SAMSUNG_S9_PATH),该文件描述了目标设备的特性(如屏幕大小、CPU 架构等),从而确保提取的 APK 适合该设备# 从上面两条 bundletool 命令的作用,我们了解到,只是用 .aab 生成 apk 组到 .apks,然后再通过 --device-spec 指定的 Json 配置文件
# 从 .apks 文件中提取出满足特定设备的 apk
# .aab 文件还是ProjectExportApk.ExportApkAndAAB 方法中生成的,没有做任何处理
# 那么为什么要添加上面两条 bundletool 命令?
# 这在开发和测试阶段是非常有用的,因为它允许开发者在本地测试和验证 APK 的功能,特别是在不同的设备配置下确保其在目标设备上能正常运行。
# 对于上传到 Google Play 的生产版本,这些步骤可能不是必须的,但常常在 CI/CD 流程中用于验证构建的有效性。
# 这些命令在比较典型的开发工作流中是有用的,尤其是在测试和验证阶段,当开发者需要验证构建后的 APK 是否如预期那样工作时
三、项目配置

配置 Jenkins 构建 Unity打包APK 是一样的
修改 Editor/ProjectExportApk.cs

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using Google.Android.AppBundle.Editor;public class ProjectExportApk : Editor
{private static BuildOptions s_BuildOptions = BuildOptions.CompressWithLz4HC;[MenuItem("Tools/ExportAPK")]public static void ExportAPK(){Debug.Log("ExportApk ExportAPK start");// 切换平台到 Android 分支bool switchAndroid = EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);if (!switchAndroid){Debug.LogError("ExportApk Switch Android Error");return;}Debug.Log("ExportApk Switch Android success");string exportPath = WorkExportPath();if (Directory.Exists(exportPath)){Directory.Delete(exportPath, true);}Directory.CreateDirectory(exportPath);PlayerSettings.applicationIdentifier = "com.DeCompany.Project";string keystorePath = GetKeyStorePath();Debug.Log("keystorePath:" + keystorePath);// 配置 keystore 信息PlayerSettings.Android.keystoreName = keystorePath;PlayerSettings.Android.keystorePass = "123456";PlayerSettings.Android.keyaliasName = "testapk";PlayerSettings.Android.keyaliasPass = "123456";PlayerSettings.Android.useCustomKeystore = true;PlayerSettings.Android.bundleVersionCode = 2;PlayerSettings.Android.useAPKExpansionFiles = false;EditorUserBuildSettings.buildAppBundle = EnvironmentUtil.GetBool("BUILD_AAB", false);// 生成符号文件EditorUserBuildSettings.androidCreateSymbols = AndroidCreateSymbols.Public;EditorUserBuildSettings.exportAsGoogleAndroidProject = false;var options = s_BuildOptions;// 是否连接 profilerbool connectProfiler = false;if (connectProfiler){options |= BuildOptions.Development;EditorUserBuildSettings.development = true;EditorUserBuildSettings.connectProfiler = true;EditorUserBuildSettings.buildWithDeepProfilingSupport = true;}EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle;PlayerSettings.bundleVersion = "1.1.1";PlayerSettings.productName = "TestProduct";var targetArchitectures = AndroidArchitecture.ARM64 | AndroidArchitecture.ARMv7;PlayerSettings.Android.targetArchitectures = (AndroidArchitecture)targetArchitectures;// PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, defs);List<string> levels = new List<string>();foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes){if (!scene.enabled) continue;// 获取有效的 Scenelevels.Add(scene.path);}string apkPath = GetApkPath();Debug.Log("apkPath:" + apkPath);BuildPipeline.BuildPlayer(levels.ToArray(), apkPath, BuildTarget.Android, options);}public static void ExportApkAndAAB(){ExportAPK();if (!EditorUserBuildSettings.buildAppBundle){return;}string aabPath = GetAABPath();var buildPlayerOptions = AndroidBuildHelper.CreateBuildPlayerOptions(aabPath);var assetPackConfig = new AssetPackConfig();assetPackConfig.SplitBaseModuleAssets = true;Google.Android.AppBundle.Editor.Internal.AppBundlePublisher.Build(buildPlayerOptions, assetPackConfig, false);}public static string WorkExportPath(){return EnvironmentUtil.GetString("EXPORT_PATH", Application.dataPath);}private static string GetKeyStorePath(){return EnvironmentUtil.GetString("KEY_STORE_PATH", string.Empty);}private static string GetApkPath(){return EnvironmentUtil.GetString("EXPORT_APK_PATH", "output.apk");}private static string GetAABPath(){return EnvironmentUtil.GetString("GOOGLE_PLAY_AAB_PATH", "googleplay.aab");}}
ExportAPK() 方法中没有做任何修改,复用的打包 APK 的代码

生成 aab 用到了 AndroidBuildHelper、AssetPackConfig、AppBundlePublisher 类
这三个类包含在命名空间Google.Android.AppBundle.Editor中,是插件 com.google.android.appbundle 提供的
插件官方 gitHub 地址 https://github.com/google/play-unity-plugins
在这里插入图片描述
github 打开插件并下载,解压目录找到 GooglePlayPlugins 文件夹打开
在这里插入图片描述
com.google.android.appbundle 文件夹就是需要的插件
到 Unity 项目 Assets 文件夹下创建文件夹 GooglePlayPlugins,复制场面解压出来的 com.google.android.appbundle 文件夹粘贴到 Assets 文件夹下的 GooglePlayPlugins 文件夹

关于 bundletool 更多命令的使用请看 官网 https://developer.android.com/tools/bundletool?hl=zh-cn

例如:将 APK 部署到连接的设备
生成一组 APK 后,bundletool 可以将其中适当的 APK 组合部署到已连接的设备。
如果您的已连接设备搭载 Android 5.0(API 级别 21)或更高版本,bundletool 会推送在该设备上运行您的应用所需的基础 APK、功能模块 APK 和配置 APK。

如果您的已连接设备搭载 Android 4.4(API 级别 20)或更低版本,bundletool 会搜索兼容的多 APK,以将其部署到您的设备。

如需从 APK 集部署您的应用,请使用 install-apks 命令并使用 --apks=/path/to/apks 标志指定 APK 集的路径,如以下命令所示。如果您连接了多个设备,请添加 --device-id=serial-id 标志来指定目标设备。

bundletool install-apks --apks=/MyApp/my_app.apks

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/22534.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVAweb-标签选择器,盒模型,定位,浮动

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>标签</title><style type"text/css&q…

计算机视觉:主流数据集整理

第一章&#xff1a;计算机视觉中图像的基础认知 第二章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(一) 第三章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(二) 第四章&#xff1a;搭建一个经典的LeNet5神经网络(附代码) 第五章&#xff1…

二级公共基础之数据结构与算法篇(五)树和二叉树

目录 前言 一、树的基本概念 1.父结点和根节点 2.子节点和叶子节点 3.度和深度 4.子树 二、二叉树及其基本性质 1. 二叉树的定义 2. 二叉树的基本性质 性质1 性质2 性质3 性质4 性质5 性质6 三、二叉树的存储结构 四、二叉树的遍历 1.遍历二叉树的概念 1. 前…

自制操作系统学习第七天

今天要做什么&#xff1f; 实现HLT&#xff0c;不让计算机处于HALT&#xff08;HLT&#xff09;.用C语言实现内存写入&#xff08;错误&#xff0c;需要分析&#xff09; 一:使用HLT&#xff0c;让计算机处于睡眠状态 写了下面这个程序&#xff0c;naskfunc.nas 函数名叫io_h…

Python Django系列—入门实例(二)

数据库配置 现在&#xff0c;打开 mysite/settings.py 。这是个包含了 Django 项目设置的 Python 模块。 默认情况下&#xff0c;​ DATABASES 配置使用 SQLite。如果你是数据库新手&#xff0c;或者只是想尝试 Django&#xff0c;这是最简单的选择。SQLite 包含在 Python 中…

DeepSeek接入Siri(已升级支持苹果手表)完整版硅基流动DeepSeek-R1部署

DeepSeek接入Siri&#xff08;已升级支持苹果手表&#xff09;完整版硅基流动DeepSeek-R1部署 **DeepSeek** 是一款专注于深度学习和人工智能的工具或平台&#xff0c;通常与人工智能、机器学习、自动化分析等领域有关。它的主要功能可能包括&#xff1a;深度学习模型搜索&…

抗辐照加固CAN FD芯片的商业航天与车规级应用解析

在工业自动化、智能汽车、航空航天及国防装备等关键领域&#xff0c;数据传输的安全性、可靠性与极端环境适应能力是技术升级的核心挑战。国科安芯推出全新一代CANFD&#xff08;Controller Area Network Flexible Data Rate&#xff09;芯片&#xff0c;以高安全、高可靠、断电…

Java数据结构第十二期:走进二叉树的奇妙世界(一)

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 目录 一、树型结构 1.1. 树的定义 1.2. 树的基本概念 1.3. 树的表示形式 二、二叉树 2.1. 概念 2.2. 两种特殊的二叉树 2.3. 二叉树的性质 2.4. 二叉树的存储 三、二叉树的基本操作 一、树型结构 1.…

nginx 反向代理 配置请求路由

nginx | 反向代理 | 配置请求路由 nginx简介 Nginx&#xff08;发音为“Engine-X”&#xff09;是一款高性能、开源的 Web 服务器和反向代理服务器&#xff0c;同时也支持邮件代理和负载均衡等功能。它由俄罗斯程序员伊戈尔西索夫&#xff08;Igor Sysoev&#xff09;于 2004…

ath9k(Atheros芯片)开源驱动之wifi连接

为什么会推荐这个wifi 驱动进行学习&#xff1f; ath9k&#xff08;Atheros芯片&#xff09;&#xff1a;代码结构清晰&#xff0c;适合学习实践 为什么我只在开篇写了一个wifi连接的操作&#xff1f; 先让一个开源驱动在你的硬件上跑起来&#xff0c;再逐步修改&#xff0c…

LLaMA-Factory|微调大语言模型初探索(4),64G显存微调13b模型

上篇文章记录了使用lora微调deepseek-7b&#xff0c;微调成功&#xff0c;但是微调llama3-8b显存爆炸&#xff0c;这次尝试使用qlora微调HQQ方式量化&#xff0c;微调更大参数体量的大语言模型&#xff0c;记录下来微调过程&#xff0c;仅供参考。 对过程不感兴趣的兄弟们可以直…

知识管理平台如何实现高效数据整合?

内容概要 现代知识管理平台通过架构化的四库体系&#xff08;资源库、规则库、模型库、知识库&#xff09;驱动数据智能整合进程。核心机制依托智能数据工具集对异构数据进行自动化清洗与语义标注&#xff0c;其跨源数据汇聚能力支持超过200种结构化与非结构化数据源的接入&am…

近10年气象分析(深度学习)

这是一个气象数据分析程序&#xff0c;主要用于分析和可视化气象数据。以下是该文件的主要功能&#xff1a; 1. 数据加载 在线数据&#xff1a;尝试从 GitHub 加载气象数据。 示例数据&#xff1a;如果无法加载在线数据&#xff0c;程序会自动生成示例数据。 2. 数据分析 …

DeepSeek最新开源动态:核心技术公布

2月21日午间&#xff0c;DeepSeek在社交平台X发文称&#xff0c;从下周开始&#xff0c;他们将开源5个代码库&#xff0c;以完全透明的方式与全球开发者社区分享他们的研究进展。并将这一计划定义为“Open Source Week”。 DeepSeek表示&#xff0c;即将开源的代码库是他们在线…

wps中zotero插件消失,解决每次都需要重新开问题

参考 查看zotero目录 D:\zotero\integration\word-for-windows 加载项点击 dotm即可 长期解决 把dom 复制到 C:\Users\89735\AppData\Roaming\kingsoft\office6\templates\wps\zh_CN还是每次都需要重新开的话 重新加载一下

洛谷B3629

B3629 吃冰棍 - 洛谷 代码区&#xff1a; #include<algorithm> #include<iostream>using namespace std; int main(){int n,ans;cin >> n;for(int in/2;i<n;i){int ti;ans0;while(t>3){t-3;ans3;t;}if(anst>n){cout << i;return 0;}}return…

VMware安装Centos 9虚拟机+设置共享文件夹+远程登录

一、安装背景 工作需要安装一台CentOS-Stream-9的机器环境&#xff0c;所以一开始的安装准备工作有&#xff1a; vmware版本&#xff1a;VMware Workstation 16 镜像版本&#xff1a;CentOS-Stream-9-latest-x86_64-dvd1.iso &#xff08;kernel-5.14.0&#xff09; …

[ProtoBuf] 介绍 | 保姆级win/linux安装教程

目录 一、序列化概念 二、ProtoBuf 是什么 三、ProtoBuf 的使用特点 ProtoBuf 在不同操作系统下的安装 一、ProtoBuf 在 Windows 下的安装 二、ProtoBuf 在 Linux 下的安装 三、检查是否安装成功 安装教程 可以直接目录跳转到后面 笔记参考&#xff1a;官方文档 一、序…

element ui的select选择框

我们首先先试一下&#xff0c;这个东西怎么玩的 <el-select v-model"select" change"changeSelect"><el-option value"香蕉"></el-option><el-option value"菠萝"></el-option><el-option value&quo…

51单片机学习之旅——定时器

打开软件 1与其它等于其它&#xff0c;0与其它等于0 1或其它等于1&#xff0c;0或其它等于其它 TMODTMOD&0xF0;//0xF01111 0000进行与操作&#xff0c;高四位保持&#xff0c;低四位清零&#xff0c;高四位定时器1&#xff0c;低四位定时器0 TMODTMOD|0x01;//0x010000 0…