App Bundle是一种什么东西呢?关于它的介绍性内容可以在官网和简书上找到很多,这里就不再重复了。如果想了解更多,可以参考以下资源:Android App Bundle和AndroidAppBundle。
这里主要侧重于实例。
Base APK是指在Android Studio中新建的任何一个工程(Application),都可以作为基础APK。
- 新建base apk与Dynamic feature
新建一个Empty Activity工程作为Base apk,然后app右键,通过New -> New Module,新建一个Dynamic Feature Module:
在Dynamic Feature Module同样新建一个Empty Activity。
那么如何将Base APK与Dynamic Feature Module关联起来呢?其实这一步骤在Android Studio中已经默认完成了。
在基本apk中,它将包含以下内容:
在Dynamic部分,将添加:dynamicFeatures = [:dynamictest]修改后的文案如下: 1. 修改前: ```implementation project(':app')``` 2. 修改后: 动态管理依赖包,其中前者为Google的依赖包,后者为华为的依赖包。修改后的文本如下: ```bash allprojects { repositories { google() jcenter() maven ``````java public class DynamicApplication extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); } } ``` 改写为: ```java /** * This is the DynamicApplication class that extends the Application class. */ public class DynamicApplication extends Application { /** * Override method to attach the base context. * * @param base The context to be attached. */ @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); } } ```package net.wen.dynamic.test; public class MainActivity extends AppCompatActivity { @Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(newBase); } }华为的动态管理类叫FeatureInstallManager,在Activity中可以对其进行初始化和添加listener:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mFeatureInstallManager = FeatureInstallManagerFactory.create(this); findViewById(R.id.click_test).setOnClickListener(v -> launchDynamic()); } @Override protected void onResume() { super.onResume(); if(mFeatureInstallManager != null) { mFeatureInstallManager.registerInstallListener(mStateUpdateListener); } } @Override protected void onPause() { super.onPause(); if(mFeatureInstallManager != null) { mFeatureInstallManager.unregisterInstallListener(mStateUpdateListener); } } private InstallStateListener mStateUpdateListener = new InstallStateListener() { @Override public void onStateUpdate(InstallState state) { Log.d(TAG, "install session state " + state); if (state.status() == FeatureInstallSessionStatus.REQUIRES_USER_CONFIRMATION) { try { mFeatureInstallManager.triggerUserConfirm(state, MainActivity.this, 1); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); } return; } if (state.status() == FeatureInstallSessionStatus.REQUIRES_PERSON_AGREEMENT) { try { mFeatureInstallManager.triggerUserConfirm(state, MainActivity.this, 1); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); } return; } if (state.status() == FeatureInstallSessionStatus.INSTALLED) { Log.i(TAG, "installed success ,can use new feature"); makeToast("installed success , can test new feature "); startDynamic();//use the dynamic feature return; } if (state.status() == FeatureInstallSessionStatus.UNKNOWN) { Log.e(TAG, "installed in unknown status"); makeToast("installed in unknown status "); return; } if (state.status() == FeatureInstallSessionStatus.DOWNLOADING) { long process = state.bytesDownloaded() * 100 / state.totalBytesToDownload(); Log.d(TAG, "downloading percentage: " + process); makeToast("downloading percentage: " + process); return; } if (state.status() == FeatureInstallSessionStatus.FAILED) { Log.e(TAG, "installed failed, errorcode : " + state.errorCode()); makeToast("installed failed, errorcode : " + state.errorCode()); } } };
那么如何安装动态部分呢?通过FeatureInstallRequest新建一个任务,然后通过FeatureInstallManager来启动任务:
private void requestDynamicInstall() { FeatureInstallRequest request = FeatureInstallRequest.newBuilder() // 添加dynamic feature 的名称 .addModule(DYNAMIC_MODULE) .build(); mFeatureInstallManager.installFeature(request) .addOnListener(new OnFeatureSuccessListener() { @Override public void onSuccess(Integer integer) { Log.d(TAG, load feature onSuccess.session id: + integer); } }) .addOnListener(new OnFeatureFailureListener() { @Override public void onFailure(Exception e) { Log.e(TAG, load feature onFailure: + e.getMessage()); } }); }3) Google的动态管理实现 实际上,华为的动态管理接口与Google非常相似,可能是为了兼容Android而有意设计成这样。为了区分开来,将Google部分代码写在一个ViewModel中。初始时也会进行listener的添加操作。
public BaseViewModel(@NonNull Application application) { super(application); splitInstallManager = SplitInstallManagerFactory.create(application); splitInstallManager.registerListener(listener); } @Override protected void onCleared() { super.onCleared(); splitInstallManager.unregisterListener(listener); } private SplitInstallStateUpdatedListener listener = state -> { if (state.sessionId() == sessionId) { if (state.status() == FAILED) { Log.d(TAG, Module in); } } };private void requestDynamicInstall() { SplitInstallRequest request = SplitInstallRequest.newBuilder() .addModule(DYNAMIC_MODULE) .build(); splitInstallManager.startInstall(request) .addOnSuccessListener(id -> sessionId = id) .addOnFailureListener(e -> { // handle failure }); }3 本地测试 为了在本地测试App Bundle的功能,您需要下载bundletool工具。您可以在google_bundletool下载地址找到该工具。如果您觉得下载速度较慢,也可以选择下载我上传的资源:bundletool-all-0.15.0.jar。
1) 首先,我们使用Android Studio进行编译。与编译APK的过程相似,不同之处在于这次我们选择构建bundle(s)。一旦编译完成,将会在app\build\outputs\bundle\debug目录下生成app-debug.aab文件。 2) 接下来,我们需要使用bundletool来生成APK文件。请切换到app\build\outputs\bundle\debug目录,并在命令行中输入以下指令:
java -jar D:\Chrome\Download\bundletool.jar build-apks --bundle=app-debug.aab --output=aab.apks
aab.apks生成后,以压缩文件的方式打开,即可看到:
默认情况下,Android studio 会自动根据 CPU 架构、屏幕分辨率、语言这三个维度将app 分拆;如果希望自由控制分拆维度,可以在app/build.gradle 文件中android {} 增加控制开个bundle { language { enableSplit = false } density { enableSplit = true } }D:\Android\android-sdk\platform-tools>adb install-multiple D:\apks\base-master.apk D:\apks\base-xxhdpi.apk D:\apks\base-zh.apk
然后运行,可以看到:
由于我们的动态模块需要从华为商城或者google play下载,而我们apks并没有走上传这一步,所以后续的结果是看不到的。当然,我们也可以将整个(包括动态部分)打包成一个完整的apk(注意:Android 5.0以下不支持bundle)。
请安装以下命令:java -jar D:\Chrome\Download\bundletool.jar build-apks --bundle=app-debug.aab --output=aab_un.apks --mode=universal
使用以下命令安装应用程序:adb install D:\apks\universal.apk。这与普通的apk安装方式相似,没有太大区别。4. 参考代码 以下是文中提到的代码示例: DynamicApplication
Google的示例:Android动态代码加载
还木有评论哦,快来抢沙发吧~