Android App Bundle 自动打包原理

2023-05-16

Google推出Android App Bundle 已经有一段时间了。 根据Google的政策说明 ,预计2021年8月之后,新发布的应用都必须使用Android App Bundle(aab)来上架Google Play Store了。

对于Android App Bundle的原理,Google官方文档已经有了很详细的介绍, 想了解的同学建议直接阅读Google的官方文档。

如果你是使用Android Studio打包,那么你直接在Android Studio中选择构建App Bundle即可将应用打包成aab了。

这篇文章,我们主要介绍如何在U8SDK聚合打包工具中生成aab格式的文件(新版本的U8SDK打包工具已经支持aab打包了)。

一、文件格式介绍

aab——Android App Bundle格式文件,也就是一个有固定目录格式的压缩文件。

我们以一个demo.aab为例,将其解压,我们看下其中的目录结构:

--BundleConfig.pb  : 打包bundle的时候,自动生成
--base  : base目录
------assets:         对应apk的assets目录
------dex:             原apk中classes.dex,classes2.dex...都放这里
------lib: 原apk中lib目录都放这里
------manifest: 原apk的AndroidManifest.xml放这里,需要是编译后的AndroidManifest.xml
------res:apk中的资源放这里,需要是编译后的资源
------root: apk中相对于根目录的其他资源文件
------resources.pb:编译资源的时候会生成的
------assets.pb:编译bundle的时候会生成的
------native.pb: 编译bundle的时候会生成的

二、如何打包生成aab

了解过U8SDK打包原理的同学应该知道,在U8SDK打包工具中,我们将母包apk反编译,然后合并进去对应的渠道SDK的代码、资源、so文件等,然后再将合并后的内容回编译成最终的apk。

在U8SDK打包工程中直接打出aab的原理其实就一句话——要生成aab,我们只需要将合并后的目录(decompile目录), 转换为上面aab打包需要的资源目录格式即可。

所以整个适配过程如下(这里不贴python脚本,只说原理过程~😄):

1、编译资源

首先,我们需要将decompile目录下的res进行编译。 编译资源我们需要使用aapt2,并且需要将资源编译生成protobuf格式的版本。


使用aapt2编译资源,我们需要先执行compile命令,再执行link命令:

aapt2 compile --dir ./res -o ./compiled_resources

aapt2 link --proto-format -o baseapk -I ../android.jar --manifest .\AndroidManifest.xml -R .\compiled_resources\*.flat --auto-add-overlay

执行上面的命令之后, 我们就在decompile目录下,生成了base.apk。 我们需要将这个apk解压。 
解压后里面的目录格式如下:

--res
--AndroidManifest.xml
--resouces.pb

我们就以这个目录作为base目录, 后面拷贝的资源都拷贝到这个目录里面来。 

按照上面的bundle目录结构,我们在这个目录下,新建一个manifest目录,然后我们将AndroidManifest.xml拷贝到manifest子目录下。

现在base的目录结构如下:


--res
--manifest
------AndroidManfiest.xml
--resources.pb

2、编译dex

我们打包过程中合并后的代码格式是smali格式, 经过u8sdk打包脚本的自动dex拆分后,在decompile目录下的代码目录结构是smali、smali_classes2、smali_classes3...

我们需要将这些smali目录编译生成对应的classes.dex、classes2.dex、classes3.dex...

我们使用smali.jar进行这步操作,smali.jar可以从github上下载,或者加U8SDK技术交流裙(扣:1055996444)索要。

对所有smali目录执行如下命令,就可以将dex生成到base目录下了
 

java -jar smali.jar assemble -o ./base/dex/classes.dex ./smali

生成之后,base目录结构如下:

--res
--manifest
------AndroidManfiest.xml
--dex
------classes.dex
------classes2.dex
--resources.pb

3、拷贝其他资源

这一步就更简单了, 我们需要将decompile目录下其他对应目录中的内容,直接拷贝到base目录下对应的子目录中即可。 对应的拷贝目录关系如下:

decompile/assets ==>  base/assets
decompile/lib ==> base/lib
decompile/unknown ==> base/root

拷贝之后, 我们的base目录结构如下图:

--assets
--lib
--root
--res
--manifest
------AndroidManfiest.xml
--dex
------classes.dex
------classes2.dex
--resources.pb

4、编译bundle

打包生成aab文件,我们需要使用bundletool.jar,这个文件你可以Google官网或者github上下载,或者加U8SDK海外交流群(扣)索要。

上面的base目录结构已经准备好了,我们将这个目录压缩成base.zip,接下来我们就可以使用bundletool.jar生成aab文件了

java -jar bundletool.jar build-bundle --modules= ./base.zip --output=./output.aab

跟着流程到这里,我们的output.aab就是一个纯正的aab文件啦~

5、签名bundle

如果你需要将bundle发布到Google Play平台,还需要对你的aab文件进行签名, 只能使用jarsigner进行签名哦,不可以使用apksigner。

jarsigner -digestalg SHA1 -sigalg SHA1withRSA -keystore test.keystore -storepass 123456 -keypass 123456 ./output.aab test


三、如何测试生成的aab

1、生成apks

打出了bundle之后, 如果我们本地想测试这个bundle的功能是否正常怎么办呢?我们依然使用bundletool.jar来完成。

我们用bundletool.jar将我们的bundle编译生成apks,注意不是apk,是apks。

java -jar bundletool.jar build-apks --bundle=./output.aab --output=./output.apks

这样就生成了apks文件,apks文件你可以解压看下,里面是一群根据特性拆分后的apk文件。

2、部署到设备

然后,我们可以将apks部署到设备上,进行安装测试。 我们可以将设备通过USB连上电脑,然后依然使用bundletool命令:

