原标题:基于DX的Android动态更新技术

转自:文/Mob开发者平台 技术副总监 余勋杰

DX简介

安卓程序的主要代码是java 代码,不过由于安卓系统不直接使用sun的jvm,所以从javac编译过来的class文件并不能直接被安卓系统加载运行。

要想运行java代码,需要除了和以前一样调用javac将java代码编译为class文件以外,还需要调用dx这个工具,将class文件转成dex文件。然后安卓系统才会去加载dex文件并执行程序。因此说,dx是将class文件(及class文件集合)转成dex的工具。

dx属于安卓开源项目的一部分,它的源码位于“external/dexmaker”目录下,纯java。由于是纯java工具,所以可以打包成依赖库放到我们的 项目里面,实现安卓平台上,将一组class文件或一个jar文件转换成dex的功能。下面我将通过代码演示将一组class文件编译成dex,并加载运 行。

使用DX

导入class文件

程序的第一步是将class文件以字节数组的方式读入内存。为了演示方便,这里我将运行时编译的class集合选择为MobTools,为了简化示例程序,我事先将它解压到项目的assets中。下面的代码演示的是以递归的方式读取所有class文件到内存中:

初始化dex配置信息

载入class文件后,就可以将它们写入dex,但是dex会有一些配置信息需要初始化,下面的代码演示了这个过程:

我并没有仔细查阅过这两个类的用途,希望后续使用此功能的同事可以追加注释。

添加class文件

接下来是将class类名和数据添加到dex实例中:

DexFile是dex数据在内存中的抽象,可以理解为一个列表。列表中存放着一个个ClassDefItem,携带着各个class的完整路径和描述数据。

我在添加的过程中利用ClassDefItem对类描述数据的解析功能,获取了每一个类的父类和接口列表,并缓存了起来。这个会在后续加载dex的时候用到。

保存dex文件

DexFile是dex文件在内存的解析结果,不能直接拿来使用。安卓系统加载dex都是基于文件的,所以现在还需要将DexFile转成dex数据:

toDex的第一个参数是日志输出工具,如果设置为null,表示不输出日志。

完成转换以后得到一个byte数组,只要将byte数组写入文件,并保存为dex后缀就可以被多数的安卓系统加载。但是对于一些定制的系统,比方说小米,他 们只识别压缩包里的dex,比方说jar包里的dex。这种方式普通系统也是支持的,为了更好的兼容性,我将dex文件保存到了应用私有目录下的一个 jar文件中:

数据会保存到“/data/data/包名/files”下的MobTools.jar中。打开个jar包,里面就是我们熟悉的“classes.dex”文件。

加载dex文件

有了文件,现在就可以调用系统的api来加载它:

dalvik.system.DexFile是android.jar里面提供的api,虽然名字也是DexFile,但是功能和dx里面DexFile不同。使用时通过其静态方法loadDex来获取实例。传入的参数jarPath表示jar包的路径,dexPath表示准备加压的dex文件路径。

由于MobTools中有很多各类,而且不同的类有继承关系,所以这里我开辟了一个方法loadClass做递归加载。其原理是:循环获取 classesNames列表中的第一个元素尝试进行加载,加载前判断这个类是否有父类,如果有,将这个父类从classesNames列表中取出,然后先对这个父类进行加载。如果被加载的类没有父类,则再检查他是否有实现什么借口,如果有,循环加载这些接口的类。父类和接口列表都完成加载以后,再加载最 初尝试加载的类。这样子就不会再加载的过程中报出“子类找不到父类”的问题。

使用

完成了上述的操作后,原先assets中的class文件就被全部加载如内容,可以被使用了。

使用的方式有两种,一直是基于反射,先获取某个类的Class 对象,然后通过Class对象获取方法或字段,最后invoke或者get/set。第二种方式是实现通过依赖mobtools的方式编写一份代码,并将 这份代码编译为jar包,被我们的项目依赖;等到mobtools加载完毕后,代用这个jar包中的api,使用其中的功能。

