AtlasDemo And 一些问题与经验

Atlas Demo过程记录。有这个是因为项目中的插件不是放在apk里面,也不是自动下载安装的。而是有个插件管理界面,里面和app应用市场一样的可以安装,更新和卸载插件(其中还涉及到一些用户/插件/插件中的功能 之间的权限问题,这里不需要关心)。Atlas自带的动态部署和dexPatch不满足需求,比如更新是要针对单个插件的更新而不是整个apk和所有插件。 为了找到解决方案和复习Atlas的动态部署,这才用新的demo重新走了遍流程。最后还好发现条路子可以解决我的问题~~!。
1。打包
assembleDebug
1.0.0

产物
AtlasDemo And 一些问题与经验_第1张图片
image.png
2.上传发布
gradlew publish -DversionName=1.0.0(这里不加参数默认也是1.0.0,但是得有这个概念)
本地maven
AtlasDemo And 一些问题与经验_第2张图片
image.png
其中.ap文件的内部结构
AtlasDemo And 一些问题与经验_第3张图片
image.png

3.安装运行apk

4.上传并加载运程bundle
image.png
adb push E:\data\AS_Other\atlas\atlas-demo\AtlasDe
mo\app\build\outputs\remote-bundles-debug\libcom_taobao_remotebunle.so /sdcard/Android/data/com.taobao.demo/cache/libcom_taobao_remotebunle.so
直接打开运程bundle中的component加载bundle运行。

5.查看目前为止手机上生成的产物。Adb shell下

run-as com.taobao.demo ls -l /data/data/com.taobao.demo/files/storage
image.png
其中每个bundle下面的结构都是这样的
image.png

在往下本地bundle和remote的稍微不一样

本地:
image.png
Remote:
image.png

--------------------------------------------------------动态部署------------------------------------------------------
1.分别对publicBundle,firstbundle,secondbundle,remotebundle做简单修改。
2.gradlew clean assembleDebug -DapVersion=1.0.0 -DversionName=2.0.0
*这里第一次打patch时失败,原因是修改过的bundle没有改version.

产出:
AtlasDemo And 一些问题与经验_第4张图片
image.png

3.maven上传新的ap
gradlew publish -DversionName=2.0.0
首先demo文档中没有指示这一步,其次,需要指定版本,不然把原先maven中的1.0.0覆盖掉,这样是不对的,而且又得重来。
4..tpatch差异包文件
AtlasDemo And 一些问题与经验_第5张图片
image.png
image.png

根据修改的情况不同,每个bundle包中结果可能不同。
比如只改了代码,就只有classes.dex;改了界面但是没有加id操作,就会多res但是不会有resources.arsc. Maindex.so也差不多,只是多了manifest,因为最起码版本号变了,所以manifest肯定需要更新。

5.update-1.0.0.json动态部署配置文件(精简)
AtlasDemo And 一些问题与经验_第6张图片
image.png
这里为了表现出bundle的version不是受打patch包时传入的版本决定,bundle的版本用了和app的版本不一样的。

6.上传手机
adb push build/outputs/tpatch-debug/update-1.0.0.json /sdcard/Android/data/com.taobao.demo/cache/update-1.0.0.json
adb push build/outputs/tpatch-debug/[email protected]/sdcard/Android/data/com.taobao.demo/cache/[email protected]

7.正式执行动态部署
AtlasDemo And 一些问题与经验_第7张图片
image.png

8.so far so good. 疑惑的地方是,文档里面说动态部署后bundle和hostbundle在文件夹里面都为升级,如version1到version2,备份了为回滚做准备,但是并没有看到。手机里面目录结构和动态部署前差不多,只是bundle文件夹下面那一串unitTag的文件夹名变成新的了。

------------------------------------------第二次动态部署----------------------------------------
1.修改部分bundle。

2.gradlew clean assembleDebug -DapVersion=1.0.0 -DversionName=3.0.0。记得修改过的bundle要改version
AtlasDemo And 一些问题与经验_第8张图片
image.png

3.上传测试,因为当前手机是2.0.0,所以上传的是2.0.0到3.0.0的patch
adb push build/outputs/tpatch-debug/update-2.0.0.json /sdcard/Android/data/com.taobao.demo/cache/update-2.0.0.json

adb push build/outputs/tpatch-debug/[email protected] /sdcard/Android/data/com.taobao.demo/cache/[email protected]
4.so for so gud. 查看手机文件夹还是和第一次动态部署情况一样。

