教你接入阿里的Atlas组件化框架

1,972 阅读7分钟
原文链接: mp.weixin.qq.com

点击上方蓝字关注公众号

码个蛋第265次推文

手机淘宝都在用它

作者:在寻找雪见的景天

博客:https://www.jianshu.com/u/3a5162ea1c99

文章目录

  • 前言

  • 主要功能

  • 开始接入

  • 重点来了

  • 总结步骤

0

前言

Atlas已经出了很久,这几天刚好有个空档期研究了一下,在没啥资料的情况下,加了一堆群,踩了一堆坑,终于成功接入了。本文就是记录接入的过程,并不会讲解太多的原理,想要知道原理的前往:官网(https://link.jianshu.com/?t=http://atlas.taobao.org/)

1

主要功能

一、远程Bundle,就是打包的时候不会把这个bundle打包进去,减少apk的安装体积,用户安装apk后,需要加载那个功能的话,就从网上下载这个bundle的so,然后加载打开,当然下载逻辑是app写的。适用模块比较多的app使用,按需加载模块。

二、热更新,就是出补丁包,对一个版本进行代码修改,在不需要用户更新apk的情况下完成更新。

2

开始接入

一、新建一个项目,然后新建几个module,如下图

二、配置1、把gradle改为3.3

2、项目级的build

buildscript {    repositories {        jcenter()        mavenLocal()//本地maven    }    //引入啊里的依赖,不需要再依赖classpath "com.android.tools.build:gradle"的版本,默认使用的是 2.1    dependencies {        classpath "com.taobao.android:atlasplugin:2.3.1.rc9"    }}allprojects {    repositories {        jcenter()        mavenLocal()//本地maven    }}task clean(type: Delete) {    delete rootProject.buildDir}

3、app的build

// 需要放最上面初始化group = "mmc.atlastest"version = getEnvValue("versionName", "1.0.0");def apVersion = getEnvValue("apVersion", "");apply plugin: 'com.android.application'apply plugin: 'com.taobao.atlas'android {    compileSdkVersion 25    buildToolsVersion "25.0.2"    defaultConfig {        applicationId "mmc.atlastest"        minSdkVersion 15        targetSdkVersion 25        versionCode 1        versionName version        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}dependencies {    compile fileTree(include: ['*.jar'], dir: 'libs')    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {        exclude group: 'com.android.support', module: 'support-annotations'    })    compile 'com.android.support:appcompat-v7:25.3.1'    testCompile 'junit:junit:4.12'    //atlas的依赖    compile('com.taobao.android:atlas_core:5.0.7@aar') {        transitive = true    }    compile 'com.taobao.android:atlasupdate:1.1.4.7@aar'    compile 'com.alibaba:fastjson:1.1.45.android@jar'    //项目依赖    compile project(':librarybundle')    compile project(':localbundle')    compile project(':remotebundle')}//加入以下配置atlas {    atlasEnabled true    tBuildConfig {       // autoStartBundles = ['com.android.homebundle'] //自启动bundle配置        outOfApkBundles = ['remotebundle'] //远程module,列表来的,可填多个        preLaunch = 'mmc.atlastest.AtlasLaunch' //AppApplication启动之前调用,这个类下面放出代码    }    patchConfigs {        debug {            createTPatch true        }    }    buildTypes {        debug {            if (apVersion) {                // 打差异补丁 gradlew assembleDebug -DapVersion=1.1.0 -DversionName=1.1.1                // 对应着本地maven仓库地址 .m2/repository/mmc/atlastest/AP-debug/1.1.4/AP-debug-1.1.4.ap                baseApDependency "mmc.atlastest:AP-debug:${apVersion}@ap"                patchConfig patchConfigs.debug            }        }    }}String getEnvValue(key, defValue) {    def val = System.getProperty(key);    if (null != val) {        return val;    }    val = System.getenv(key);    if (null != val) {        return val;    }    return defValue;}apply plugin: 'maven'apply plugin: 'maven-publish'publishing {    // 指定仓库位置    repositories {        mavenLocal()    }    publications {        // 默认本地仓库地址  用户目录/.m2/repository/        maven(MavenPublication) {            //读取ap目录上传maven            artifact "${project.buildDir}/outputs/apk/${project.name}-debug.ap"            //生成本地maven目录            groupId group            artifactId "AP-debug"        }    }}

4、远程bundle和本地bundle的build

apply plugin: 'com.android.library'apply plugin: 'com.taobao.atlas'atlas {    bundleConfig{        awbBundle true    }    buildTypes {        debug {            baseApFile project.rootProject.file('app/build/outputs/apk/app-debug.ap')        }    }}//只添加上面的配置就行了,下面的是默认生成的android {    compileSdkVersion 25    buildToolsVersion "25.0.2"    defaultConfig {        minSdkVersion 15        targetSdkVersion 25        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}dependencies {    compile fileTree(include: ['*.jar'], dir: 'libs')    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {        exclude group: 'com.android.support', module: 'support-annotations'    })    compile 'com.android.support:appcompat-v7:25.3.1'    testCompile 'junit:junit:4.12'    //依赖lib中间bundle    compile project(':librarybundle')}

5、application里面添加

public class DemoApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        Atlas.getInstance().setClassNotFoundInterceptorCallback(new ClassNotFoundInterceptorCallback() {            @Override            public Intent returnIntent(Intent intent) {                final String className = intent.getComponent().getClassName();                final String bundleName = AtlasBundleInfoManager.instance().getBundleForComponet(className);                if (!TextUtils.isEmpty(bundleName) && !AtlasBundleInfoManager.instance().isInternalBundle(bundleName)) {                    //远程bundle                    Activity activity = ActivityTaskMgr.getInstance().peekTopActivity();                    File remoteBundleFile = new File(activity.getExternalCacheDir(),"lib" + bundleName.replace(".","_") + ".so");                    String path = "";                    if (remoteBundleFile.exists()){                        path = remoteBundleFile.getAbsolutePath();                    }else {                        Toast.makeText(activity, " 远程bundle不存在,请确定 : " + remoteBundleFile.getAbsolutePath() , Toast.LENGTH_LONG).show();                        return intent;                    }                    PackageInfo info = activity.getPackageManager().getPackageArchiveInfo(path, 0);                    try {                        Atlas.getInstance().installBundle(info.packageName, new File(path));                    } catch (BundleException e) {                        Toast.makeText(activity, " 远程bundle 安装失败," + e.getMessage() , Toast.LENGTH_LONG).show();                        e.printStackTrace();                    }                    activity.startActivities(new Intent[]{intent});                }                return intent;            }        });    }}

6、在app新建一个类AtlasLaunch,继承AtlasPreLauncher

public class AtlasLaunch implements AtlasPreLauncher {    @Override    public void initBeforeAtlas(Context context) {    }}

三、然后写app的基本功能,示例如下图:

public class MainActivity extends BaseActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);            }    //打开远程bundle    public void remote(View view){        Intent intent = new Intent();        intent.setClassName(view.getContext(), "mmc.remotebundle.RemoteActivity");        startActivity(intent);    }    //打开本地bundle    public void local(View view){        Intent intent = new Intent();        intent.setClassName(view.getContext(), "mmc.localbundle.LocalActivity");        startActivity(intent);    }    //更新补丁    public void update(View view){        new AsyncTask<Void, Void, Void>() {            @Override            protected Void doInBackground(Void... voids) {               update();                return null;            }            @Override            protected void onPostExecute(Void aVoid) {                Toast.makeText(MainActivity.this, "更新完成,请重启", Toast.LENGTH_LONG).show();            }        }.execute();    }    private void update(){        File updateInfo = new File(getExternalCacheDir(), "update.json");        if (!updateInfo.exists()) {            showToast("更新信息不存在,请先 执行 buildTpatch.sh");            return;        }        String jsonStr = new String(FileUtils.readFile(updateInfo));        UpdateInfo info = JSON.parseObject(jsonStr, UpdateInfo.class);        File patchFile = new File(getExternalCacheDir(), "patch-" + info.updateVersion + "@" + info.baseVersion + ".tpatch");        try {            AtlasUpdater.update(info, patchFile);        } catch (Throwable e) {            e.printStackTrace();            showToast("更新失败, " + e.getMessage());        }    }}

四、安装运行这个版本的apk,界面如下:

1、这个时候点击远程bundle会弹出说没有so文件,因为还没打so包呢2、点击本地bundle,是可以跳转到那个本地bundle页面3、点击更新补丁,会提示更新信息不存在

3

重点来了

下面要打包出远程bundle的so文件,补丁的差异包和更新说明1、打so文件,每个远程都会生成一个so文件的。打开AS的Terminal,输入:gradlew clean assembleDebug publish,然后回车,如下图:

正常的话,会提示这个:

如果提示下面这个错

那就把java进程全部杀掉,然后重试,原因是为啥,我也不知道

成功的话,app的build文件夹里,会生成这个so文件,这个就是远程bundle的so文件,把这个文件放到手机内存卡Android/data/mmc.atlastest/cache 文件夹里面,然后再打开app,点击“远程Bundle”,这个时候就能跳转过去了。

2、更新补丁,打差异包和更新说明接着第一步,然后修改版本号,对本地Bundle进行文字修改,对app主项目也可以修改(修改已有的Activity)

修改后,在Terminal里面输入:gradlew clean assembleDebug -DapVersion=1.0.0 -DversionName=1.0.1回车,成功后会生成补丁差异包和更新说明,如下图:

把红色圈中的两个文件,放到手机内存卡Android/data/mmc.atlastest/cache 文件夹里面,然后点击“更新补丁”,过一会,提示更新成功后,就退出杀死app,再打开就是后面修改的内容了。这样就完成更新过程了,完整源码:AtlasTest(https://link.jianshu.com/?t=https://github.com/LuoGuoXin/AtlasTest)

4

总结步骤

1、配置好,安装1.0.0的app2、用命令“gradlew clean assembleDebug publish”打AP,得到远程Bundle的so文件3、修改版本号,修改版本内容4、用命令“gradlew clean assembleDebug -DapVersion=1.0.0 -DversionName=1.0.1”打差异包补丁和更新说明5、把上面得到的三个文件放到app的cache目录里面6、运行更新方法,杀死app,重启