这两种办法各有优劣。第一种办法编写起来很麻烦,容易出错,但是随时可以改变逻辑。第二种办法由于编码的时候依赖了mobtools,所以能以常规的编码方式进行开发,后来使用时调用它的api时也比较直观。但是它在使用时已经是静态的jar包,要改动比较麻烦。

动态更新

我研究dx的目的在于动态更新,否则在安卓系统上编译和加载class文件并没有什么意义。一般操作方式是这样子:首先,对于一些可能日后要改变的功能,编 译代码时不将它们打包到apk的dex中,而是打包到zip文件,当做资源的方式随包发布;使用时会对zip文件进行解压,然后运行时合并为dex,并 path到内存中使用。然后,等项目的逻辑改变了,服务端可以向客户端推送改变逻辑后的class文件集合,去覆盖原来的class文件;等到下一次客户 端重新启动时,发现class文件版本已经改变了,于是再度动态合并dex,并path。

如此,apk的升级可以变得频繁,而且每次都是增量更新。如果用户删除了缓存的数据,应用只会恢复到初始状态,然后再从服务端获取最新版本的“class补丁”替换合并即可。

甚至,如果服务端的性能更强的情况下,可以对不同的客户端下发不同的class文件,比方说为不同的客户端定制RSA的公钥,或者其它的配置信息等等。

与groovy结合

如果嫌以class为单位来更新代码,颗粒度还不够的话,还可以结合groovy的解析器。

groovy 是一种脚本语言,它基于java虚拟机,并且完全兼容java语法。groovy能将自己的脚本编译为java的class,所以刚好可以被我们用来减少 动态更新的颗粒度。比方说一开始我们发布的时候不是将class文件压缩为一个zip,而是直接压缩java源码。运行后调用groovy来解析这些 java源码,将它们编译为class文件,再调用dx对这些class文件进行合并。升级的时候,服务端指定具体的源码文件的具体段落进行替换,可以替 换一整个包,也可以只是替换一行代码。替换以后再调用groovy重新编译即可。

妈妈常教导我,让我养成良好习惯。这样长大才能成为一个有用的人。良好的习惯是尊敬师长这样长大才能成为一个有用的人。良好的习惯是尊敬师长,爱护同学,对人有礼貌;是不粗心,做事情不拖拉;还是爱护公物,不浪费粮食。为什么呢?因为拥有良好习惯,做一个品德高尚的人,懂得尊重别人,才会得到别人的尊重。我要努力地做到这些。我有一些坏习惯,有时候学习很粗心,把一些会做的题做错。在生活上,也很粗心,有一次早上起床居然穿反了衣服。我吃饭很慢,有的时候还剩饭。我还起床磨蹭,本来应该迅速地穿好衣服,但是,我总是磨磨蹭蹭地,速度很慢。“我打算在这学期里,改掉这些坏习惯。早上起来,迅速地穿好衣服,不拖拉。学习不粗心,仔细完成每一道题。吃饭的时候,要很快的把饭吃完,不剩饭。我要从一点一滴做起,逐渐养成良好习惯。我相信自己一定能成为一名品学兼优的好学生!我打算在这学期里,改掉这些坏习惯。早上起来,迅速地穿好衣服,不拖拉。学习不粗心,仔细完成每一道题。吃饭的时候,要很快的把饭吃完,不剩饭。我要从一点一滴做起,逐渐养成良好习惯。我相信自己一定能成为一名品学兼优的好学生!”在上幼儿园以前,我什么也不会干,就连穿衣服也是妈妈给我穿好,就要上幼儿园了,这样可不行,妈妈锻炼我要学会自己穿衣服。   有一天,妈妈把衣服摆在我面前,开始让我自己穿。一开始。我又哭又叫就是不穿,还把衣服扔的满地都是,然后坐在地上开始大哭,等了好长时间,妈妈还是不理我,我只好自己乖乖的把衣服穿好, 一出了房间门,妈妈就笑了起来,再看看我的衣服,毛衣和裤子都穿反了,我赶紧回房间又重新穿了一遍,这次穿好了,拿起外套,可是外套的扣子又扣不上了,扣子可调皮了,好像故意和我作对,我把扣子往扣眼——人类邪恶的根源;爱情——幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话:幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话“亲爱的!擦干你的眼泪,至高无上的爱情已经打开了我们的眼界,使我们成了它的崇拜者。是它,