----------------------------测试直接从安装状态更新到3.0.0,并且在安装时不上传加载remote------------------------------
1.把1.0.0的ap中的apk安装到手机
2.在把3.0.0对于1.0.0的patch上传到手机
3.动态部署后,内部bundle能正常更新,但是外部bundle因为没有安装过so不能启动,所以也谈不上更新。
4.把1.0.0的remote上传后可正常运行,但是这样就失去了3.0.0的更新。
5.但是把1.0.0的remote完全从手机中删除后,重新上传3.0.0remote的so,加载后就是3.0.0的状态。
6.震精!!!重新卸载安装1.0.0,上传3.0.0的remote,可行。那么就是说,我可以单独更新某个remote bundle,不需要动态部署的升级版本,也不仅限于dexPatch只能更新代码。只要安装前把原来已经安装的remote的文件夹删除就可以。但是需要考虑几个问题:1.已经运行状态,内存中关于remote bundle的信息已经加载是否会造成影响,比如说已经删除了文件夹,但是还是能查到这个bundle的信息。2.后面的更新不能依赖于host的更新。3.如果此次启动已经运行过remote,是否会有影响,是否需要直接关闭应用让用户重启。
7.最后一试,上一条否定。不用直接删除文件夹处理,用自带的Atlas里面的uninstall方法卸载可行。但是不会删除上传的so,所以要注意处理。这样的话单独更新一个remotebunlde是确实可行的。。。
8.So far so fucking gud.
9.新发现,现在通过AtlasBundleInfoManager查询到的插件版本都是null,不管是否是remote. Why? I need it.
10.Debug时发现通过uninstall把remote插件卸载之后,通过Atlas.getBundle是获取不到了,但是AtlasBundleInfoManager中还是有保存。
11.测试发现AtlasBundleInfoManager中的远程插件的信息和有没有安装或者安装的是那个版本的remote没什么关系,不会变化。
12.测试发现从Altas获取Bundle时如果插件还没有运行过得到的是null.

最后,过程中记录一下还是挺有好处的,有好几次需要各种命令,比如push文件到手机啊,run-as看手机目录啊这种,本来路径就长记不住,需要的时候回来文档里面找一下,美滋滋。

-----------------后续在实际项目中遇到的新问题---------------------

实际项目中自己设计的更新逻辑(试了下流程图太麻烦..):
AtlasDemo And 一些问题与经验_第9张图片
image.png
这个是大体流程,但是实际中有几个表管理插件信息和插件与人员的关系和插件里的具体功能等。和流程中对应的操作比如:1.安装成功需要保存插件信息和插件人员关系信息。2.如果安装失败且安装备份插件包也失败的话需要把插件表和插件人员关系表中相关数据都清除,避免用户还是能在功能界面看到插件的功能但是实际上是没有插件安装的。3.插件更新成功需要更新插件信息和插件功能表的信息。



1.通过uninstall在install的方式更新远程插件时,如果这个要更新的插件在这次启动app还没有加载过,那么会导致uninstall失败。 解决办法有:设置成启动就加载,虽然有可能还没有安装过插件会导致异常,但是应该不至于崩溃。这样的话能保证更新的时候如果之前已经安装过,在启动的时候已经加载了,就不会异常。 还可以在uninstall前判断下有没有加载,没有的话就先执行一次加载在卸载。项目中我使用的是后者。
2.如果更新成功需要重启app.不是因为需要重启才能看到更新,且是不重启会崩溃。日志里面看不出什么异常,因为是框架里面的原因。

2017/11/14更新
最新发现,按照上面的逻辑管理插件时。当手机上安装了插件后,开发时如果apk修改后installDebug安装,这时storage下面编译后的插件还在,但是一旦启动apk后,storage下面的插件文件夹就消失了。 猜测是发现插件的那个类似唯一码的东西和apk里面的对应插件的不相同,所有系统把它删除了。
解决办法:这个时候就体现出我之前备份安装过的插件so的英明之处了,哈哈。
利用Atlas.getInstance().setClassNotFoundInterceptorCallback
回调,重新安装备份插件即可。如果找不到插件或者安装失败,则直接清除表里面的插件信息,跳转到插件管理界面提示用户重新安装插件即可。no毛病~!

Sample code
AtlasDemo And 一些问题与经验_第10张图片
image.png

2018/05/23更新
使用中发现在插件间通过intent传递数据时会有问题。比如class找不到,或者类型转换异常等,具体细节忘了。只记得解决方法是把Searializable换成Parceable,还有就是在activity中设置调用intent的setExtrasClassLoader方法,把类加载器设置为插件的BundleClassLoader,不然这些系统类会用默认的加载器,如果数据类是在插件中而不是在host里面就会报找不到类。还有调用Bundle里面的setClassLoader也是一样的。

你可能感兴趣的:(AtlasDemo And 一些问题与经验)