Alibaba-Dexposed框架在线热补丁修复的使用

来源:互联网 发布:php在线运行测试 编辑:程序博客网 时间:2024/04/30 14:36

转:http://blog.csdn.net/qxs965266509/article/details/49821413

目录(?)[-]

  1. DexPosed
    1. 介绍
    2. 应用场景
    3. 在Android上的使用
      1. 在自定义Application初始化
    4. patch文件的生成
    5. 支持的系统

这里写图片描述

前两篇已经介绍了alibaba的AndFix热修复: 
Alibaba-AndFix Bug热修复框架的使用 
Alibaba-AndFix Bug热修复框架原理及源码解析

DexPosed是Alibaba的另一个框架,都可以在线热修复bug,只不过DexPosed也可以实现其他的功能。

  • DexPosed
    • 介绍
    • 应用场景
    • 在Android上的使用
      • 在自定义Application初始化
    • patch文件的生成
    • 支持的系统

DexPosed

介绍

DexPosed是强大而无侵入的AOP(面向切面编程)运行Android应用程序开发框架,基于开源的Xposed框架项目的工作(Xposed是修改系统框架服务的框架)。 
Github : https://github.com/alibaba/dexposed

应用场景

AOP编程 
仪表(用于测试,性能监测等) 
在线热补丁修复 
SDK hooking(钩)以提供更好的开发体验

在Android上的使用

Android Studio中使用: 
在Gradle中添加:

 dependencies {        compile 'com.taobao.android:dexposed:0.1.1@aar' }
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

在libs中加入:dexposedbridge.jar、patchloader.jar包。 
需要添加的so文件有:libdexposed.so、libdexposed_1.so。

在自定义Application初始化

if (DexposedBridge.canDexposed(this)) {//判断系统是否支持DexPosed      Log.e("APP", "true application");} else {      Log.e("APP", "false application");}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

当收到服务器推送消息,需要下载patch文件,下载完成后即时加载来修复bug。 
PatchResult result = PatchMain.load(this, “patch apk文件的路径”, null);

 //加载patch apk文件            PatchResult result = PatchMain.load(this, fullpath, null);            if (result.isSuccess()) {                Log.e("Hotpatch", "patch success!");            } else {                Log.e("Hotpatch", "patch error is " + result.getErrorInfo());            }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

//注:patch apk 文件不能放在共享目录中,建议放在cache文件中。 
在应用升级之前需每次load加载patch apk,当应用升级后把patch apk进行清空。 
PatchMain.load加载patch apk,会遍历apk中实现IPatch接口的所有,并hook对应的方法对象。

patch文件的生成

新创建一个项目MyPatch,并在libs中加入dexposedbridge.jar、patchloader.jar包。 
在build.gradle设置jar为provided,如下:

dependencies {    provided files('libs/dexposedbridge.jar')    provided files('libs/patchloader.jar')}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

如果想修复一个bug,需在MyPatch中创建一个类,并实现IPatch接口,实现handlePatch方法。

接下的Demo是想在bug方法的前后做一些处理,也可以终止bug方法的调用及修改bug方法的参数:

package com.open.cool.patch;import android.util.Log;import android.view.View;import android.widget.Toast;import com.taobao.android.dexposed.DexposedBridge;import com.taobao.android.dexposed.XC_MethodHook;import com.taobao.patch.IPatch;import com.taobao.patch.PatchParam;//必须实现IPatch接口public class MyPatch implements IPatch {    @Override    public void handlePatch(final PatchParam arg0) throws Throwable {        Class<?> cls = null;        try {            //使用类加载器获取需要修复的方法所在的类Class            cls = arg0.context.getClassLoader()                    .loadClass("com.open.cool.mydex1.MainActivity");        } catch (ClassNotFoundException e) {            e.printStackTrace();            return;        }        //hook想要操作的方法,在方法前后做一些处理,XC_MethodHook        //cls上边获取到的,这里的test1是有bug的方法名称,View.class是test1的参数类型,如果有多个参数就依次在后边添加View.class,Object.class,Object.class等。        DexposedBridge.findAndHookMethod(cls, "test1", View.class,                new XC_MethodHook() {                    @Override                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {                        super.beforeHookedMethod(param);                        Log.e("IPatch", "beforeHookedMethod");                        //TODO 调用hook方法前的操作                        Toast.makeText(arg0.context, "before", Toast.LENGTH_SHORT).show();//                           param.setResult(null);//禁止调用原方法                    }                    @Override                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {                        super.afterHookedMethod(param);                        //TODO 调用hook方法后的操作                        Log.e("IPatch", "afterHookedMethod");                    }                });         }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

下面的Demo是直接替换掉bug方法:

package com.open.cool.patch;import android.util.Log;import android.view.View;import android.widget.Toast;import com.taobao.android.dexposed.DexposedBridge;import com.taobao.android.dexposed.XC_MethodHook;import com.taobao.android.dexposed.XC_MethodReplacement;import com.taobao.patch.IPatch;import com.taobao.patch.PatchParam;//必须实现IPatch接口public class MyPatch implements IPatch {    @Override    public void handlePatch(final PatchParam arg0) throws Throwable {        Class<?> cls = null;        try {            //使用类加载器获取指定的类Class            cls = arg0.context.getClassLoader()                    .loadClass("com.open.cool.mydex1.MainActivity");        } catch (ClassNotFoundException e) {            e.printStackTrace();            return;        }//        //替换hook方法中的方法实现,XC_MethodReplacement        DexposedBridge.findAndHookMethod(cls, "test1", View.class, new XC_MethodReplacement() {            @Override            protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {                //TODO 替换后的方法实现                //.....                return null;            }        });    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

上面2个Demo两者的区别是:回调接口的类不同(XC_MethodHook和XC_MethodReplacement); 
//XC_MethodHook是XC_MethodReplacement的基类。

把MyPatch项目打包生成补丁apk文件,服务器通知客户端下载补丁文件apk,并使用

PatchResult result = PatchMain.load(this, “patch apk文件的路径”, null);
  • 1
  • 1

加载补丁apk,即时修复bug方法。

如果项目有代码混淆: 
需注意的部分

cls = arg0.context.getClassLoader()                    .loadClass("packageName+className");
  • 1
  • 2
  • 1
  • 2

packageName+className必须是混淆后的类名和方法名称。

在打release包时,在build/outputs/mapping/release/下面有mapping.txt,这个里面记录了混淆以前的类和混淆以后的类的一一对应关系(所以叫mapping.txt),所以每次发版以后要保留好mapping.txt文件,以便以后编写Patch。

支持的系统

RuntimeAndroid VersionSupportDalvik2.2Not TestDalvik2.3YesDalvik3.0NoDalvik4.0-4.4YesART5.0TestingART5.1NoARTMNo

注意:android4.4之后的版本都用Art取代了Dalvik,所以要hook Android4.4以后的版本就必须去适配Art虚拟机的机制。目前官方表示,为了适配Art的dexposed_l只是beta版,所以最好不要在正式的线上产品中使用它。


0 0