妈妈常教导我,让我养成良好习惯。这样长大才能成为一个有用的人。良好的习惯是尊敬师长这样长大才能成为一个有用的人。良好的习惯是尊敬师长,爱护同学,对人有礼貌;是不粗心,做事情不拖拉;还是爱护公物,不浪费粮食。为什么呢?因为拥有良好习惯,做一个品德高尚的人,懂得尊重别人,才会得到别人的尊重。我要努力地做到这些。我有一些坏习惯,有时候学习很粗心,把一些会做的题做错。在生活上,也很粗心,有一次早上起床居然穿反了衣服。我吃饭很慢,有的时候还剩饭。我还起床磨蹭,本来应该迅速地穿好衣服,但是,我总是磨磨蹭蹭地,速度很慢。“我打算在这学期里,改掉这些坏习惯。早上起来,迅速地穿好衣服,不拖拉。学习不粗心,仔细完成每一道题。吃饭的时候,要很快的把饭吃完,不剩饭。我要从一点一滴做起,逐渐养成良好习惯。我相信自己一定能成为一名品学兼优的好学生!我打算在这学期里,改掉这些坏习惯。早上起来,迅速地穿好衣服,不拖拉。学习不粗心,仔细完成每一道题。吃饭的时候,要很快的把饭吃完,不剩饭。我要从一点一滴做起,逐渐养成良好习惯。我相信自己一定能成为一名品学兼优的好学生!”在上幼儿园以前,我什么也不会干,就连穿衣服也是妈妈给我穿好,就要上幼儿园了,这样可不行,妈妈锻炼我要学会自己穿衣服。   有一天,妈妈把衣服摆在我面前,开始让我自己穿。一开始。我又哭又叫就是不穿,还把衣服扔的满地都是,然后坐在地上开始大哭,等了好长时间,妈妈还是不理我,我只好自己乖乖的把衣服穿好, 一出了房间门,妈妈就笑了起来,再看看我的衣服,毛衣和裤子都穿反了,我赶紧回房间又重新穿了一遍,这次穿好了,拿起外套,可是外套的扣子又扣不上了,扣子可调皮了,好像故意和我作对,我把扣子往扣眼——人类邪恶的根源;爱情——幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话:“亲爱的!擦干你的眼泪,至高无上的爱情已经打开了我们的眼界,使我们成了它的崇拜者。是它,

最后,国庆福利来了,我们的知识星球已达到1000人了,之前说过到达1000人时将大大幅涨价到169元,为了反馈大家对我们的关注和厚爱,国庆之际特此维持现价99元,国庆天后将涨到169元,欢迎大家加入我们的知识星球,更多星球信息参见:返回搜狐,查看更多

责任编辑:

