一、了解Hook概念
Hook是钩子的意思。我们知道应用运行依赖系统各种各样的API。当某些API不能满足我们的要求时,如果想修改它的功能,使之能满足我们的要求。就要用到Hook技术。
在Android开发中,我们同样能利用Hook的原理让系统某些方法运行时,实际调用的是我们自己定义的方法,从而满足我们的要求。
二、利用java反射实现简单的Hook——将在Manifest中注册的MainActivity替换成没在Manifest中注册过的TestActivity。
2.1)新建一个Android项目,创建MainActivity和TestActivity,TestActivity不在AndroidManifest.xml中配置。
2.2)写一个InstrumentationHook继承系统的Instrumentation,并重写父类的newActivity方法
- public class InstrumentationHook extends Instrumentation {
- @Override
- public Activity newActivity(Class<?> clazz, Context context, IBinder token,
- Application application, Intent intent, ActivityInfo info,
- CharSequence title, Activity parent, String id,
- Object lastNonConfigurationInstance) throws InstantiationException,
- IllegalAccessException {
- Log.d(this, " CustomInstrumentation#newActivity call 1");
- return super.newActivity(clazz, context, token, application, intent, info,
- title, parent, id, lastNonConfigurationInstance);
- }
- @Override
- public Activity newActivity(ClassLoader cl, String className, Intent intent)
- throws InstantiationException, IllegalAccessException,
- ClassNotFoundException {
- Log.d(this, " CustomInstrumentation#newActivity call 3 parmas className:" + className + " intent:" + intent.toString());
- Activity activity = createActivity(intent);
- if (activity != null) {
- return activity;
- }
- return super.newActivity(cl, className, intent);
- }
- /*可以在createActivity拦截替换某个activity,下面自是一个简单例子*/
- protected Activity createActivity(Intent intent) {
- String className = intent.getComponent().getClassName();
- Log.d(this, "createActivity className=" + className);
- if ("hook.jason.com.androidhook.MainActivity".equals(className)) {
- try {
- Class<? extends Activity> PluginActivity = (Class<? extends Activity>) Class
- .forName("hook.jason.com.androidhook.TestActivity");
- return PluginActivity.newInstance();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return null;
- }
- }
2.3)获取当前应用的ActivityThread,并替换系统默认定义的mInstrumentation实例
- /**
- * Created by zeyu,Jia
- */
- public class HookManager {
- static Object activityThreadInstance;
- public static void init() throws ClassNotFoundException,
- NoSuchMethodException, IllegalAccessException,
- IllegalArgumentException, InvocationTargetException {
- Class<?> activityThread = Class.forName("android.app.ActivityThread");
- Method currentActivityThread = activityThread
- .getDeclaredMethod("currentActivityThread");
- activityThreadInstance = currentActivityThread.invoke(null);
- }
- public static void injectInstrumentation() throws NoSuchFieldException,
- IllegalAccessException, IllegalArgumentException {
- Log.i(HookManager.class, " start injectInstrumentation");
- Field field_instrumentation = activityThreadInstance.getClass()
- .getDeclaredField("mInstrumentation");
- field_instrumentation.setAccessible(true);
- InstrumentationHook instrumentationHook = new InstrumentationHook();
- field_instrumentation.set(activityThreadInstance, instrumentationHook);
- }
- }
2.4)在MyApplication的onCreate里替换ActivityThread里的mInstrumentation变量
- public class MyApplication extends Application {
- @Override
- public void onCreate() {
- try {
- Log.d(this, " onCreate starting init");
- HookManager.init();
- HookManager.injectInstrumentation();
- } catch (Exception e) {
- Log.d(this, " onCreate e:" + e.toString());
- }
- super.onCreate();
- }
- }
2.5)运行后界面如下:
2.6)具体log如下:
03-18 17:28:55.621 436-436/hook.jason.com.androidhook D/AndroidHook: MyApplication : onCreate starting init
03-18 17:28:55.623 436-436/hook.jason.com.androidhook I/AndroidHook: Class : start injectInstrumentation
03-18 17:28:55.633 436-436/hook.jason.com.androidhook D/AndroidHook: InstrumentationHook : CustomInstrumentation#newActivity call 3 parmas className:hook.jason.com.androidhook.MainActivity intent:Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=hook.jason.com.androidhook/.MainActivity }
03-18 17:28:55.633 436-436/hook.jason.com.androidhook D/AndroidHook: InstrumentationHook : createActivity className=hook.jason.com.androidhook.MainActivity
03-18 17:28:55.674 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onCreate
03-18 17:28:55.752 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onResume
03-18 17:28:55.775 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onPause
03-18 17:28:55.789 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onAttachedToWindow
03-18 17:39:55.838 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onRestart
03-18 17:39:55.855 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onResume
03-18 17:40:26.044 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onPause
从log中可以看出MainActivity的onCreate方法根本没有运行,走的是没有配置的TestActivity类