天天看点

Android热修复技术——QQ空间补丁方案解析(3)

正常app开发过程中,编译,打包过程都是android studio自动完成。如无特殊需求无需人为干预,但是要实现插桩就必须在android studio的自动化打包流程中加入插桩的过程。

android studio采用gradle作为构建工具,所有有必要了解一下gradle构建的基本概念和流程。如果不熟悉可以参考一下下列文章:

<a href="http://www.cnblogs.com/davenkin/p/gradle-learning-1.html">gradle学习系列之一——gradle快速入门</a>

<a href="http://blog.csdn.net/innost/article/details/48228651">深入理解android之gradle</a>

gradle的构建工程实质上是通过一系列的task完成的,所以在构建apk的过程中就存在一个打包dex的任务。gradle 1.5以上版本提供了一个新的api:transform,官方文档对于transform的描述是:

the goal of this api is to simplify injecting custom class manipulations without having to deal with tasks, and to offer more flexibility on what is manipulated. the internal code processing (jacoco, progard, multi-dex) have all moved to this new mechanism already in 1.5.0-beta1. the dex class is gone. you cannot access it anymore through the variant api (the getter is still there for now but will throw an exception)

transform can only be registered globally which applies them to all the variants. we'll improve this shortly.

there's no way to control ordering of the transforms.

transform任务一经注册就会被插入到任务执行队列中,并且其恰好在dex打包task之前。所以要想实现插桩就必须创建一个transform类的task。

gradle的执行脚本就是由一系列的task完成的。task有一个重要的概念:input的output。每一个task需要有输入input,然后对input进行处理完成后在输出output。

在android开发中我们经常使用到的plugin有:"com.android.application","com.android.library","java"等等。

每一个plugin包含了一系列的task,所以执行gradle脚本的过程也就是执行目标脚本所apply的plugin所包含的task。

新建一个module,选择library module,module名字必须叫buildsrc

删除module下的所有文件,除了build.gradle,清空build.gradle中的内容

然后新建以下目录 src-main-groovy

修改build.gradle如下,同步

像普通module一样新建package和类,不过这里的类是以groovy结尾,新建类的时候选择file,并且以.groovy作为后缀

自定义plugin:

8.inject.groovy, jarziputil.groovy

在app module下build.gradle文件中添加新插件:<code>apply plugin: com.hotpatch.plugin.register</code>

创建一个单独的module,命名为com.hotpatch.plugin.antilazyload:

使用上一篇博客介绍的方法打包hack.jar。然后将hack.jar复制到app module下的assets目录中。另外注意:app module不能依赖hack module。之所以要创建一个hack module,同时人为地在dex打包过程中插入对其他hack.jar中类的依赖,就是要让apk文件在安装的时候不被打上<code>class_ispreverified</code>标记。

另外由于hack.jar位于assets中,所以必须要在加载patch_dex之前加载hack.jar。另外由于加载其他路径的dex文件都是在<code>application.oncreate()</code>方法中执行的,此时还没有加载hack.jar,所以这就是为什么在上一章节插桩的时候不能在<code>application</code>中插桩的原因。

继续阅读