Android——Android app bundle插件化部署
Posted 化作孤岛的瓜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android——Android app bundle插件化部署相关的知识,希望对你有一定的参考价值。
其实google发布app bundle已经是18年的事情了,只是一直在业务上接触不到。最近刚好打算用到爱奇艺的Qigsaw框架来做国内的模块化加载,所以打算一起学习一下。
说到模块化加载。其实本质就是为了缩小apk大小,增加下载量,增加应用功能的自由装载机制。
本文会先从官网的android app bundle文档与实例开始分析,先快速入手,写一个最简单的模块化调用demo。
1.分析官网的demo:
演示了如何使用 PlayCore API 请求和下载功能模块:
https://github.com/android/app-bundle-samples/tree/main/DynamicFeatures
演示了从安装的功能模块安全访问代码的三种不同方法:
https://github.com/googlesamples/android-dynamic-code-loading
2.首先新建一个工程,名字叫PlayFeatureDemo
导入依赖:api "com.google.android.play:core:1.8.3"
3.file->new module->Dynamic Feature ->输入module名字,game->next->finish
创建一个GameSampleActivity
4.创建SplitInstallManager实例,配置监听器,发起跳转。
代码:
package com.ng.playfeaturedemo;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.google.android.play.core.splitinstall.SplitInstallManager;
import com.google.android.play.core.splitinstall.SplitInstallManagerFactory;
import com.google.android.play.core.splitinstall.SplitInstallRequest;
import com.google.android.play.core.splitinstall.SplitInstallSessionState;
import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener;
import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus;
import com.google.android.play.core.tasks.OnFailureListener;
import com.google.android.play.core.tasks.OnSuccessListener;
public class MainActivity extends BaseSplitActivity implements SplitInstallStateUpdatedListener
private TextView mProgressBar;
private SplitInstallManager manager;
private String PACKAGE_NAME = "com.ng.game";
private String KOTLIN_SAMPLE_CLASSNAME = "com.ng.game.GameSampleActivity";
private int CONFIRMATION_REQUEST_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgressBar = findViewById(R.id.progressBar);
manager = SplitInstallManagerFactory.create(this);
findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
loadAndLaunchModule(getString(R.string.module_feature_game));
);
private void loadAndLaunchModule(String string)
if (manager.getInstalledModules().contains(string))
Toast.makeText(this, "已安装", Toast.LENGTH_SHORT).show();
launchActivity(KOTLIN_SAMPLE_CLASSNAME);
return;
SplitInstallRequest request = SplitInstallRequest.newBuilder().addModule(string).build();
manager.startInstall(request).addOnSuccessListener(new OnSuccessListener<Integer>()
@Override
public void onSuccess(Integer result)
toastAndLog("成功: " + result);
).addOnFailureListener(new OnFailureListener()
@Override
public void onFailure(Exception e)
toastAndLog("失败: " + e.getMessage());
);
private void launchActivity(String className)
Intent intent = new Intent().setClassName(BuildConfig.APPLICATION_ID, className);
startActivity(intent);
@Override
protected void onResume()
manager.registerListener(this);
super.onResume();
@Override
protected void onPause()
manager.unregisterListener(this);
super.onPause();
@Override
public void onStateUpdate(SplitInstallSessionState state)
//是否多模块安装
boolean multiInstall = state.moduleNames().size() > 1;
switch (state.status())
case SplitInstallSessionStatus.DOWNLOADING:
displayLoadingState(state, "下载中 ");
case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION:
try
manager.startConfirmationDialogForResult(state, this, CONFIRMATION_REQUEST_CODE);
catch (IntentSender.SendIntentException e)
e.printStackTrace();
break;
case SplitInstallSessionStatus.INSTALLED:
launchActivity(KOTLIN_SAMPLE_CLASSNAME);
break;
case SplitInstallSessionStatus.INSTALLING:
displayLoadingState(state, "安装进度");
break;
case SplitInstallSessionStatus.FAILED:
toastAndLog(getString(R.string.error_for_module, state.errorCode(),
state.moduleNames()));
break;
private void displayLoadingState(SplitInstallSessionState state, String message)
int max = (int) state.totalBytesToDownload();
int progress = (int) state.bytesDownloaded();
mProgressBar.setText(message + " " + progress + " / " + max);
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
if (requestCode == CONFIRMATION_REQUEST_CODE)
// Handle the user's decision. For example, if the user selects "Cancel",
// you may want to disable certain functionality that depends on the module.
if (resultCode == Activity.RESULT_CANCELED)
toastAndLog("用户拒绝");
else
super.onActivityResult(requestCode, resultCode, data);
void toastAndLog(String text)
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
Log.d("MainActivity", text);
@Override
public void onPointerCaptureChanged(boolean hasCapture)
本地测试:
api文档:https://developer.android.com/guide/app-bundle/test/testing-fakesplitinstallmanager
生成aab之后:
拆包:
bundletool用法_zzzia-CSDN博客_bundletool怎么使用
拆包命令:
bundletool build-apks --local-testing --bundle=/Users/xiaoguagua/AndroidProjects/OpenSourceProjects/PlayFeatureDemo/app/release/app-release.aab --output=/Users/xiaoguagua/AndroidProjects/OpenSourceProjects/PlayFeatureDemo/app/release/my_app.apks
得到了一个my_app.apks,可以解压
安装到手机:
bundletool install-apks --apks=/Users/xiaoguagua/AndroidProjects/OpenSourceProjects/PlayFeatureDemo/app/release/my_app.apks
运行,点击按钮:
可以看到开始下载组件
然后自动跳转到写的组件界面
就大功告成了。接下来会开始分析 实现原理以及Qigsaw的实现步骤。
参考:
AppBundle api
示例工程:
https://github.com/android/app-bundle-samples/tree/main/PlayCoreKtx
https://developer.android.com/guide/app-bundle
https://developer.android.com/guide/playcore/play-feature-delivery
安装时分发,按需分发和按条件分发
demo:
app-bundle
https://developer.android.com/guide/playcore/play-feature-delivery
以上是关于Android——Android app bundle插件化部署的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向类加载器 ClassLoader ( 加载 Android 组件的类加载器 | 双亲委派机制实例分析 )