Android-->热修复,补丁实战

原创 2015年11月18日 16:27:38

阅读此文之前,可以先阅读: http://blog.csdn.net/lmj623565791/article/details/49883661

在此不阐述原理, 只描述实际过程.


1:首先新建一个Android Studio Android 工程(Project)
新建2个类:

public class BugWrapperClass {//存在Bug的类, 需要被一个父类包含
    public String getBug() {
        return new BugClass().getBug();
    }
}
public class BugClass {
    public String getBug(){
        return "Is In Bug Class";//用于修复的类
    }
}
  ((TextView) findViewById(R.id.text_view)).setText( new BugWrapperClass().getBug());//调用的方法, 很简单,不详述了.

2:这个时候,需要替换BugClass.class, 步骤如下:
需要修改项目 Module 的 build.gradle 如下:

apply plugin: 'com.android.application'

//注意此处
task('insertClass') << {
    String classPath = file('build/intermediates/classes/debug')//项目编译class所在目录
    dodola.patch.PatchClass.process(classPath, project(':InsertLib').buildDir
            .absolutePath + '/intermediates/classes/debug')//第二个参数是hackdex的class所在目录
}

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        ...
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    //注意此处
    applicationVariants.all { variant ->
        variant.dex.dependsOn << insertClass}
}

dependencies {
    ...
}

//以下方法在,buildSrc(Moudle中),后面有下载地址;主要最用就是去除 CLASS_ISPREVERIFIED 标识

public class PatchClass {
    /**
     * 植入代码
     * @param buildDir 是项目的build class目录,就是我们需要注入的class所在地
     * @param lib 这个是hackdex的目录,就是AntilazyLoad类的class文件所在地
     */
    public static void process(String buildDir, String lib) {

        println(lib)
        ClassPool classes = ClassPool.getDefault()
        classes.appendClassPath(buildDir)
        classes.appendClassPath(lib)

        println("buildDir:" + buildDir)
        println("lib:" + lib)

        CtClass c1 = classes.getCtClass("com.rsen.BugWrapperClass")//需要去除标识的类
        if (c1.isFrozen()) {
            c1.defrost()
        }
        println("====添加构造方法====")
        def constructor1 = c1.getConstructors()[0];
        constructor1.insertBefore("System.out.println(com.angcyo.insertlib.InsertClass.class);")
        c1.writeFile(buildDir)
    }
}

修改完 build.gradle之后,此时运行项目,调用代码时,会报错;
因为 InsertClass.class类,没有加载;
新建一个 lib moudle,新建一个 InsertClass.class类;如下:

public class InsertClass {
//这个类,声明了就可以
}

编译成jar, 再用dx工具,打包成dex类型的jar:
方法如下:

Make Moudle之后,会在
(Moudle根目录)\build\intermediates\bundles\debug\classes.jar 这个目录下生成jar文件

在 (Android SDK目录)\build-tools\23.0.2\dx.bat 这个目录有dx工具

通过 命令:dx  --dex --output hack_dex.jar hack.jar
可以得到 dex类型的jar

得到dex.jar文件之后,复制到项目assets目录中,通过以下代码,加载InsertClass类

public class RApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        File dexPath = new File(getDir("dex", Context.MODE_PRIVATE), "indertlib_dex.jar");
        HotFix.prepareDex(this.getApplicationContext(), dexPath, "indertlib_dex.jar");
        HotFix.patch(this, dexPath.getAbsolutePath(), "com.angcyo.insertlib.InsertClass");
        try {
            this.getClassLoader().loadClass("com.angcyo.insertlib.InsertClass");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
//注意要在manifest.xml文件中 使用这个application哦;
//这里需要依赖 HotFix 库moudle,后面有下载地址;

此时,项目可以正常运行了;

3:打补丁
新建一个 补丁 lib moudle;创建需要修补的类

public class BugClass {
    public String getBug(){
        return "Is Patch Rsen Class";//此方法已经修改了.
    }
}

通过之前介绍的方法: 使用dx工具,获取dex类型的jar;
将得到的jar,放在项目assets目录;

4:加载补丁

  //准备补丁,从assert里拷贝到dex里
  File dexPath = new File(getDir("dex", Context.MODE_PRIVATE), "patch_dex.jar");
  HotFix.prepareDex(this.getApplicationContext(), dexPath, "patch_dex.jar");
  HotFix.patch(this, dexPath.getAbsolutePath(), "com.rsen.BugClass");//包名要一致

  Snackbar.make(findViewById(R.id.text_view), "打补丁完成", Snackbar.LENGTH_LONG)
          .setAction("Action", null).show();
  //注意,在打补丁之前,先不要调用BugClass类,否则打补丁会失败;

热修复的方法有点复杂,如果有更容易实现的方法,欢迎告之,不胜感激;


文中依赖的2个库项目,和整个项目下载地址:https://github.com/angcyo/HotFixMultiDexDemo

特别提示:gradle的插件版本只能使用 1.3.0; 否则编译会出错!

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0' //注意此行
    }
}

至此: 文章就结束了,如有疑问: QQ群:274306954 欢迎您的加入.

版权声明:欢迎转载,转载请注明出处-->http://blog.csdn.net/angcyo 举报

相关文章推荐

Android 热修复 Tinker接入及源码浅析

一、概述 放了一个大长假,happy,先祝大家2017年笑口常开。 假期中一行代码没写,但是想着马上要上班了,赶紧写篇博客回顾下技能,于是便有了本文。 热修复这项技术,基本上已经成为项目比较重要...

浅谈Android热修复

前言: 很多时候测试完的产品上线后,突然发现一个小的bug。这时候考虑到用户体验、和时间成本,不能为了一点点bug而重新发布新版本。于是就有了热修复这个概念的产生!它可以在不发布版本的情况下修复出bu...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

安卓热修复,android打补丁,不用发版本就能实时的解决一些线上版本的bug

安卓热修复,android打补丁,不用发版本就能实时的解决一些线上版本的bug

Android 热修复方案分析

绝大部分的APP项目其实都需要一个动态化方案,来应对线上紧急bug修复发新版本的高成本.之前有利用加壳,分拆两个dex结合DexClassLoader实现了一套全量更新的热更方案.实现原理在Andro...
  • l2show
  • l2show
  • 2016-11-11 16:06
  • 4923

Android 热修复其实很简单

android AndFix 热修复 动态加载

Android-->热修复,补丁实战

阅读此文之前,可以先阅读: http://blog.csdn.net/lmj623565791/article/details/49883661 在此不阐述原理, 只描述实际过程.1:首先新建一个An...
  • angcyo
  • angcyo
  • 2015-11-18 16:27
  • 3527

AndHotFix热修补使用总结

今天给大家介绍AndHotFix热修补的使用,也没有那么的难,我结合了github和csdn的一些东西,自己总结出来一套非常简单的操作流程。 这个就是我结合出来的AndHotFix的结构,...

andfix 热补丁修复

andfix 热补丁修复背景:我们知道Android在发布新版本后如果发现某个方法有bug时native app是不能像webapp让用户无感知的实现更新代码的,我们必须要提醒用户下载新版本;在这种情...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)