使用反射技术在Android平台上实现本进程内Activity切换时的拦截
2014-05-26 23:08
537 查看
有需求需要统计本应用内各Activity切换的次数与频度等,由于之前架构设计并未让所有Activity共同继承于一个基础类,同时TabActivity、FragmentActivity等的使用也没法让它们使用同一个父类,因此在本着不想改动每个Activity的目的下,我们摸索出了一个使用反射的方式来实现本应用内部Activity切换时的拦截,具体说来就是拦截本应用中每一个Activity的onPause和onResume事件。
基本思路:
访问ActivityThread的静态方法currentActivityThread拿到当前ActivityThread的实例,再通过反射拿到其private的mInstrumentation对象,并设置一个新的对象给此Field。该新的对象继承自Instramentation,重写了callActivityonPause和callActivityonResume方法,并在方法体内调用了之前旧的Instrumentation对象的同名方法。
ActivityThreadHooker.java
HookInstrumentation.java
使用时只需要在Application初始化时,new一个ActivityThreadHooker即可。切换Activity时,会在logcat中打印出“OnPause Intercept here.”以及“OnResume Intercept here.”等信息。
基本思路:
访问ActivityThread的静态方法currentActivityThread拿到当前ActivityThread的实例,再通过反射拿到其private的mInstrumentation对象,并设置一个新的对象给此Field。该新的对象继承自Instramentation,重写了callActivityonPause和callActivityonResume方法,并在方法体内调用了之前旧的Instrumentation对象的同名方法。
ActivityThreadHooker.java
package com.testme.testinstr; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.app.Instrumentation; import android.util.Log; public class ActivityThreadHooker { private static final String TAG = "ATHOOK"; private static ActivityThreadHooker instance = null; private HookInstrumentation mHookInstr = null; private Instrumentation mOldInstr = null; private static boolean mHooked = false; public static boolean getHooked() { return mHooked; } public ActivityThreadHooker() throws Throwable { synchronized (ActivityThreadHooker.class) { if (instance != null) throw new Exception("Only one ActivityThreadHooker instance can be created."); instance = this; } mHookInstr = new HookInstrumentation(); try { initHook(); } catch (NoSuchFieldException ensf) { ensf.printStackTrace(); return; } catch (IllegalArgumentException eilar) { eilar.printStackTrace(); return; } catch (IllegalAccessException eilac) { eilac.printStackTrace(); return; } catch (ClassNotFoundException ecnf) { ecnf.printStackTrace(); return; } catch (NoSuchMethodException ensm) { ensm.printStackTrace(); return; } mHooked = true; } private void initHook() throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException { Class<?> atClass = Class.forName("android.app.ActivityThread"); Method cat = atClass.getMethod("currentActivityThread"); Object at = null; try { at = cat.invoke(atClass, new Object[0]); } catch (InvocationTargetException eit) { return; } if (at == null) return; Field instrField = atClass.getDeclaredField("mInstrumentation"); instrField.setAccessible(true); mOldInstr = (Instrumentation) instrField.get(at); boolean res = mHookInstr.initOldInstr(mOldInstr); if (!res) { Log.e(TAG, "Error process Old Instrumentation."); return; } instrField.set(at, mHookInstr); Log.d(TAG, "Hook success!"); } }
HookInstrumentation.java
package com.testme.testinstr; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.app.Activity; import android.app.Instrumentation; import android.util.Log; public class HookInstrumentation extends Instrumentation { private static final String TAG = "ATHOOK"; private Instrumentation mOldInstr = null; private Method methodResume = null; private Method methodPause = null; private void obtainMethods() throws NoSuchMethodException { if ( mOldInstr == null ) return; Class<?> inClass = mOldInstr.getClass(); methodResume = inClass.getMethod("callActivityOnResume", Activity.class); methodPause = inClass.getMethod("callActivityOnPause", Activity.class); } @Override public void callActivityOnPause(Activity activity) { Log.d(TAG, "OnPause Intercept here."); if ( methodPause != null ) { try { methodPause.invoke(mOldInstr, activity); } catch (IllegalArgumentException e) { e.printStackTrace(); return; } catch (IllegalAccessException e) { e.printStackTrace(); return; } catch (InvocationTargetException e) { e.printStackTrace(); return; } } else super.callActivityOnPause(activity); } @Override public void callActivityOnResume(Activity activity) { if ( methodResume != null ) { try { methodResume.invoke(mOldInstr, activity); } catch (IllegalArgumentException e) { e.printStackTrace(); return; } catch (IllegalAccessException e) { e.printStackTrace(); return; } catch (InvocationTargetException e) { e.printStackTrace(); return; } Log.d(TAG, "OnResume Intercept here."); } else super.callActivityOnResume(activity); } public boolean initOldInstr(Instrumentation oldInstr) { mOldInstr = oldInstr; try { obtainMethods(); return true; } catch (NoSuchMethodException e) { e.printStackTrace(); return false; } } }
使用时只需要在Application初始化时,new一个ActivityThreadHooker即可。切换Activity时,会在logcat中打印出“OnPause Intercept here.”以及“OnResume Intercept here.”等信息。
相关文章推荐
- Android编程实现两个Activity相互切换而不使用onCreate()的方法
- android使用viewPager和Fragment实现滑动切换activity!
- android背景图片点击效果的实现(android平台下使用点九PNG技术)
- Android 自定义activity切换动画实现,overridePendingTransition的使用详解
- Android中使用overridePendingTransition实现Activity切换动画
- android overridePendingTransition()使用(切换activity动画实现)
- 【黑马Android】(08)activity生命周期/横竖屏切换的生命周期/任务栈的概念/广播接收者ip拨号器/进程的优先级&为什么使用服务
- H5 Web App 的性能测试平台 : 使用 Frida 实现 AOP 拦截 hook Android 原生应用的方法
- Android 实现同个Activity中存在多个Fragment多次切换之后依次返回(一)(Fragment回退栈简单使用)
- Hook技术activity启动过程中拦截(无需在androidmanifest文件注册即可使用)
- Android 实现同个Activity中存在多个Fragment多次切换之后依次返回(一)(Fragment回退栈简单使用)
- Android开发使用Activity嵌套多个Fragment实现横竖屏切换功能的方法
- android 使用BroadcastReceiver实现开机启动Service或Activity
- 市面上所有号称"虚拟机","防火墙"的实时监控杀毒软件无一不是使用的IFSHOOK技术.但是同时也有一些朋友不断写MAIL给我打听如何实现读写的监控.下面给出用VTOOLSD写的代码.也就是所有实时杀毒软件的奥秘.同时,很多拦截文件操作的软件,例如对目录加
- Android通过共享用户ID来实现多Activity进程共享
- Android通过共享用户ID来实现多Activity进程共享
- android平台下使用点九PNG技术
- [Android]使用ActivityGroup来切换Activity和Layout
- 【Android游戏开发之五】游戏注册界面Demo-实现两个Activity之间的切换与数据交互!
- 【Android游戏开发之五】游戏注册界面Demo-实现两个Activity之间的切换与数据交互!