context 是当前activity
public class InstrumentationProxy extends Instrumentation {
private static 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 option) {
Log.d(TAG, "Hook successful " + 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, option);
} catch (Exception e) {
throw new RuntimeException();
}
}
public void replaceApplicationContextInstrumentation(Activity activity) {
try {
Field field = Activity.class.getDeclaredField("mInstrumentation");
field.setAccessible(true);
Instrumentation instrumentation = (Instrumentation) field.get(activity);
Instrumentation instrumentationProxy = new InstrumentationProxy(instrumentation);
field.set(activity, instrumentationProxy);
} catch (Exception e) {
e.printStackTrace();
}
}
context是application的context
hook点不同,这个context由contextimpl具体实现
mMainTHread.getInstrumentation().exexStartActvity(...)
主要改变在replace方法上,Instrumentation类没有改变。
public void replaceApplicationContextInstrumentation() {
try {
Class<?> activityThreadClazz = Class.forName("android.app.ActivityThread");
Field activityThreadField = activityThreadClazz.getDeclaredField("sCurrentActivityThread");
activityThreadField.setAccessible(true);
Object currentActivityThread = activityThreadField.get(null);
Field mInstrumentationField = activityThreadClazz.getDeclaredField("mInstrumentation");
mInstrumentationField.setAccessible(true);
Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);
Instrumentation mInstrumentationProxy = new InstrumentationProxy(mInstrumentation);
mInstrumentationField.set(currentActivityThread, mInstrumentationProxy);
} catch (Exception e) {
e.printStackTrace();
}
}