android 动态更新配置文件,基于DX的Android动态更新技术相关推荐

  1. android美食app设计图,基于位置的Android美食地图应用的设计与实现

    摘要: 随着近些年移动互联网的迅猛发展和智能手机的普及,手机应用迎来于广阔的发展空间,移动LBS应用应运而生.传统的位置服务主要以网页或单机的形式实现,已无法满足用户日益增长的移动需求.而移动LBS应 ...

  2. android 电视语音遥控器,基于遥控器的Android电视语音聊天系统及其方法与流程

    本发明涉及,尤其涉及一种基于遥控器的Android电视语音聊天系统及其方法. 背景技术: 随着科技越来越发展,电视机的功能也越来越强大,对于电视机,相对于传统电视机的单纯看电视功能,现有技术中,还支持 ...

  3. 【C 语言】文件操作 ( 配置文件读写 | 写出或更新配置文件 | 追加键值对数据 | 更新键值对数据 )

    文章目录 一.追加键值对数据 二.更新键值对数据 三.完整代码示例 一.追加键值对数据 在上一篇博客 [C 语言]文件操作 ( 配置文件读写 | 写出或更新配置文件 | 逐行遍历文件文本数据 | 获取 ...

  4. seo vue 动态路由_基于vue.jsvue-router的动态更新TDK(SEO优化)

    本文基于工作项目开发,做的整理笔记 前几天帮朋友解决这个问题,顺带学习了一下,做个笔记Mark下. 前提条件: 你已经了解并使用vue,能够搭建应用站点. 编码环境: system:OS X EI C ...

  5. lxc和android的双系统,基于LXC的Android系统虚拟化技术

    近年来云计算[1]的快速发展,虚拟化技术[2]被广泛应用于高性能服务器,以提高系统资源的利用率.同时,随着智能手机等移动终端的普及[3],智能终端扮演着越来越重要的角色,用户对视频.微信.新闻浏览等功 ...

  6. android屏幕共享实现方式,基于WebRtc在Android端实现屏幕共享

    注:本文默认你已经掌握了如何用WebRtc建立视频连接.如果没有,请参考https://www.jianshu.com/p/eb5fd116e6c8,这里将不再赘述. 第一步:向系统发起屏幕截取请求 ...

  7. android 即时通讯 xmpp,基于xmpp实现android端实现即时通讯

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 简单介绍一下asmack中常用到的方法属性 connection.getAccountManager().createA ...

  8. Android学习-- 基于位置的服务 LBS(基于百度地图Android SDK)--定位SDK

    原文:Android学习-- 基于位置的服务 LBS(基于百度地图Android SDK)--定位SDK 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.ne ...

  9. 动态代理的两种方式_动态代理是基于什么原理?

    代理模式 给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问. 什么是动态代理 运行时动态生成代理类. 动态代理我们需要些什么 1.业务接口(Interface) 业务的抽象表示. 2.业务 ...

最新文章

  1. 谈谈 Tomcat 请求处理流程
  2. ping php支付,thinkphp框架中引出ping++支付server SDK
  3. Understanding your audience
  4. 如何在64位WIN7下安装64位的解压版mysql-5.6.37-winx64.zip
  5. java虚拟机手机下载_java虚拟机下载
  6. 前端每周清单第 39 期: OpenAI 与 gRPC, Gitlab 的 Vue 年度总结,GraphQL 技术栈漫游
  7. 电脑死机大全,看完你就是高手了
  8. atitit.为什么笔记本跟个手机不能组装而pc可以
  9. 示例:父子关系(Parent Child Relationships)
  10. Apple Configurator 2 修复M1 Macbook 时报错 0x15
  11. 股票实时行情接口编程难度大吗?
  12. 操作系统实验八:页面置换模拟程序设计
  13. 记一次修改阿里云DNS解析问题
  14. ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13新特性大全
  15. 驴商人和胡萝卜的算法逻辑思维问题
  16. MTK android WIFI地址 不写随机变动问题
  17. unity 让ui对齐_Unity中UI锚点的四种摆放形式
  18. iPad与电脑端文件互传解决方案(基于nPlayer lite)
  19. 名词解释第二十八讲:跨链
  20. 中国各省会城市经纬度数据(附MATLAB代码)

热门文章

  1. 【百度快照】基于MATLAB的人民币纸币系列号面额识别系统【GUI】
  2. 简易电量计算解决方案
  3. PIE SDK地图显示范围截图
  4. 重读《C primer plus》(六)
  5. it团队建设方案参考
  6. Xyplayer X3 智能云解析官方正式版 x3.95
  7. vue拆分js文件_基于Vue+Webpack拆分路由文件实现管理
  8. Word 取消超链接快捷键
  9. Maven Setting文件详细配置
  10. Java™ 教程(目录)