谷歌新安装包文件形式 .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>
<![CDATA[
        // for GooglePAD (use upfront for main.obb.png)
        assetPackManager = AssetPackManagerFactory.getInstance(this);

表示追加字符串到 gradle\app\src\main\java\com\epicgames\ue4\GameActivity.java 中。GameActivity.java是运行时的逻辑。也许你会好奇,我如何得知它们会拷贝给 GameActivity.java。我的做法是在整个Gradle工程中搜索  <![CDATA[  后面的字符串。

settings.gradle

经过Package执行后,settings.gradle的内容成为了:

rootProject.name='app'
include ':app'
include ':downloader_library'
include ':GCloud'
include ':GCloudCore'
include ':permission_library'
include ':PluginCrosCurl'
include ':TDM'
include ':TssSDK'
// generate mainobb assetpack
if (OBB_FILECOUNT.toInteger() > 0) {File obbfile = new File(OBB_FILE0)if (obbfile.exists()) {println 'Creating install-time assetpack for GooglePAD: assetpacks/install-time/obbassets'file("assetpacks/install-time/obbassets/src/main/assets").mkdirs()def assetBuildGradle = """apply plugin: 'com.android.asset-pack'assetPack {packName = "obbassets"dynamicDelivery {deliveryType = "install-time"instantDeliveryType = "install-time"}
}"""def assetBuildGradleFile = new File("assetpacks/install-time/obbassets/build.gradle")assetBuildGradleFile.write(assetBuildGradle)def destobbfile = new File("assetpacks/install-time/obbassets/src/main/assets/main.obb.png")if (destobbfile.exists()) {destobbfile.delete()}def srcobbStream = obbfile.newDataInputStream()def dstobbStream = destobbfile.newDataOutputStream()dstobbStream << srcobbStreamsrcobbStream.close()dstobbStream.close()}
}// add the assetpacks
def assetpacksDir = new File("assetpacks/install-time")
if (assetpacksDir.exists()) assetpacksDir.eachDir {println ':assetpacks:install-time:' + it.nameinclude ':assetpacks:install-time:' + it.name
}
assetpacksDir = new File("assetpacks/fast-follow")
if (assetpacksDir.exists()) assetpacksDir.eachDir {println ':assetpacks:fast-follow:' + it.nameinclude ':assetpacks:fast-follow:' + it.name
}
assetpacksDir = new File("assetpacks/on-demand")
if (assetpacksDir.exists()) assetpacksDir.eachDir {println ':assetpacks:on-demand:' + it.nameinclude ':assetpacks:on-demand:' + it.name
}

在这其中,我们看到特定的文件夹被设置成了开头我们说的“install-time”等拉取方式。

未完。

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

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

相关文章

OpenCV视觉分析之运动分析(2)背景减除类:BackgroundSubtractorKNN的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 K-最近邻&#xff08;K-nearest neighbours, KNN&#xff09;基于的背景/前景分割算法。 该类实现了如 319中所述的 K-最近邻背景减除。如果前景…

Zypher Network Layer3 主网上线,“宝藏方舟”活动是亮点

前言 随着 Zytron Layer3 主网的上线&#xff0c;Zypher Network联合Linea共同推出了“宝藏方舟”活动&#xff0c;用户可通过参与活动&#xff0c;获得包括代币、积分、SBT等系列奖励。 Zypher Network 是一个以ZK方案为核心的游戏底层堆栈&#xff0c;其提供了一个具备主权…

C++20中头文件span的使用

<span>是C20中新增加的头文件&#xff0c;此头文件是containers库的一部分。包括&#xff1a; 1.模板类std::span&#xff1a;连续对象序列的非拥有视图(view)。std::span可以具有static extent&#xff0c;在这种情况下&#xff0c;序列中的元素数量在编译时已知并以typ…

探寻医疗行业人力资源管理系统优选方案

医疗机构管理日益重要&#xff0c;ZohoPeople HRMS助力医疗行业优化人力管理&#xff0c;提升效率。其涵盖智能排班、培训发展、合规保障、绩效管理等功能&#xff0c;支持全球化及远程协作&#xff0c;是医疗行业人力资源管理的有效工具。 一、医疗行业人力资源管理的复杂性 …

基于SpringBoot+Vue+uniapp微信小程序的社区门诊管理系统的详细设计和实现(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

15.正则化——防止过拟合的有效手段

引言 在人工智能(AI)领域&#xff0c;尤其是在机器学习和深度学习中&#xff0c;正则化(regularization)具有非常重要的地位。它不仅是训练模型过程中不可或缺的一部分&#xff0c;也是提高模型性能的关键因素之一。此外&#xff0c;正则化还可以提升模型的泛化能力&#xff0…

产品如何实现3D展示?具体步骤如下

产品实现3D展示主要依赖于先进的3D建模与展示技术。以下是产品实现3D展示的具体步骤和方法&#xff1a; 一、3D建模 使用专业的3D建模软件&#xff0c;如Blender、Maya、3ds Max等&#xff0c;这些软件提供了丰富的建模工具和材质编辑器&#xff0c;能够创建出高精度的3D模型…

Flutter 12 实现双击屏幕显示点赞爱心多种动画(AnimationIcon)效果

本文主要是使用Flutter封装一个双击屏幕显示点赞爱心UI效果&#xff0c;并实现了爱心Icon 透明度、缩放、旋转、渐变等动画效果。 实现效果&#xff1a; 实现逻辑&#xff1a; 1、封装FavoriteGesture&#xff08;爱心手势&#xff09;实现双击屏幕显示爱心Icon&#xff1b; …

文件摆渡系统选型指南:如何找到最适合您的数据安全解决方案?

在当今数字化时代&#xff0c;数据的安全传输与共享已成为企业运营中不可或缺的一环。文件摆渡系统&#xff0c;作为实现数据在不同安全域之间高效、安全传输的重要工具&#xff0c;其选型直接关系到企业数据的安全性与业务效率。本文将为您详细介绍如何挑选最适合您企业的文件…

视频网站系统的设计与实现(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;视频网站系统 摘 要 使用旧方法对视频信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在视频信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#…

为什么k8s不支持docker-kubernetes

为什么Kubernetes不再支持Docker&#xff1f; 在Kubernetes 1.20版本之后&#xff0c;Kubernetes宣布逐步停止对Docker作为容器运行时的支持。这一改变在容器管理领域引起了广泛关注。许多人不禁疑惑&#xff1a;Kubernetes与Docker一向密切合作&#xff0c;为何会做出这样的决…

骨传导耳机哪个品牌好?2024年五大热门精选骨传导耳机推荐

在当今快节奏的生活中&#xff0c;人们对于个人音频设备的需求不仅限于优质的音质体验&#xff0c;还越来越注重健康与舒适。骨传导耳机作为一种新兴的技术产品&#xff0c;以其独特的听觉传递方式——通过颞骨而非耳道传递声音——赢得了众多用户的青睐。这种技术不仅可以提供…

Webserver(1)Linux开发环境搭建

目录 配置软件虚拟机中安装ubuntu安装ubuntu18的操作系统 安装VM tools安装XshellVscode远程连接到虚拟机 配置软件 VMwareVScodeg安装ubuntu 18.04.iso 或者镜像版本 XShellXFTP 虚拟机中安装ubuntu 安装ubuntu18的操作系统 开启虚拟机 选择中文简体 安装VM tools 打开v…

炸了!改进Transformer!Transformer-BiGRU多变量回归预测(Matlab)

炸了&#xff01;改进Transformer&#xff01;Transformer-BiGRU多变量回归预测&#xff08;Matlab&#xff09; 目录 炸了&#xff01;改进Transformer&#xff01;Transformer-BiGRU多变量回归预测&#xff08;Matlab&#xff09;分类效果基本介绍程序设计参考资料 分类效果 …

python离线安装依赖

以pymsql依赖为例操作如下: Python Package Index&#xff08;PyPI&#xff09;的官方网址是&#xff1a; PyPI The Python Package Index 在这个网站上&#xff0c;你可以搜索、浏览和下载Python包。 tar -xvzf pymysql2-1.3.3.tar.gz cd pymysql2-1.3.3 python setup.p…

基于SSM机场网上订票系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;机票信息管理&#xff0c;订单信息管理&#xff0c;机场广告管理&#xff0c;系统管理 前台账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;机票信息&#xf…

CRMEB标准版Mysql修改sql_mode

数据库配置 1.宝塔控制面板-软件商店-MySql-设置 2.点击配置修改&#xff0c;查找sql-mode或sql_mode &#xff08;可使用CtrlF快捷查找&#xff09; 3.复制 NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION 然后替换粘贴&#xff0c;保存 注&#xff1a;MySQL8.0版本的 第三步用…

CRM在企业协同中发挥了哪些作用?

在当今快速变化的商业环境中&#xff0c;企业竞争力的核心已逐渐从单一的产品或服务优势&#xff0c;转向以客户为中心的综合能力构建。客户关系管理&#xff08;CRM&#xff09;系统作为这一转型的关键驱动力&#xff0c;正以前所未有的力度打破企业内部部门间的传统壁垒&…

MusePose模型部署指南

一、模型介绍 MusePose是一个基于扩散和姿势引导的虚拟人视频生成框架。 主要贡献可以概括如下&#xff1a; 发布的模型能够根据给定的姿势序列&#xff0c;生成参考图中人物的舞蹈视频&#xff0c;生成的结果质量超越了同一主题中几乎所有当前开源的模型。发布该 pose alig…

Python CGI编程-get、post-复选框、单选框、文本框、下拉列表

GET方法&#xff1a;将网址中的两个参数读取出来显示到浏览器中 url示例&#xff1a;表单示例&#xff1a;服务器脚本hello.py文件是放在/Library/WebServer/CGI-Executables&#xff0c;hello.py同样也需要通过chmod修改权限到755. 放在/Library/WebServer/Documents中的是get…