• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android热补丁动态修复技术(三)—— 使用Javassist注入字节码,完成热补丁框架雏形(可使用)

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

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了Android热补丁动态修复技术(三)—— 使用Javassist注入字节码,完成热补丁框架雏形(可使用)等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

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


一、关于CSDN 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。
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作为后缀。
这里写图片描述
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 {
    @Override
    public void apply(Project project) {
        project.logger.error "================自定义插件成功!=========="
    }
}

在app module下的buiil.gradle中添apply 插件
这里写图片描述
说明:如果plugin所在的module名不叫BuildSrc,这里是无法apply包名的,会提示找不到。所以之前也说明取名一定要叫buildsrc

运行一下项目就可以看到”================自定义插件成功!==========”这句话了
和gradle有关的输出都会显示在gradle console这个窗口中。
这里写图片描述

4.2 自定义Transfrom

新建一个groovy继承Transfrom,注意这个Transfrom是要com.android.build.api.transform.Transform这个包的
要先添加依赖才能导入此包,如下

dependencies {
    compile gradleApi()
    compile 'com.android.tools.build:gradle:1.5.0'
    compile 'org.javassist:javassist:3.20.0-GA'
}

javassist待会要用到,顺便添加进来了。

我们定义一个PreDexTransform,代码如下

package com.aitsuki.plugin

import com.android.build.api.transform.*
import com.android.build.gradle.internal.pipeline.TransformManager
import org.gradle.api.Project

public class PreDexTransform extends Transform {

    Project project
    // 添加构造,为了方便从plugin中拿到project对象,待会有用
    public PreDexTransform(Project project) {
        this.project = project
    }

    // Transfrom在Task列表中的名字
    // TransfromClassesWithPreDexForXXXX
    @Override
    String getName() {
        return "preDex"
    }

    // 指定input的类型
    @Override
    Set getInputTypes() {
        return TransformManager.CONTENT_CLASS
    }

    // 指定Transfrom的作用范围
    @Override
    Set getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT
    }

    @Override
    boolean isIncremental() {
        return false
    }

    @Override
    void transform(Context context, Collection inputs,
                   Collection referencedInputs,
                   TransformOutputProvider outputProvider, boolean isIncremental)
            throws IOException, TransformException, InterruptedException {

       // inputs就是输入文件的集合
       // outputProvider可以获取outputs的路径
    }
}

然后再Register这个plugin的apply方法中添加一下代码,注册Transfrom

def android = project.extensions.findByType(AppExtension)
        andro



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

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

相关文章

  • 2017-05-26View的事件分发机制,View事件分发机制
  • 2017-05-26Android刷机教程之LG Nexus 5X线刷官方Nexus系列教程,androidnexus
  • 2017-05-26Toast显示图文界面——Android开发之路1,toastandroid
  • 2017-05-26android 在5.0以后不允许使用隐式Intent方式来启动Service,androidintent
  • 2017-05-26android:QQ多种侧滑菜单的实现
  • 2017-05-26Android开源库集合(工具),android开源库集合
  • 2017-05-226.2 数据存储与访问之——SharedPreferences保存用户偏好参数
  • 2017-05-26listview下拉刷新和上拉加载更多的多种实现方案,listview下拉
  • 2017-05-26弧形菜单(Android),弧形菜单android
  • 2017-05-26解决 Could not find com.android.tools.build:gradle 问题,couldnotfindntldr

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android(Linux)实时监测串口数据,android实时监测
    • Android线程优先级设置方法技巧,android线程优先级
    • Android打印机--小票打印格式及模板设置
    • Android versionCode和versionName的区别,androidversioncode
    • android 权限拒绝时的问题解决(详解)
    • 仿天天动听5应用项目源码,项目源码
    • Android View体系(六)从源码解析Activity的构成
    • Activity被回收导致fragment的getActivity为空,fragmentgetactivity
    • 【原创】Android ExpandableListView使用,expandablelistview
    • Android 接入 OpenCV库的三种方式,androidopencv

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有