一、关于优快云 mardown编辑器的坑
Android热补丁动态修复技术(三)这篇博文其实在4月8日的晚上已经发布了,然后紧接着写第四篇,但是我将(四)保存到草稿箱时,发现已经发布的(三)消失了,取而代之的是第四篇博文。
在论坛问过版主,可能是因为我误操作导致的,第三篇博文已经无法恢复。
真是手贱!写了好几天的东西啊,不过比起误操作我更倾向认为这是csdn的bug……
markdown编辑器绝对有坑!光是写新文章时不会自动清楚缓存我认为就是一个很严重的Bug了!
二、前言
因为第三篇博文消失的原因,伴随着演示的Demo项目也修改了很多内容,我也没那么精力重新写一篇,就和第四篇博文合并在一起当做第三篇吧,这可能导致内容跨度有些大,并且不会像之前的博文这么详细,希望大家多多支持和理解。
上一篇博客中,我们再Application中成功注入了patch_dex.jar到ClassLoader中。
但是伴随着CLASS_ISPREVERIFIED问题,解决方式就在在所有类的构造函数中添加一行代码System.out.println(AntilazyLoad.class);
三、Gradle, Transfrom, Task, Plugin
我们来分析一下如何在所有类的构造函数中添加System.out.println(AntilazyLoad.class);
- 在源码中直接添加,这个不行。AntilazyLoad.class这个类找不到,编译不通过
- 绕过编译,使用javassist操作字节码,直接注入代码。
第二点是可行的,但是AndroidStudio项目是使用Gradle构建的,编译-打包-签名都是自动化。
我们在什么时候注入代码?
看过我上一篇博文推荐的文章就知道,Gradle是通过一个一个Task执行完成整个流程的,其中肯定也有将所有class打包成dex的task。
(在gradle plugin 1.5 以上和以下版本有些不同)
- 1.5以下,preDex这个task会将依赖的module编译后的class打包成jar,然后dex这个task则会将所有class打包成dex
- 1.5以上,preDex和Dex这两个task已经消失,取而代之的是TransfromClassesWithDexForDebug
3.1 Transfrom
Transfrom是Gradle 1.5以上新出的一个api,其实它也是Task,不过定义方式和Task有点区别。
对于热补丁来说,Transfrom反而比原先的Task更好用。
-
在Transfrom这个api出来之前,想要在项目被打包成dex之前对class进行操作,必须自定义一个Task,然后插入到predex或者dex之前,在自定义的Task中可以使用javassist或者asm对class进行操作。
-
而Transform则更为方便,Transfrom会有他自己的执行时机,不需要我们插入到某个Task前面。Tranfrom一经注册便会自动添加到Task执行序列中,并且正好是项目被打包成dex之前。
而本文就是使用Gradle1.5以上版本,下面则是Google对Transfrom的描述文档。
http://tools.android.com/tech-docs/new-build-system/transform-api
有时候会访问不了,你可能需要一把梯子……
3.2 Task的inputs和outputs
Gradle可以看做是一个脚本,包含一系列的Task,依次执行这些task后,项目就打包成功了。
而Task有一个重要的概念,那就是inputs和outputs。
Task通过inputs拿到一些东西,处理完毕之后就输出outputs,而下一个Task的inputs则是上一个Task的outputs。
例如:一个Task的作用是将java编译成class,这个Task的inputs就是java文件的保存目录,outputs这是编译后的class的输出目录,它的下一个Task的inputs就会是编译后的class的保存目录了。
3.3 Plugin
Gradle中除了Task这个重要的api,还有一个就是Plugin。
Plugin的作用是什么呢,这一两句话比较难以说明。
Gralde只能算是一个构建框架,里面的那么多Task是怎么来的呢,谁定义的呢?
是Plugin,细心的网友会发现,在module下的build.gradle文件中的第一行,往往会有apply plugin : 'com.android.application'
亦或者apply plugin : 'com.android.library'
。
com.android.application
:这是app module下Build.gradle的
com.android.library
:这是app依赖的module中的Builde.gradle的
就是这些Plugin为项目构建提供了Task,使用不同的plugin,module的功能也就不一样。
可以简单的理解为: Gradle只是一个框架,真正起作用的是plugin。而plugin的主要作用是往Gradle脚本中添加Task。
当然,实际上这些是很复杂的东西,plugin还有其他作用这里用不上。
四、如何注册一个Transfrom
我们可以自定义一个plugin,然后使用plugin注册一个Transfrom。
4.1 apply plugin
在此之前,先教大家怎么自定义一个plugin。
-
新建一个module,选择library module,module名字必须叫BuildSrc
-
删除module下的所有文件,除了build.gradle,清空build.gradle中的内容
-
然后新建以下目录 src-main-groovy
-
修改build.gradle如下,同步
apply plugin: 'groovy' repositories { jcenter() } dependencies { compile gradleApi() compile 'com.android.tools.build:gradle:1.5.0' compile 'org.javassist:javassist:3.20.0-GA' }
package com.aitsuki.plugin
import org.gradle.api.Plugin;
import org.gradle.api.Project
/**
* Created by hp on 2016/4/8.
*/
public class Register implements Plugin<Project> {
@Override
public void apply(Project project) {
project.logger.error "================自定义插件成功!=========="
}
}
在app module下的buiil.gradle中添apply 插件
说