本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Step 1 新建工程
在 Android Studio 中新建一个通用的 Android 工程
Step 2 修改 app’s build.gradle
文件
添加android.bundle
代码块,可以启用对屏幕分辨率、cpu 架构配置 APK 的支持
// 'app' module should have the application plugin.
apply plugin: 'com.android.application'
android {
defaultConfig {
...
// Specify the version code, only once for each new version of your app, for your App Bundle
// No need to have different version codes for different APKs generated.
// All split APKs will share the same version code once installed via Google Play.
versionCode 1
versionName "1.0"
...
}
// Add this block and enable/disable the parameters as follows
bundle {
density {
// Different APKs are generated for devices with different screen densities; true by default.
enableSplit true
}
abi {
// Different APKs are generated for devices with different CPU architectures; true by default.
enableSplit true
}
language {
// This is disabled so that the App Bundle does NOT split the APK for each language.
// We're gonna use the same APK for all languages.
enableSplit false
}
}
}
Step 3 新建 Feature Module
打开 File > New > New Module
窗口,选中 “Dynamic Feature
” Module,如下图所示
- 选中 app module 作为
Base application module
; Module name
命名为“feature1”;- 配置 feature1 module 的
Packge name
和Minimum API Level
; - 点击
Next
。
In the Configure On-Demand Options section:
- 设置
Module title
为 “Feature 1”; - 选择
Do not include module at install-time (on - demande only)
, 安装应用时不包含 featue module,后期用户手动请求时再安装 featue module; - 勾选
Fusing
(Android L 之前版本不支持 On-demand 安装,所以需要初次安装时就包含 feature module); - 点击
Finish
。 修改 feature1’smanifest.xml
文件, 并且为 feature1 添加一个空 Activity
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
package="com.elijah.feature1" >
<dist:module
dist:instant="false"
dist:title="@string/title_feature1" >
<dist:delivery>
<dist:on-demand />
</dist:delivery>
<dist:fusing dist:include="true" />
</dist:module>
<application>
<activity
android:name=".FeatureOneActivity"
android:exported="false" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.elijah.appbundledemo.MainActivity" />
</activity>
</application>
</manifest>
确认 feature1 的 build.gradle
文件有如下插件配置
plugins {
id 'com.android.dynamic-feature'
}
相同的步骤创建feature2
Step 4 检查 app’s build.gradle
文件
检查 android 模块下是否有 dynamicFeatures
配置
plugins {
id 'com.android.application'
}
android {
...
// This specifies the dynamic features.
dynamicFeatures = [':feature1', ':feature2']
}
Step 5 检查 feature1 和 feature2 的 build.gradle
文件
检查是否依赖 app module
plugins {
id 'com.android.dynamic-feature'
}
android {
...
}
dependencies {
...
// Add the app module as a dependency in the dynamic feature modules.
implementation project(':app')
...
}
Step 6 编辑 app module
app’s build.gradle
添加 google play core 依赖
implementation 'com.google.android.play:core:1.10.3'
MainAcitivy 编辑
public class MainActivity extends AppCompatActivity {
private SplitInstallManager splitInstallManager = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Instantiate an instance of SplitInstallManager for the dynamic feature module
splitInstallManager =
SplitInstallManagerFactory.create(getApplicationContext());
Button buttonFeatureOne = findViewById(R.id.btn_feature_one);
Button buttonFeatureTwo = findViewById(R.id.btn_feature_two);
buttonFeatureOne.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
loadFeatureOne();
}
});
buttonFeatureTwo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
loadFeatureTwo();
}
});
}
public void loadFeatureOne() {
// Builds a request to install the feature1 module
SplitInstallRequest request =
SplitInstallRequest
.newBuilder()
// You can download multiple on demand modules per
// request by invoking the following method for each
// module you want to install.
.addModule("feature1")
.build();
// Begin the installation of the feature1 module and handle success/failure
splitInstallManager
.startInstall(request)
.addOnSuccessListener(new OnSuccessListener<Integer>() {
@Override
public void onSuccess(Integer integer) {
// Module download successful
Intent intent = new Intent().setClassName(getPackageName(), "com.bapspatil.feature1.FeatureOneActivity");
startActivity(intent);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Module download failed; handle the error here
Toast.makeText(getApplicationContext(), "Couldn't download feature1: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
public void loadFeatureTwo() {
// Builds a request to install the feature1 module
SplitInstallRequest request =
SplitInstallRequest
.newBuilder()
// You can download multiple on demand modules per
// request by invoking the following method for each
// module you want to install.
.addModule("feature2")
.build();
// Begin the installation of the feature1 module and handle success/failure
splitInstallManager
.startInstall(request)
.addOnSuccessListener(new OnSuccessListener<Integer>() {
@Override
public void onSuccess(Integer integer) {
// Module download successful
Intent intent = new Intent().setClassName(getPackageName(), "com.bapspatil.feature2.FeatureTwoActivity");
startActivity(intent);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Module download failed; handle the error here
Toast.makeText(getApplicationContext(), "Couldn't download feature2: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}
Step 7 生成 App Bundle 文件
在 Android Studio 中点击 Build > Build Bundle(s)/APK(s) > Build Bundle(s)
或者输入命令行:
./gradlew :base:bundleDebug
即可在 project-name/app/build/outputs/bundle/
目录下生成 bundle 文件
Step 8 部署 App Bundle 文件
Google Play
海外发布的应用可支持 Google Play 部署
-
点击
Build > Generate Signed Bundle/APK
, 生成签名 Bundle 包 -
上传签名文件和 Bundle 包到 Google Play Console
-
通过 Google Play 下载应用 BundleTool
-
下载 bundletool,地址: bundletool release
-
通过应用包生成 apk 集
java -jar bundletool-all-1.11.0.jar build-apks
--bundle=<your_app_bundle_path>
--output=<output_apks_path>
- 为已连接的设备生成 apk(根据已连接设备的分辨率、abi 和语言)
java -jar bundletool-all-1.11.0.jar build-apks
--connected-device
--bundle=<your_app_bundle_path>
--output=<output_apks_path>
- 将 apk 部署到设备上(需要连接设备,根据设备信息自动提取对应资源并安装)
java -jar bundletool-all-1.11.0.jar install-apks
--apks=<output_apks_path>
因其生成的 apk 集的后缀为 apks,只能通过 bundletool 进行 apk 安装,无法通过 adb install 进行安装。
生成的full APKs
连接特定机型配置生成的 APKs
大小对比
full APKs | Find X5 APKs | 减少体积 | |
---|---|---|---|
APKs 大小 | 4100KB | 3728KB | 9% |