tinker源码分析

一、基础信息相关验证
从服务器下载patch包之后,开始加载patch包合并全量的dex,合并之前要对patch进行一系列的验证,首先进入 onPatchReceived(String path)
方法

1.判断!manager.isTinkerEnabled() || !ShareTinkerInternals.isTinkerEnableWithSharedPreferences(context),其中manager.isTinkerEnabled()实际是判断最开始的ApplicationLike中的注解flag的值,比如我的app中的注解为


只要flag的注解不是ShareConstants.TINKER_DISABLE,则manager.isTinkerEnabled()=true;而或语句后面的判断,则是根据tinker版本对应储存在SharedPreferences的值(防止tinker升级版本之后的影响),默认为true,(false的情况为当app加载patch出现异常,会进入tinkerPreVerifiedCrashHandler,然后会设置SharedPreferences对应的值为false)


2.判断patch包是否是有效文件;
3.判断是否是patch进程,根据Tinker类中的isPatchProcess变量判断,而isPatchProcess变量在Tinker类的构造函数赋值,Tinker类使用了建造者模式,其中this.mainProcess = TinkerServiceInternals.isInMainProcess(context),
this.patchProcess = TinkerServiceInternals.isInTinkerPatchServiceProcess(context),一个判断是否在主进程,一个判断在Patch服务进程;
4.判断patchService是否在运行中
5.判断安卓系统dalvik虚拟机是否用JIT编译
6.判断最大内存和最大空间
7.获取patch文件的MD5值,在SharedPreferences查看合并dex时候crash次数是否超过了最大crash次数
8.判断重试次数,如果设置重试为false,或者重试结果文件不存在,或者MD5值不存在,返回true,否则返回false(说明重试次数超过最大重试次数)
9.判断多渠道的补丁包是否正确
10.将结果传递给SampleTinkerReport


二、签名,tinker_id和修复类型的验证
所有这些检验没有问题之后,开启patchService服务(TinkerPatchService.runPatchService(context, path))进行合并全量的dex;使用的是IntentService,合并结束后服务自动stop,并且过程中增加了服务的优先级,降低被系统杀死的概率,
最后调用upgradePatchProcessor.tryPatch(context, path, patchResult)进行合并全量dex;
首先还是进行前面说到的1和2两点判断,
3.获取本地apk的签名信息,调用ShareTinkerInternals.checkTinkerPackage(context, manager.getTinkerFlags(), patchFile, signatureCheck)验证签名信息;首先进行checkSignatureAndTinkerID(context, patchFile, securityCheck)判断基础包apk的签名、tinker_id和patch包的
签名和tinker_id是否相等,checkPackageAndTinkerFlag(securityCheck, tinkerFlag)检查是否支持dex,so和资源文件的修复。


三、合并全量的dex,并对其优化

验证完之后,再进行全量dex的合并,合并用到了二路归并算法,合并的dex放到DEX_PATH下面,同时对dex进行优化生产odex放到DEX_OPTIMIZE_PATH.

其中,patch包中会有

以及dex_meta和package_meta的信息如下图:


源代码中会在系统目录下生成dex文件和优化后的odex:


在系统路径生成patch包的apk文件,如果该文件和patch包的MD5值不相等,则将patch包文件复制到destPatchFile文件,


接下来进行tryRecoverDexFiles()方法,在debug模式下,根据源码的顺序,下面的图展示的各个变量的值。




然后会根据dexDiffMd5和oldDexCrc的值进行一些判断,dexDiffMd5和oldDexCrc的值为0的时候,应该是对test.dex进行操作,其他情况对classes.dex进行操作(这里不确定),验证dexDiffMd5是否符合MD5格式,oldDexCrc和基础包的值是否相等,不相等说明补丁包不是根据当前基础包打的补丁,都通过的话执行patchDexFile(apk, patch, rawApkFileEntry, patchFileEntry, info, extractedFile)合并dex文件extractedFile,生成的文件的MD5与补丁包的MD5比较进行验证。这些步骤做完之后(即完成extractDexDiffInternals(context, dir, meta, patchFile, TYPE_DEX)方法。接下来就是针对不同的虚拟机,对dex进行优化生成optimizeDex,针对dalvik虚拟机,我们生成optimizeDexDirectoryFile目录,然后调用DexFile.loadDex(file.getAbsolutePath(), outputPathName, 0)即对dex进行了optimized,针对art虚拟机,比较复杂点。使用了线程池和CountDownLatch同步方法,如果useInterpretMode,则采用Dex2Oat,否则依然用dalvik虚拟机里面的DexFile.loadDex方法;针对art系统,里面有很好的多线程同步的例子,时候学习和研究。


以上就是加载patch包进行合并全量的dex文件,和优化后的odex,在app下次启动的时候,ApplicationLike注解生成的TinkerApplication扩展类中
onBaseContextAttached(Context base)的方法中有loadTinker();loadTinker()方法通过java反射调用了TinkerLoader.tryLoad(TinkerApplication app),即加载了上述修复后的全量dex和odex。


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值