Android热补丁动态修复技术(三)—— 使用Javassist注入字节码,完成热补丁框架雏形(可使用)

一、关于优快云 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);

  1. 在源码中直接添加,这个不行。AntilazyLoad.class这个类找不到,编译不通过
  2. 绕过编译,使用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。

  1. 新建一个module,选择library module,module名字必须叫BuildSrc

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

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

  4. 修改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'
    }
    
5. 这时候就可以像普通module一样新建package和类了,不过这里的类是以groovy结尾,新建类的时候选择file,并且以.groovy作为后缀。 ![这里写图片描述](https://img-blog.csdnimg.cn/img_convert/84987fdc41abf541de90bc069524b069.png) Register就是我自定义个Plugin(无视黑色涂块,Demo被我修改太多了,再次鄙视csdn) 代码如下
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 插件
这里写图片描述

评论 59
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值