随着移动应用的不断发展,开发者和用户都在寻求更高效、便捷的解决方案。在安卓平台上,传统的APK(Android Package)文件一直是发布应用的主要方式,但随着设备种类的增加和应用包体积问题的日益突出,“Android App Bundles(AAB)”应运而生,成为了安卓应用发布的新标准。
我将深入解析Android App Bundles(AAB)的概念、优势、如何转化为AAB以及开发者在使用过程中需要注意的关键问题。
AAB官网:https://developer.android.com/guide/app-bundle
一、什么是Android App Bundles(AAB)?
Android App Bundles(AAB)是一种新的应用发布格式,它是Google为了解决APK格式存在的问题而推出的一种解决方案。与传统的APK文件不同,AAB不是一个包含应用所有资源的单一文件,而是一个包含所有代码、资源和配置的容器。这个容器通过Google Play的**动态交付(Dynamic Delivery)**技术,可以根据用户设备的特性(如屏幕密度、CPU架构、语言设置等)生成最适合该设备的APK,从而提供更小、更高效的应用包。
换句话说,AAB让开发者上传一个统一的应用包,然后由Google Play根据设备需求动态生成多个个性化的APK文件,最终分发给用户。这样不仅可以减小应用体积,还能让用户下载到最适合自己设备的APK,提升用户体验。
如下图为ABB的结构:
图1-1
图解:
1.Android App Bundle (*.aab): 这是主文件,表示这是一个Android应用包,使用AAB格式,这是Google Play用于发布应用的格式。
2.BUNDLE-METADATA/: 这个目录包含与应用包相关的元数据。BundleConfig.pb: 这是一个协议缓冲区文件,用于存储关于这个应用包的配置信息。
3.Base Module (base/): 这是应用的基础模块,包含了所有核心功能和资源。assets.pb, resources.pb, textures/: 这些是协议缓冲区文件和纹理资源,用于存储应用的资产和资源。res/: 资源文件夹,包含各种分辨率的drawable资源,如hdpi、xhdpi等,以及声音、材料、着色器等。manifest/: AndroidManifest.xml文件所在目录,定义了应用的基本属性和组件。licenses.txt: 许可证文件。dex/: Dalvik Executable文件,包含编译后的Java字节码。values/: 字符串和其他资源值的XML文件,包括不同语言版本(如en, fr)。
4.Dynamic Feature 1 (feature1/) 和 Dynamic Feature 2 (feature2/): 这些是动态特性模块,可以按需下载,以减少初始安装大小或提供可选功能。assets.pb, classes.dex, lib/: 类似于基础模块,但特定于该特性。values-fr/: 特定语言的资源值。root/: 根目录,可能包含特定于该特性的全局资源或文件。layout/, xml/: 布局和XML配置文件。armeabi, x86, arm64-v8a/: 针对不同CPU架构的原生库文件。
二、AAB与APK的区别
为了更好地理解AAB的优势,我们首先需要了解它与传统APK文件的不同之处。
-
APK:一个固定的安装包
传统的APK文件包含应用的所有资源和代码,无论用户设备的实际需求如何。即便某些设备不需要特定的资源(如高清图像、语言包等),这些资源依然会被包含在APK中,导致APK体积膨胀。比如,一个包含多种语言资源和不同分辨率图片的APK文件,可能会包含许多设备不需要的内容。 -
AAB:一个包含资源和代码的容器
与APK不同,AAB只是一个容器,包含了应用的所有资源和代码,但并不包含具体的APK文件。Google Play在收到AAB后,会根据用户设备的需求动态生成针对性APK。这样,最终用户下载的APK将只有其设备所需的资源和代码,避免了冗余的内容。
如下图:
图2-1
注:Dynamic Delivery:动态交付是一种通过将应用拆分成多个小模块,并根据用户需求进行动态安装和更新的技术方案。
举个例子:
假设我们开发了一个游戏应用,该应用支持英语、中文、法语等多种语言,并且为每种语言提供了对应的资源文件。传统的APK格式需要将所有语言的资源打包到同一个APK中,但通过AAB格式,Google Play会根据用户设备的语言设置,仅下载所需的语言包,从而减少了不必要的资源。
大家或许会有疑问为什么同一个app用AAB打包的文件会比APK打包的文件大,这又是为什么呢?
原因如下,主要涉及到两者的结构和工作方式:
- 包含了多个构建变体
.aab 包含了所有的应用资源、代码和其他构建变体(例如不同的架构、屏幕尺寸、语言等)。这样,Google Play 可以根据设备的配置(如 CPU 架构、屏幕密度等)来生成一个优化后的 APK(也称为“分发 APK”)。
而 .apk 文件是一个完整的、针对特定设备或配置打包的文件。因此,它只包含最终用户设备所需的资源和代码。
- 包含所有资源文件
Android App Bundle 中会包含针对所有设备配置的资源(例如不同 DPI 的图像、多个架构的.so库等),它会将这些资源以较为通用的方式打包成一个文件。虽然最终用户设备上只会下载和安装其需要的资源,但在打包过程中,所有资源都会包含在内。
.apk 文件只会包含与目标设备相关的资源文件,不会包含其他不必要的资源,因此通常比 .aab 文件小。
- 使用了动态交付和模块化
Android App Bundle 支持动态交付(Dynamic Delivery),这意味着可以将应用拆分成多个模块(例如功能模块、语言模块等),这些模块可以在用户安装应用后按需下载。虽然这些模块没有立即打包进 .aab 文件中,但 .aab 文件需要包含所有模块的描述和其他信息,这会导致其整体大小增大。
而 .apk 文件是一个单一的打包文件,其中包含了应用的所有代码和资源。
三、AAB的优势
随着安卓应用的不断发展,AAB的优势逐渐显现,尤其在以下几个方面表现突出。
-
显著减少应用体积
一个传统的APK文件包含了所有设备资源,无论设备是否需要这些资源,这会导致APK体积不必要地庞大。通过AAB,Google Play会根据设备的实际配置(如屏幕分辨率、CPU架构、语言设置等)生成最合适的APK,这样用户只会下载到与自己设备匹配的资源,显著减少了安装包的体积。对于用户来说,这意味着更快的下载速度和更小的存储占用。 -
提升发布效率
在传统的APK发布方式下,开发者需要针对不同的设备类型和配置生成多个APK文件,这既麻烦又容易出错。而AAB则简化了这一过程。开发者只需要上传一个统一的AAB文件,Google Play会自动处理设备差异,生成适合的APK。这不仅提高了发布效率,还减少了发布过程中的出错率。 -
更好的支持多语言和多设备适配
AAB的动态交付机制使得开发者可以更容易地处理多语言和多设备适配的问题。传统的APK文件可能包含多个语言包、不同分辨率的图片和针对不同CPU架构的代码,导致APK体积庞大。而使用AAB后,Google Play会根据设备的语言、屏幕分辨率和CPU架构自动生成最适合的APK,只包含用户设备所需的资源和代码。 -
支持动态功能模块
AAB还支持Play Feature Delivery功能,允许开发者将应用功能模块化,按需分发。例如,某些功能或内容(如高级功能、DLC、游戏中的关卡等)可以在用户需要时动态下载,而不是在应用初次安装时就捆绑在APK内。这样可以进一步减少应用的安装包体积,同时为用户提供更灵活的体验。
Play Feature Delivery介绍如下:
1.Play Feature Delivery是一种由Google Play提供的高级功能,允许开发者在Android应用中使用模块化和动态交付技术。
2.Play Feature Delivery是Android App Bundle的一部分,它支持安装时交付、按条件交付和按需交付三种模式 这种技术通过将应用的功能拆分成多个模块,并根据设备特性或用户需求动态下载和安装特定模块,从而优化了应用的分发和用户体验。
3.Play Feature Delivery的主要优势是减少初始下载大小,通过仅下载用户当前需要的功能模块,减少了应用的初始下载大小,加快了安装速度,并可能提高用户的安装意愿 。他还提升用户体验,用户可以根据自己的需求选择安装特定的功能模块,避免了不必要的资源浪费,同时也提升了应用的响应速度和性能,他还有更加灵活更新,开发者可以独立更新各个功能模块,而不需要重新发布整个应用,这使得应用的维护和更新更加灵活和高效
4.Play Feature Delivery特别适用于那些具有大量可选功能或大型资源的应用,如游戏、社交媒体应用或企业级应用。通过使用这种技术,开发者可以为用户提供更加个性化和高效的应用体验
- 优化应用的更新和扩展
使用AAB格式发布的应用支持Play Asset Delivery,可以将大型资源文件(如游戏中的图像、音频文件、视频等)按需交付,避免了资源的重复下载。开发者可以通过分段传输资源来优化应用的安装和更新体验。对于大体积的游戏或多媒体应用,Play Asset Delivery提供了一个有效的解决方案。
Play Asset Delivery介绍如下:
1.Play Asset Delivery是一种由Google Play提供的高级功能,允许开发者在Android应用中使用动态资源交付技术。
2.Play Asset Delivery (PAD) 是Android App Bundle的一部分,它支持安装时交付、按条件交付和按需交付三种模式 这种技术通过将应用的资源拆分成多个模块,并根据设备特性或用户需求动态下载和安装特定模块,从而优化了应用的分发和用户体验。
四、如何将应用转换为AAB?
将现有的应用转换为AAB其实并不复杂。以下是一步步的操作指南:
- 更新Android Studio
首先,确保你的开发环境是最新版本的Android Studio,因为AAB的支持从Android Studio 3.2版本开始。如果还没有更新,可以前往Android Studio官网下载最新版本。
官网连接:https://developer.android.google.cn/?hl=zh-cn
- 修改build.gradle文件
打开项目中的build.gradle文件,确保配置了正确的构建设置。需要检查以下几个方面:
minSdkVersion 和 targetSdkVersion:确保它们符合Google Play的最新要求。
buildTypes:配置不同构建类型的签名设置。
build.gradle配置如下:
android { compileSdkVersion 33 defaultConfig { applicationId "com.example.myapp" minSdkVersion 21 targetSdkVersion 33 versionCode 1 versionName
"1.0" } }
- 生成AAB文件并上传
在Android Studio中,点击菜单打开Build-Generate Singned Bundle/APK,系统会自动生成AAB格式的应用包。
图片4-1
点击Next(下一步)
图片4-2
选择签名,并勾选Export encrypted key for enrolling published apps in Google Play App Signing,该导出的私钥文件上传到后台时会用到。
图片4-3
选择打包的类型realse,点击Finish
图片4-4
打包完成会在release目录下看到ABB文件,上传后台即可
图片4-5
上传后,提示需要上传密钥选择从Android Studio导出并上传密钥
图片4-6
点击上传私钥,选择刚才导出的.pepk格式的文件
图片4-7
这样就可以了
图片4-8
bug1:1.如果上传谷歌时提示超过150M ,则按照如下方法来解决:
原因如下:AAB里base文件夹太大了 导致他用base文件夹来做基础apk就会很大(150M以内)这里不是指AAB文件太大
解决方法:把base里的资源拆到其他的module里作为install-pak (即goggle推出的PAD 资源包解决方案)
(1)对你的android studio 工程 右键 新建一个module
图4-9
(2)选择 android library 点击next 创建
图4-10
(3)重命名Module 为install-time-asset_pack
图4-11
(4) 打开 build.gradle文件,修改如下内容:(copy就可以)
apply plugin: ‘com.android.asset-pack’ assetPack{ packName = “install_time_asset_pack” dynamicDelivery{ deliveryType = “install-time” } }
图4-12
(5)打开setting.gradle,添加如下内容:
图4-13
(6) 打开build.gradle,添加如下内容:
图4-14
(7)将目录里的文件资源复制到 install-time-asset_pack 对应asset 目录里。
图4-15
(8)打开gradle.properities,填加如下内容:
android.useAndroidX=true
android.enableJetifier=true
注:这里是为了支持Androidx
完整注释后按照步骤重新导出AAB文件即可
bug2:2.出现了The signing configuration is invalid或Could not read key from keystore
原因如下:
签名配置问题:
1.签名配置不完整或错误,在 build.gradle 中的 signingConfigs 配置部分没有正确设置签名密钥的路径、别名、密码等信息。
2.Keystore 文件路径问题:如果 keystore 文件路径不正确(例如,路径中包含空格、拼写错误或使用了相对路径而不是绝对路径),则无法读取签名文件。
3.密码错误:如果 keyPassword 或 storePassword 配置错误,构建时将无法读取 keystore,导致签名失败。
4.在 CI/CD 环境中的问题:在 CI/CD 环境中,签名密钥通常会被存储为环境变量,路径、密码等信息可能没有正确配置,导致构建时无法读取到签名密钥。
5.遗失 Keystore 文件或密钥信息:如果你遗失了 keystore 文件或忘记了 keystore 密码、别名等信息,你将无法进行签名,无法发布 AAB。
解决方法:
1.检查 build.gradle 配置
在 app/build.gradle 文件中确保签名配置部分正确:
android { signingConfigs
{ release
{ // keystore 配置 keyAlias '<your-key-alias>' keyPassword '<your-key-password>' storeFile file('<your-keystore-path>')
// 确保路径正确 storePassword '<your-store-password>' } }
buildTypes { release { signingConfig signingConfigs.release }
} }
keyAlias:是 keystore 中的密钥别名。
keyPassword:是与密钥别名对应的密码。
storeFile:是 keystore 文件的路径,通常是 .jks 文件。
storePassword:是 keystore 文件的密码。
确保所有路径都使用绝对路径,特别是 storeFile,如果使用相对路径,可能导致构建失败。示例:
storeFile file(‘/Users/username/keystore/my-release-key.jks’)
.2.确保 keystore 文件存在且路径正确
检查 keystore 文件是否存在,并确认路径没有错误。如果路径包含空格或特殊字符,可能导致问题。
如果路径比较复杂,建议使用绝对路径,避免相对路径引起的问题。
在命令行使用 ls 命令或通过文件浏览器确认 keystore 文件的位置。
-
确保密码正确(一定要确认,很重要)
-
使用环境变量(适用于 CI/CD)
在 CI/CD 环境中,通常不建议将敏感信息直接写入代码中。需要使用环境变量来存储签名相关的密钥和密码。首先在 CI 系统中配置这些环境变量:
export KEYSTORE_PATH=/path/to/your/keystore.jks export KEY_ALIAS=your_key_alias export KEY_PASSWORD=your_key_password export STORE_PASSWORD=your_store_password
然后在 build.gradle 中引用这些环境变量:
android {
signingConfigs
{ release
{ keyAlias System.getenv("KEY_ALIAS") keyPassword System.getenv("KEY_PASSWORD") storeFile file(System.getenv("KEYSTORE_PATH")) storePassword System.getenv("STORE_PASSWORD")
}
}
buildTypes {
release
{ signingConfig signingConfigs.release
}
}
}
5.在 Android Studio 中验证签名配置
在 Android Studio 中,你可以通过以下步骤验证签名配置:
打开 Build 菜单,选择 Generate Signed Bundle / APK。
选择 Android App Bundle 并点击 Next。
在签名配置页面中,检查所选的 keystore 和密钥别名,确保与 build.gradle 配置一致。
如果配置正确,Android Studio 会自动加载并显示签名密钥信息。
7.使用命令行验证签名配置
使用命令行来构建并验证签名配置:
./gradlew assembleRelease
8.检查 Gradle 缓存问题
如果曾经在其他项目中使用过相同的 keystore,并且存在 Gradle 缓存问题,会导致签名配置失效。尝试使用以下命令清理 Gradle 缓存:
./gradlew clean
五、unity项目打包AAB
1.将unity项目打包
在Unity的Build Settings中,当您切换到安卓平台后,需要进一步配置一些与打包相关的设置。为此,请首先点击Player Settings选项,这将带您进入一个包含多个子菜单的界面。在这个界面里,选择“player”下的“Other settings”,这里汇集了一系列针对Android平台打包过程中可能需要调整的关键参数和选项。特别需要注意的是,在图形API的选择上(即Graphics APIs部分),建议移除Vulkan的支持。尽管Vulkan作为一种现代高效的跨平台图形接口标准,在许多高端设备上能够提供出色的性能表现;然而,考虑到不同型号、品牌以及操作系统版本之间的差异性,并非所有Android设备都完全支持或优化了对Vulkan的支持。因此,为了保证应用程序能够在更广泛的设备上运行而不受限制,暂时禁用该功能是一个较为稳妥的做法。通过这种方式,可以有效避免因兼容性问题导致的游戏崩溃或者画面显示异常等情况发生,从而提升用户体验。
图5-1
在Player Settings的“Identification”中:
“Override Default”选项,勾选这个复选框后,您可以自定义应用程序的包名(Package Name)。包名是Android系统中用于唯一标识应用程序的一个字符串,它通常遵循反向域名命名规则,例如com.example.myapp。
“Minimum API Level”是一个非常重要的设置项。这个选项指定了应用程序支持的最低Android API级别。API级别是Android操作系统的一个版本标识,每个新版本的Android都会对应一个特定的API级别。例如,API级别21对应于Android 5.0 Lollipop。设置这个值可以确保您的应用不会在低于该API级别的设备上运行,从而避免因系统功能缺失或不兼容而导致的运行时错误。
在Unity中设置好这些参数后,它们会被写入到打包过程中生成的gradle.build文件中。具体来说,Minimum API Level的值会被用来设置gradle.build文件中的minSdkVersion属性。这意味着,如果在Unity中更改了这个值,那么在后续将Android工程导入到Android Studio进行进一步开发和构建时,需要确保这些设置保持一致,以避免出现兼容性问题。
图5-2
在Player Settings的“Configuration”中:
“Scripting Backend”选项,选择IL2CPP(Intermediate Language To C++)将Unity脚本代码转换为C++代码。这种转换使得应用程序能够以原生代码的形式运行,从而提高了性能和安全性。IL2CPP是Unity提供的一种脚本后端,它允许开发者利用C++的性能优势,同时保持使用C#进行开发的优势。
“Target Architectures”指定应用程序支持的目标CPU架构。在Android平台上,常见的架构版本包括ARMv7和ARM64。ARMv7是32位的架构,而ARM64是64位的架构。
最省事的方法是同时勾选ARMv7和ARM64。这样做的好处是,可以使应用能够在大多数现代Android设备上运行,无论是基于32位还是64位的处理器。
图5-3
返回到Build Settings界面。这是Unity中用于管理不同平台构建设置的地方,可以选择要构建的目标平台(Android)
勾选“Export Project”选项。告诉Unity,希望将当前的Unity项目导出为一个独立的Android Studio项目。这样就可以利用Android Studio来进行进一步的开发和调试。
点击“Build”按钮开始导出过程。Unity会处理所有的转换工作,包括将Unity的场景和资源转换为Android Studio项目所需的格式。这个过程可能需要一些时间,具体取决于项目的大小和复杂性。
图5-4
2.把unity的模组添加到Android Studio中
打开gradle.properties文件
添加如下变量:
unityStreamingAssets=/path/to/your/UnityProject/Assets/StreamingAssets
//这里根据unity项目中的streamingAssets的路径来修改
点击Import Module
图5-5
打开gradle.build文件
添加如下代码:
// 应用到所有子项目的配置
allprojects {
// 配置构建脚本的仓库和依赖项
buildscript {
repositories {
google() // Google 的 Maven 仓库
mavenCentral() // Maven Central 仓库
}
dependencies {
// Android Gradle 插件的类路径依赖
classpath 'com.android.tools.build:gradle:7.0.2' // 请根据需要更新版本号
}
}
// 配置项目的仓库
repositories {
google() // Google 的 Maven 仓库
mavenCentral() // Maven Central 仓库
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs" // 自定义本地库目录
}
}
}
// 定义一个清理任务,用于删除根项目的构建目录
task clean(type: Delete) {
delete rootProject.buildDir
}
在defaultConfig添加如下代码:
ndk {
abiFilters 'arm64-v8a'
}
打开settings.gradle文件
在dependencyResolutionManagement添加如下代码:
// 设置仓库模式为 FAIL_ON_PROJECT_REPOS
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
// 配置项目的仓库
repositories {
google() // Google 的 Maven 仓库
mavenCentral() // Maven Central 仓库
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs" // 自定义本地库目录
}
}
打开MainUnityActivity类
添加如下代码:
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取按钮实例
Button button = findViewById(R.id.button);
// 设置按钮的点击监听器
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建意图以启动新的活动
Intent intent = new Intent(MainActivity.this, MainUnityActivity.class);
startActivity(intent);
}
});
}
}
打开activity_main.xml
添加如下代码(一个button用于跳转):
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Unity Activity"/>
这样点击button按钮就会运行我们的unity文件了
3.打包.aab
与普通的项目同理(这里提供一个方便的打包方式)
1.在 Android Studio 中,点击 Build > Build Bundle(s) / APK(s)。
选择 Build Bundle,并开始构建。
生成 AAB 文件
2.构建过程完成后,Android Studio 会在 app/build/outputs/bundle/release/ 目录下生成 .aab 文件。文件名为 app-release.aab。
3.登录到 Google Play Console,选择unity应用,进入应用的发布页面。
4.在 Release management > App releases 中选择你的发布渠道(例如 Production)。
点击 Create Release,然后上传你从 Android Studio 生成的 .aab 文件。
5.根据 Google Play 的要求,填写版本号、更新说明等信息。
6.提交审核,等待 Google Play 的审核过程完成。
六、AAB的挑战与注意事项
尽管AAB有许多优势,但在实际使用过程中,开发者仍需注意以下几点:
-
兼容性问题
尽管AAB是Google推荐的发布格式,但对于其他应用市场或非Google Play渠道,APK格式仍然占据主流。因此,如果应用需要在多个平台发布,可能需要同时支持AAB和APK格式。 -
调试和测试
AAB的调试比传统APK稍微复杂一些,因为应用的最终APK由Google Play生成,开发者无法直接获取到每个设备的APK文件。因此,在开发阶段,开发者需要依赖Google Play Console的测试版发布功能进行调试和验证。 -
较大的应用体积
尽管AAB能够有效减少应用体积,但如果应用本身非常庞大(例如大型游戏或含有大量高清资源的应用),最终生成的APK仍然可能会较大。因此,合理的资源优化和模块化设计仍然非常重要。
七、AAB将如何影响安卓应用开发?
随着Google Play和AAB格式的逐步普及,开发者和用户的体验都将得到极大的提升。AAB不仅能减少应用体积,提高应用发布效率,还能为应用开发者提供更多灵活的功能模块化选择。这无疑是移动应用发布的未来趋势。
对于开发者来说,转向AAB格式是一项必须尽快适应的新挑战,虽然初期可能会遇到一些问题,但从长远来看,AAB将带来更加高效、灵活和用户友好的开发体验。
八、总结
Android App Bundles(AAB)作为安卓应用的新标准,正在逐步改变应用的发布和分发方式。它不仅能优化应用的体积和性能,还能带来更多灵活的功能分发方式。对于安卓开发者来说,理解并适应AAB的使用,将为你带来更加高效的开发流程和更好的用户体验。
原文链接:https://blog.youkuaiyun.com/2301_78445315/article/details/144203163
作者:贺宇博