从《Android进阶解密》上面学习到的一个Hook示例。
定义:
HOOK可以是一个方法或对象,用于劫持请求,例如A请求B,然后可以在中间加入C,在A的请求中加入一些处理,例如改变参数或者返回值,起到欺上瞒下的作用。在应用程序中可以通过代理来实现。
实现示例
startActivity中间会调用Instrumentation的execStartActivity,那么可以实现一个代理类InstrumentationProxy,用于中途改变参数或者拿到返回值后再做一些想要的处理,这里是示例代码,这里的HoOK作为一个对象:
- 首先实现代理类InstrumentationProxy
public class InstrumentationProxy extends Instrumentation {
private final String TAG = "InstrumentationProxy";
Instrumentation instrumentation;
public InstrumentationProxy(Instrumentation instrumentation) {
this.instrumentation = instrumentation;
}
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options){
//加入劫持代码
Log.d(TAG,"Hook成功" + "----who:"+who);
try {
//然后再继续调用原来的方法,通过反射
Method execStartActivity = Instrumentation.class.getDeclaredMethod("execStartActivity",Context.class,
IBinder.class,IBinder.class,Activity.class,Intent.class,int.class,Bundle.class);
return (ActivityResult) execStartActivity.invoke(instrumentation,who,contextThread,token,target,intent,requestCode,options);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//也可以改变返回值
return null;
}
}
- Activity中调用
mInstrumentation是Activity的成员变量,首先通过反射拿到成员变量,然后将它的值设置为代理类,那么之后再调用startActivity就用到了InstrumentationProxy的execStartActivity方法。
public void replaceActivityInstrumentation(Activity activity){
try {
//得到Activity的mInstrumentation对象
Field field = Activity.class.getDeclaredField("mInstrumentation");
//取消Java的权限控制检查
field.setAccessible(true);
Instrumentation instrumentation = (Instrumentation) field.get(activity);
Instrumentation proxy = new InstrumentationProxy(instrumentation);
field.set(activity,proxy);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}