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 单字阅读

Android 逆向类加载器 ClassLoader ( 加载 Android 组件的类加载器 | 双亲委派机制实例分析 )

android 之 TabHost

Android:如何保存数据(Intent's Data)

单击侦听器+复选框-在android上

触摸监听器不工作android