Atlas初探

概念

atlas:容器化框架,提供组件化开发,热更新。

image

如上图所示,atlas主要分为以下几个层级:

  1. 最底下的hack工具层: 包括了容器所需的所有系统层面的注入和hack的工具类初始化和校验,容器启动时先校验设备是否支持容器运行,不支持则采取降级并记录原因;
  2. Bundle Framework 负责bundle的安装 更新 操作以及管理整个bundle的生命周期;
  3. runtime层:主要包括清单管理、版本管理、以及系统代理三大块,基于不同的触发点按需执行bundle的安装和加载;runtime层同时提供了开发期快速debug支持和监控两个功能模块。从Delegate层可以看到,最核心的两个代理点:一个是DelegateClassLoader:负责路由class加载到各个bundle内部,第二个是DelegateResource:负责资源查找时能够找到bundle内的资源;这是bundle能够真正运行起来的根本;其余的代理点均是为了保证在必要的时机按需加载起来目标bundle,让其可以被DelegateClassloader和DelegateResource使用
  4. 对外接入层:AtlasBridgeApplication是atlas框架下apk的真正Application,在基于Atlas框架构建的过程中会替换原有manifest中的application,所以Atlas没入的接入并不存在任何初始化代码,构建脚本完成了接入的过程。AtlasBridgeApplication里面除了完成了Atlas的初始化功能,同时内置了multidex的功能,这样做的原因有两个:

很多大型的app不合理的初始化导致用multidex分包逻辑拆分的时候主dex的代码就有可能方法数超过65536,�AtlasBridgeApplication与业务代码完全解耦,所以拆分上面只要保证atlas框架在主dex,其他代码无论怎么拆分都不会有问题;
如果不替换Application,那么atlas的初始化就会在application里面,由于基于Atlas的动态部署实际上是类替换的机制,那么这种机制就会必然存在包括Application及其import的class等部分代码在dalvik不支持部署的情况,这个在使用过程中造成一定成本,需要小心的使用以避免dalivk内部class resolve机制导致部分class没成功,替换以后该问题得到最好的解决,除atlas本身以外,所有业务代码均可以动态部署;
另外内置的原生的multidex在dalvik上面性能并不好,atlas内部对其进行了优化提高了在dalvik上面的体验。

除AtlasBridgeApplication之外,接入层对外提供了部分工具类,包括主动install bundle,start bundle,以及获取全局的application等各种功能。

集成

  1. 工程项目的build.gradle文件依赖插件:


    image
  2. app目录下的build.gradle使用插件,并且添加相关依赖


    image

    image

    image
  3. 加载自启动的bundle

switchToActivity("home","com.taobao.firstbundle.FirstBundleActivity");
//通过类名来调用
 public void switchToActivity(String key,String activityName){
        Intent intent = new Intent();
        intent.setClassName(getBaseContext(),activityName);
        activityGroupDelegate.startChildActivity(framelayout,key,intent);
    }
image

可以看到现在的fistBundle中弹出了一个toast,message 为“更新一下”,下面修改firstBundle中的代码,然后热更新一下

修改toast的message

@Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this, "单模块部署1111111", Toast.LENGTH_SHORT).show();
    }

bundle热更新步骤
1、 app的build.gradle的语句"version = getEnvValue("versionName", "1.0.0");"中修改想要生成的app的versionName(默认为1.0.0)

app目录下执行../gradlew clean assembleDebug publish

(生成apk同时将跟apk同目录的ap文件发布到仓库)

2、 手机上安装apk,同时进到动态部署界面(侧边栏里面划开点击进入),且手机连接电脑adb(确保adb devices可见)

///////////////////////////////^^^^^^准备工作^^^^^^^^^////////////////////////

3、 进行一些想要的修改(暂时不支持manifest的修改,会在近期上线)

4、 app工程目录下执行../gradlew clean assembleDebug -DapVersion=apVersion -DversionName=newVersion,
其中apVersion为之前打的完整apk的版本,newVersion为此次动态部署要生成的新的版本号

5、 检查build/output/tpatch-debug 目录下文件是否生成,然后执行下面的命令(以下为mac下的命令,windows请修改文件分隔符)

adb push build/outputs/tpatch-debug/update.json /sdcard/Android/data/cx.com.atlasdemo11111/cache/update.json
adb push build/outputs/tpatch-debug/patch-*.tpatch /sdcard/Android/data/cx.com.atlasdemo11111/cache

6、 点击动态部署页面红色按钮执行动态部署

更改firstBundle中的代码,然后
在app目录下执行命令,app/build/outputs/ 会出现

//DapVersion基准版本号      DversionName更新版本号
../gradlew clean assembleDebug -DapVersion=1.0.0 -DversionName=1.0.1

命令跑完后就会出现下面的目录结构

image

执行

adb push build/outputs/tpatch-debug/update.json /sdcard/Android/data/cx.com.atlasdemo11111/cache/update.json
adb push build/outputs/tpatch-debug/patch-*.tpatch /sdcard/Android/data/cx.com.atlasdemo11111/cache

然后点击动态部署按钮,效果如下

image

可以看到热更新已经成功。

远程bundle使用

  1. 远程bundle必须在gradle中配置,如上图
atlas {

    atlasEnabled true
    tBuildConfig {
        autoStartBundles = ['com.taobao.firstbundle'] //自启动bundle配置
        outOfApkBundles = ['remotebundle']//配置远程bundle
    }

    manifestOptions{
        addAtlasProxyComponents true
    }


    patchConfigs {
        debug {
            createTPatch true
        }
    }


    buildTypes {
        debug {
            if (apVersion) {
                baseApDependency "com.taobao.android.atlasdemo:AP-debug:${apVersion}@ap"
                patchConfig patchConfigs.debug
            }
        }
    }
}

2.在Application中添加安装远程bundle的回调

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;
            }
        });

3.把app/build/outputs/remote-bundles-debug/libcom_taobao_remotebundle.so 放到sd卡的cache目录,执行命令

adb push build/outputs/remote-bundles-debug/libcom_taobao_remotebunle.so /sdcard/Android/data/cx.com.atlasdemo11111/cache/libcom_taobao_remotebunle.so

点击添加远程bundle看效果


image

可以看到已经将远程bundle加载成功。

在自己集成的demo中也有很多的坑。跑命令失败的情况。记录一下

集成atlas时的坑

  1. app工程目录下执行../gradlew clean assembleDebug -DapVersion=apVersion -DversionName=newVersion

这个命令中的apVersion必须是存在的版本号,比如在gradle中设置的1.0.0,不然会报找不到依赖

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "cx.com.atlasdemo11111"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName version //这里的versionName要和脚本中的一致,如果设置死,在热修复merge的时候不会起作用
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

3.这个版本的单模块调试模拟还不稳定

atlas不得不说是良心之作,这个demo只是简单地集成,以供参考。

点击下载代码

官方链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,367评论 6 343
  • 夜是那么漫长,透过黑夜我期待看到光明,可却感觉光明永远不会到来,不过终于不再做恶梦了,因为已经习惯了一次次的嘲讽与...
    清简如荷阅读 210评论 0 0
  • 到了谈婚论嫁的年纪了,始终觉得别扭,我自己还没那个能力,能够养活一家人,一直觉得能力缺少,始终不敢表达爱,我希望的...
    啊貴阅读 189评论 2 0