java -jar bundletool.jar install-apks --apks=./output.apks

这样就完成了bundle的打包以及本地测试了。 如果你对这块感兴趣或者还有疑问,可以加入U8SDK的海外交流裙(扣:1055996444)哦。


 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android App Bundle 自动打包原理 的相关文章

  • getItem 与 getItemAtPosition

    有两种方法可以获取列表视图中的选定项目 list getAdapter getItem position list getItemAtPosition position 我的问题是 哪一种是首选的做法 我见过人们同时使用这两种方法 您可以使
  • Android - 如何一次只允许播放一个 MediaPlayer 实例?

    我正在尝试创建一个简单的 Sound board Android 应用程序 使用 ListView 项目作为按钮 顺便说一句 我是一个新手程序员 我的想法是 我按下一个按钮 就会播放一个特定的声音文件 如果我在播放声音时按下任何按钮 它应该
  • 如何更新 Firebase 中的节点密钥?

    如何重命名14 04 2017 node 没有用于重命名节点的 API 您必须获取节点的值 使用新名称将其保存到数据库并删除旧节点
  • Firebase Analytics 禁用受众国家/地区跟踪

    我正在开发一个严格不允许位置跟踪的应用程序 我想使用 Firebase Analytic 的其他功能 例如 PageTransitions 和 Crashalitics 但如果我无法禁用受众位置跟踪 我就无法使用其中任何功能 这是我在 An
  • 在自定义对象中创建时粘性服务不会重新启动

    我有一个具有绑定服务的单例对象 我希望它重新启动 当我从启动器启动应用程序时 单例对象将初始化并绑定到这个现有的服务实例 以下是在单例中创建和绑定服务的代码 public class MyState private static MySta
  • Android:“dp”到“px”转换?

    我正在读这篇文章 http developer android com guide practices screens support html http developer android com guide practices scre
  • KitKat(及更低版本)设备上的 Android Material Design

    我将在我们学校开发一个 Android 应用程序作为一个项目 我想使用 Google 的新 Material Design 但我知道它仅适用于 Android L 设备 Jack Underwood 最近发布了名为 Today Calend
  • RxJava、Proguard 和 sun.misc.Unsafe

    我有以下问题RxJava 1 1 0 使用时Proguard 我没有更改 RxJava 版本或其 pro文件 但更新后OkHttp我无法编译使用Proguard因为我有关于sun misc Unsafe不在场 rxJava pro keep
  • 设置从 Facebook 登录获取用户电子邮件 ID 的权限

    我在用着Facebook 3 0 SDK对于安卓 我必须实施Facebook登录 我正在访问用户的基本信息 例如姓名 用户 ID 但我也想访问用户的电子邮件 我浏览了很多博客和论坛 但不知道该怎么做 我正在使用我自己的 android 按钮
  • 已经使用 AsyncTask doInBackground 但新数据未显示

    我使用 AsyncTask 创建一个聊天室来接收消息 因此它总是检查即将到来的消息并将其显示给客户端 但代码似乎无法按我希望的方式工作 在客户端只显示所有旧数据 新数据不显示 因为当我尝试从服务器发送消息时 新数据没有显示在客户端中 我对这
  • TextView 之间有分隔线

    我正在尝试在 android studio 中创建以下布局 因为我对 android 东西还很陌生 所以我第一次尝试使用 LinearLayout 并认为这可能无法实现 现在我正在尝试使用RelativeLayout 我已经用颜色创建了这个
  • 更新到材质 1.2.0 后,材质按钮上缺少圆角半径属性

    这是我的材质按钮代码
  • OnClick 事件中的 finish() 如何工作?

    我有一个Activity一键退出Activity 通过layout xml我必须设置OnClick事件至cmd exit调用 this finish 效果很好 public void cmd exit View editLayout thi
  • 请求位置更新参数

    这就是 requestLocationUpdates 的样子 我使用它的方式 requestLocationUpdates String provider long minTime float minDistance LocationLis
  • 使用 Matrix.setPolyToPoly 选择位图上具有 4 个点的区域

    我正在 Android 上使用位图 在使用 4 个点选择位图上的区域时遇到问题 并非所有 4 点组都适合我 在某些情况下 结果只是一个空白位图 而不是裁剪后的位图 如图所示 并且 logcat 中没有任何错误 甚至是内存错误 这是我用来进行
  • 材质设计图标颜色

    应该是哪种颜色 暗 材质图标 在官方文档上 https www google com design spec style icons html icons system icons https www google com design s
  • Android 如何聚焦当前位置

    您好 我有一个 Android 应用程序 可以在谷歌地图上找到您的位置 但是当我启动该应用程序时 它从非洲开始 而不是在我当前的城市 国家 位置等 我已经在developer android com上检查了信息与位置问题有关 但问题仍然存在
  • 如何将图像从 Android 应用程序上传到网络服务器的特定文件夹中

    如何将图像从 android 移动到 Web 服务器上的指定文件夹 这是我的安卓代码 package com example bitmaptest import java io ByteArrayOutputStream import ja
  • 无法运行我的应用程序,要求选择 Android SDK

    今天我已经安装了Android Studio 金丝雀 1 现在我无法运行我的应用程序 将出现以下对话框 我已经通过 文件 gt 项目结构 gt Android SDK 位置 设置了正确的 SDK 位置 期待您的帮助来解决这个问题 警告对话框
  • 如何删除因 Google Fitness API 7.5.0 添加的权限

    将我的 play services fitness api 从 7 0 0 更新到 7 5 0 后 我注意到当我将新版本上传到 PlayStore 时 它 告诉我正在添加一个新权限和 2 个新功能 我没有这样做 有没有搞错 在做了一些研究来

随机推荐