dexposed框架总结

这篇文章主要写一下我使用 dexposed 的一个简单流程。

一开始就不多废话了,总之dexposed是阿里巴巴新开源的一个非侵入式的AOP框架。

GitHub传送门:https://github.com/alibaba/dexposed

以下翻译自 GitHub:

1Dexposed是什么:

Dexposed Android应用开发一个功能强大且非侵入式的运行时AOP(面向方向编程)框架,他是基于开源的Xposed框架实现的。

Dexposed AOP实现是完全非侵入式的,没有使用任何注解处理器,编织器或字节码重写。集成Dexposed框架很简单,只需要使用一行代码,在程序的初始化阶段加载一个小小的JNI库即可。

Dexposed 不仅可以hook你自己的程序代码,也可以hook你的应用程序中调用的Android框架中的函数。开发者经常严重的依赖Fragment碎片化来开发程序,这个功能对这一情况大有用处。

机遇动态加载的机制,运行中的 app可以加载一小段经过编译的Java AOP代码,在不需要重新启动程序的情况下改变目标app的行为。

2、经典实用场景

1、经典AOP编程

2、仪表化(Instrumentation),用于测试,性能监控等

3、在线热修复,用于修复,紧急漏洞,安全漏洞、

4SDK hook,以提供更好的开发体验。

3、集成

这部分是我个人集成详细过程,和官方给的方法可能有出入。(因为我按它说的做根本没弄好(⊙﹏⊙)b

首先先把 GitHub上的东西下载下来解压后打开,目录如下:


Android Studio上新建项目DexposedDemo。把dexposed\src\main目录下的jniLibs文件夹拷贝到自己项目的src/main目录下。在自己的项目中添加一个包,取名为com.taobao.android.dexposed ,接着把dexposed\src\main\java\com\taobao\android\dexposed  下的源码都复制到com.taobao.android.dexposed包中。。添加后,在Project视图中,目录结构如下:


接下来检测设备是否支持 dexposed 框架,根据官方文档,因在程序中今早进行检测,所以这段代码被放到MyApplication类中。

package com.bajie.dexposed;
import android.app.Application;
import android.os.Build;
import android.util.Log;
import com.taobao.android.dexposed.DexposedBridge;
public class MyApplication extends Application {
    private static final String TAG = "MyApplication";
    private boolean mCanDexposed = false;
    @Override
    public void onCreate() {
        super.onCreate();
        mCanDexposed = DexposedBridge.canDexposed(this);
        Log.i(TAG, "canDexposed = " + mCanDexposed);
    }
    public boolean canDexposed() {
        return mCanDexposed;
    }
}

别忘了在 manifest文件中配置application哦:

<application
        android:name=".MyApplication" />

4.基本使用方法

针对一个方法,可以用三种方法对它进行改造,分别是:方法前,方法后,替代方法。

比如有一个显示 Toast的方法如下:

private void showToast() {
    toast = Toast.makeText(this, "this is a toast", Toast.LENGTH_SHORT);
}

我们想在这个方法执行前或执行后在一个 TextView中显示消息,可以这样实现:

private void hookShowToast() {
    DexposedBridge.findAndHookMethod(this.getClass(), "showToast", new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            super.beforeHookedMethod(param);
        }

        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            super.afterHookedMethod(param);
            tv.setText("showToast() afterHooked");

        }
    });
}

Dexposed 框架还可以替换掉整个函数:

private void methodReplacement() {
    if(canDexposed) {
        DexposedBridge.findAndHookMethod(this.getClass(), "showToast", new XC_MethodReplacement() {
            @Override
            protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                Toast.makeText(MainActivity.this, "this is a replacement toast", Toast.LENGTH_SHORT).show();
                return null;
            }
        });
    }
}

Dexposed 还拥有热补丁的方法。就是在项目上线的时候,在不发布新版本的情况下,动态修复线上的bug的功能。

首先先建一个 Patch项目作为补丁,引入dexposedbridge.jarpatchloader.jar,在目标项目中加入com.taobao.android.dexposed.patch 下面的源码,这里需要注意,需要在目标项目中加入读SdCard的权限。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

首先在 目标项目中添加此方法

public void runPathApk() {
    String fullPath = Environment.getExternalStorageDirectory() + File.separator + "patch.apk";
    setText("\n" + fullPath);
    PatchResult result = PatchMain.load(this, fullPath, null);
    if (result.isSuccess()) {
        setText("patch success!");
    } else {
        setText("\n" + result.getErrorInfo());
    }
}

其中 fullPath为补丁apk的路径,可以自定义,当然在路径中你需要放入补丁apk

接着在补丁中添加类:

public class ToastPach implements IPatch {

    @Override
    public void handlePatch(PatchParam patchParam) throws Throwable {
        final Class<?> cls = patchParam.context.getClassLoader().loadClass("com.bajie.dexposed.MainActivity");
        DexposedBridge.findAndHookMethod(cls, "showToast", new XC_MethodReplacement() {
            @Override
            protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                Toast.makeText((Activity)param.thisObject, "success", Toast.LENGTH_LONG).show();
                return null;
            }
        });
    }
}

补丁项目中只需要实现此类就可以,然后把补丁项目打包,放到相应的位置,运行原来的项目,在这里,showToast方法将被替换掉。

需要注意几点是,我当时用gradle2.0.2-beta6进行运行的时候,没办法使用,后来改成gradle:1.5.0就可以运行了。
























版权声明:本文为C529836078原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。