谷歌新安装包文件形式 .aab 在UE4中的打包原理
摘要
本文学习了aab的基本概念以及UE4中产生aab的构建原理。
从官网了解基本概念
官网:Android Developers
1、什么是aab?
.aab包形如:
2021年7月,在Google Play应用程序中,已经有数千个应用程序率先跟进了AAB格式。谷歌宣布从2021年8月份开始,所有提交到Google Play商店的新应用必须采用AAB格式。
全称Android App Bundles。谷歌在2018年启用了AAB新格式(AAB全称为Android App Bundles”),谷歌声称这种新格式将使应用程序文件更小,意味着aab分布式应用程序比通用apk平均少占用15% 的空间。更重要的是,它拓展了应用程序捆缚包的定义,只包含运行App时的必要代码。也就是说,下载了一部分之后,App就可以直接运行,无需等待下载完成再安装。
2、什么是PAD?
全称 Play Asset Delivery,它是能够打包出 aab 的组件。
3、三个分发模式是什么?
- install-time 资源包在用户安装应用时分发。这些资源包以拆分 APK(APK 集的一部分)的形式提供。它们也称为“预先”资源包;您可以在应用启动时立即使用这些资源包。这些资源包会增加 Google Play 商店上列出的应用大小。用户无法修改或删除这些资源包。
- fast-follow 资源包会在用户安装应用后立即自动下载;用户无需打开应用即可开始 fast-follow 下载。下载过程中,用户仍然可以进入应用。这些资源包会增加 Google Play 商店上列出的应用大小。
- on-demand 资源包会在应用运行时下载。
Google Play 商店会以归档文件(而非拆分 APK)的形式提供配置为 fast-follow 和 on-demand 的资源包。然后,这些资源包会在应用的内部存储空间中展开。
4、资源更新的方式
更新应用时,install-time Asset Pack 会作为基础应用更新的一部分进行更新(开发者无需执行任何操作)。
对于 fast-follow 和 on-demand Asset Pack 的应用更新,则遵循以下步骤:
1 系统将应用的补丁程序(包括所有资产)下载到设备上的安全位置。
2 更新应用二进制文件;这包括所有 install-time Asset Pack。
3 之前下载的所有 Asset Pack 变为无效。
4 将资源的补丁复制并应用到存储在应用内部存储空间中的资源。
5、什么是apks?apks,即apk split,分散的apk。
现在我们从谷歌商店上下载的应用多半都是apks格式的。
apks格式的安装包,就是使用了Android App Bundle(AAB)技术生成的安装包。
这种技术实际上就是将apk文件拆分成多个小包,再根据当前的设备选择适当的文件下载安装。
通过这种技术,谷歌商店就可以根据我们的设备生成一个适合当前设备的安装包,例如使用大屏幕设备的用户就不需要下载小屏幕的资源,使用arm v8架构设备的用户就不需要下载arm v7架构的资源(当然还存在x86架构的),使用中文的用户就不需要下载其他的语言文件,这样就可以在实现更多功能的同时减小app占用空间的大小。并且为开发者提供了灵活的分发方式和极高的性能。同时apks将不再支持使用obb数据包拓展软件,这也意味着使用obb数据包的xapk已经成为过去式了。
6、互斥性。
打apk就不应该打aab、apks;打aab、apks就不应该打apk。aab、apks应该同时出现。
开关
在设置中找到开关 “Generate bundle (AAB)”,打开它表示生成Google的AAB。
位置是:
EngineSource\Engine\Source\Runtime\Android\AndroidRuntimeSettings\Classes\AndroidRuntimeSettings.h
// Enables generating AAB bundleUPROPERTY(GlobalConfig, EditAnywhere, Category = "App Bundles", Meta = (DisplayName = "Generate bundle (AAB)"))bool bEnableBundle;
它影响了 EngineSource\Engine\Source\Programs\UnrealBuildTool\Platform\Android\UEDeployAndroid.cs 中的逻辑,大致是:
// 位于 private void MakeApk(...) 方法中if (!bEnableBundle) // 如果打的是 apk
{ …… RunCommandLineProgramWithExceptionAndFiltering(UE4BuildGradlePath, ShellExecutable, ShellParametersBegin + "\"" + GradleScriptPath + "\" " + GradleOptions + ShellParametersEnd, "Making .apk with Gradle...");……
}
else // 如果打的是aab、apks
{ ……RunCommandLineProgramWithExceptionAndFiltering(UE4BuildGradlePath, ShellExecutable, ShellParametersBegin + "\"" + GradleScriptPath + "\" " + GradleOptions + ShellParametersEnd, "Making .aab with Gradle...");……
}
所谓RunCommandLineProgramWithExceptionAndFiltering,字面上执行的是:
// 【书签1】
2024-10-12 15:14:19:037 : VERBOSE:
2024-10-12 15:14:19:037 : Running: cmd.exe /c "{我的项目}\Intermediate\Android\gradle\rungradle.bat" --stacktrace :app:bundleDebug --init-script init.gradle --profile
从字面意思 rungradle.bat 可以得知,无论是打 .apk 还是打 .aab/.apks,都是用 Gradle 来打包的。Gradle是安卓的构建打包管理工具。关于Gradle,推荐阅读《实战Gradle(中文完整版)》这本书。
rungradle.bat
这个脚本位于 {我的项目}\Intermediate\Android\gradle\.gradle 目录,它是 Engine\Source\Programs\UnrealBuildTool\Platform\Android\UEDeployAndroid.cs 生成出来的。内容如下:
@echo off
setlocal
set GRADLEPATH=%~dp0
set GRADLE_CMD_LINE_ARGS=
:setupArgs
if ""%1""=="""" goto doneStart
set GRADLE_CMD_LINE_ARGS=%GRADLE_CMD_LINE_ARGS% %1
shift
goto setupArgs:doneStart
subst Z: "%CD%"
pushd Z:
call "%GRADLEPATH%\gradlew.bat" %GRADLE_CMD_LINE_ARGS%
set GRADLEERROR=%ERRORLEVEL%
popd
subst Z: /d
exit /b %GRADLEERROR%
它调用的是gradlew.bat,在日志中会衔接Gradle的日志,如下:
Package
MakeApk函数包括了“生成apk”与“生成.aab、.apks”的功能,MakeApk函数发生在 UE4的package阶段。具体的调用过程示意图:
【书签1】的日志,就是在这个过程中间来的,见 UEDeployAndroid.cs 中。尽管叫做 UEDeployAndroid.cs ,但Package阶段会调用它。
众所周知,Package步骤对应的脚本是:
%EnginePath%\Engine\Build\BatchFiles\RunUAT.bat BuildCookRun -project=%ClientPath%\%ProjectName%.uproject -noP4 -platform=Android -client -clientconfig=%TargetBuildConfig% -cookflavor=%COOK_FLAVOR% %DISTRIBUTION% -skipcook -pak -compressed -stage -NoDebugInfo -package -ignorejunk -nocompile -archive -archivedirectory=%ClientPath%\Saved\Archived -manifests -Verbose
这里参数很多,不是这里的重点。这里说一个技巧,如何让【书签1】所对应的c#脚本,能够输出verbose日志呢?做法是为 RunUAT.bat 脚本传参 -Verbose,如上面命令的末尾处。
而Gradle的日志可以在哪里看呢?
打AAB包时,将会在这个位置 C:\android_build_tools\gradle-4.1-rc-2\daemon\7.2 (gradle所在环境)产生日志文件。
UE4中的Gradle工程
UE4的Gradle工程位于 {我的项目}\Intermediate\Android\gradle ,结构如下:
我在查一些无聊的问题(下面两个问题)时,发现清除UE4的Intermediate、Binaries目录,能够有效果,推测是Gradle工程脏了导致的,因此,删除Gradle工程是一个好的选择,毕竟它在Intermediate中,可以安全地删除,删除后UE4会重新产生Gradle工程。
(问题1:“main.obb.png”出现在.aab的base目录中,而不是在obbassets目录中)
(问题2:.apk、.aab|.apks 都会错误地同时出,而应该只出apk或只出aab|apks)
GooglePAD_APL.xml
在EngineSource下,GooglePAD 是谷歌生成.aab的模块。GooglePAD_APL.xml 是其中一个中间作用文件,它搭建了 UE4 到 Gradle 的桥梁,具体的关系如下:
上图只是简单阐述,下面将会仔细理解GooglePAD_APL.xml。接下来,我描述的方式是:贴一段文件内容,然后接一些解释。注意,并非所有的内容都贴出来了。
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:android="http://schemas.android.com/apk/res/android">
<init>
<log text="GooglePAD Plugin Init"/>
<setBoolFromProperty result="bEnabled" ini="Engine" section="/Script/GooglePADEditor.GooglePADRuntimeSettings" property="bEnablePlugin" default="false"/>
<setBoolFromProperty result="bOnlyDistribution" ini="Engine" section="/Script/GooglePADEditor.GooglePADRuntimeSettings" property="bOnlyDistribution" default="true"/>
依据 /Script/GooglePADEditor.GooglePADRuntimeSettings 的UE4配置,来设置变量值。
<!-- NDK path -->
<setString result="NDKVersion" value="ndk21.4.7075529"/>
声明一个字符串变量。
<if condition="bEnabled">
<true>
<!-- disable if app bundle disabled -->
<if condition="bEnableBundle">
<false>
<log text="Disabled because not generating AAB bundle"/>
<setBool result="bEnabled" value="false"/>
</false>
</if>
等价于
if bEnabled: if not bEnableBundle: bEnabled = False
当if else语句多起来时,这种描述方式会让人抓狂。
<resourceCopies>
<log text="Copying libplaycore.so and proguard files"/>
<!-- note: have to stage this since we linked it -->
<copyFile src="$S(AbsPluginDir)/../ThirdParty/play-core-native-sdk/libs/$S(Architecture)/$S(NDKVersion)/c++_shared/libplaycore.so"
dst="$S(BuildDir)/libs/$S(Architecture)/libplaycore.so" />
<isDistribution>
<copyDir src="$S(AbsPluginDir)/../ThirdParty/play-core-native-sdk/proguard"
dst="$S(BuildDir)/gradle/app/proguard" />
</isDistribution>
</resourceCopies>
一段和资源拷贝有关的逻辑。
<settingsGradleAdditions>
<if condition="bEnabled">
<true>
<insert>
<![CDATA[
// generate mainobb assetpack
if (OBB_FILECOUNT.toInteger() > 0) {
File obbfile = new File(OBB_FILE0)……
]]>
<![CDATA[ 后面的内容,直到 ]]> ,是XML语言中的表示纯粹字符串。这段表示对 settings.gradle 追加字符串,稍后会介绍 settings.gradle。
<gameActivityOverrideAPKOBBPackaging>
<if condition="bEnabled">
<true>
<insert>
<
谷歌新安装包文件形式 .aab 在UE4中的打包原理
摘要 本文学习了aab的基本概念以及UE4中产生aab的构建原理。 从官网了解基本概念 官网:Android Developers 1、什么是aab? .aab包形如: 2021年7月,在Google Play应用程序中,已经有数千个应用程序率先跟进了AAB格式。…...

昂首平台:多货币专家顾问助力投资者优化外汇投资
昂首平台推出的多货币专家顾问(EA)为投资者提供了多样化的货币对交易选择。考虑到外汇市场的复杂性,大多数EA系统专注于价差较低的主要货币对,如EUR/USD或GBP/USD。交易那些价差较大的非主流货币对,如EUR/JPY和AUD/CAD,可能会增加…...
Go标准库runtime.MemStats
在 Go 语言中,runtime.MemStats 是一个结构体,它提供了关于 Go 程序内存使用情况的统计信息。这个结构体是 runtime 包中的 MemStats 类型,它包含了多个字段,用于报告内存分配器的统计数据,如内存分配、释放、垃圾回收…...

MAC 电脑Office power point编辑的时候,显示“某些字体无法随演示文稿一起保存,仍然要保存演示文稿吗?”
目录 问题描述: 问题解决: 问题描述: 在使用mac电脑的power point打开别人的.ppt文件之后,在保存的时候,弹出““某些字体无法随演示文稿一起保存,仍然要保存演示文稿吗?”,每次只…...

R语言机器学习算法实战系列(四)随机森林算法+SHAP值 (Random Forest)
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍教程下载数据加载R包导入数据数据预处理数据描述特征选择数据切割调节参数构建模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve特征的重要性模型解释保…...

用柔性神经k-Opt学习搜索路径问题的可行和不可行区域(未完,先看前驱文章L2S)
文章目录 Abstract1 IntroductionAbstract 介绍了一种名为 Neural k-Opt(NeuOpt)的新型学习搜索(L2S)求解器,用于解决路径问题。它学习执行基于定制的动作分解方法和定制的循环双流(Recurrent Dual-Stream)解码器的灵活 k-opt 交换。 作为一项开创性的工作,我们绕过了…...

【升华】人工智能python重要库scikit-learn学习
一、人工智能python重要库scikit-learn 在人工智能10大算法中,有8个算法都导入了 sklearn库 from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn import metrics # 导入所需的库 from sklea…...

Stable Diffusion Web UI 大白话术语解释 (二)
归纳整理,Stable Diffusion Web UI 使用过程中,相关术语 ControlNet ControlNet 说简单点,就是你可以给 AI 一些“规则”,比如让它根据某些线条、结构或者骨架去画图。 这样能让 AI 画出更符合你要求的图片,特别适合画…...
vue-vben-admin 首页加载慢优化 升级vite2到vite3
我的vben-admin是2.8版本的,首次首页加载太慢了,升级下vite,原来1分钟,现在20s左右 1.修改package.json 添加 "terser": "^5.14.2",修改 "vitejs/plugin-legacy": "^2.0.0","vitejs/plugin-vue": "^3.0.1",&qu…...

集合框架07:LinkedList使用
1.视频链接:13.14 LinkedList使用_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1zD4y1Q7Fw?spm_id_from333.788.videopod.episodes&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5&p142.LinkedList集合的增删改查操作 package com.yundait.Demo01;im…...

一区鱼鹰优化算法+深度学习+注意力机制!OOA-TCN-LSTM-Attention多变量时间序列预测
一区鱼鹰优化算法深度学习注意力机制!OOA-TCN-LSTM-Attention多变量时间序列预测 目录 一区鱼鹰优化算法深度学习注意力机制!OOA-TCN-LSTM-Attention多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.基于OOA-TCN-LSTM-Attenti…...

Cesium 黑夜效果
Cesium 黑夜效果 原理: 根据相机到片元的距离雾化场景的后处理效果 效果:...
leetcode动态规划(二)-斐波那契数列
题目 509.斐波那契数列 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n - 1) F(n - 2)࿰…...

【MySQL】增删改查-进阶(一)
目录 🌴数据库约束 🚩约束类型 🚩NOT NULL 🚩UNIQUE 🚩DEFAULT 🚩PRIMARY KEY 🚩FOREIGN KEY 🚩CHECK 🎄表的设计 🚩一对一 🚩一对多 …...

MacOS RocketMQ安装
MacOS RocketMQ安装 文章目录 MacOS RocketMQ安装一、下载二、安装修改JVM参数启动关闭测试关闭测试测试收发消息运行自带的生产者测试类运行自带的消费者测试类参考博客:https://blog.csdn.net/zhiyikeji/article/details/140911649 一、下载 打开官网,…...

OpenCV高级图形用户界面(6)获取指定窗口中图像的矩形区域函数getWindowImageRect()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 提供窗口中图像的矩形区域。 该函数 getWindowImageRect 返回图像渲染区域的客户端屏幕坐标、宽度和高度。 函数原型 Rect cv::getWindowImage…...

SpringColoud GateWay 核心组件
优质博文:IT-BLOG-CN 【1】Route路由: Gateway的基本构建模块,它由ID、目标URL、断言集合和过滤器集合组成。如果聚合断言结果为真,则匹配到该路由。 Route路由-动态路由实现原理: 配置变化Apollo 服务地址实例变化…...

5.计算机网络_抓包工具wireshark
安装 Linux中安装wireshark: sudo apt-get install wireshark Linux中执行wireshark: sudo wireshark 使用 注意:只有与外网交互的数据才可以被wireshark抓到,本机回环的数据不会被抓到 实验内容: 使用nc命令…...

基于Java的车辆管理系统的设计与实现-计算机毕业设计源码41727
摘要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对车辆管理系统等问题,对车辆管理…...
在软件开发中低耦合和高内聚是什么,如何实现,请看文章
软件开发中,“低耦合”和“高内聚”是设计原则,用于提高系统的可维护性、可扩展性和可重用性。下面我会详细解释这两个概念及其带来的好处和规避的坏处。 低耦合(Low Coupling) 定义: 低耦合指的是模块之间的依赖关系…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...