动态代理、Hook - 1835434698/1835434698.github.io GitHub Wiki
动态代理
1、代理的对象是一个接口并且是某个类的成员变量。
这里举例:PopupWindow
1、首选获取成员变量的真名。
其中mWindowManager是别名即让程序员来叫的名字。其真名则是PopupWindow.class.getDeclaredField("mWindowManager")获取到的即对程序来叫的名字。
Field windowManagerField = PopupWindow.class.getDeclaredField("mWindowManager");
2、设置setAccessible(true);
windowManagerField.setAccessible(true);
3、获取到真正的接口对象mWindowManager
其中popupWindow为传递过来的真实对象,不是自己构建的,除非其是静态的。
mWindowManager = windowManagerField.get(popupWindow);
4、创建WindowManager的动态代理对象proxy
//创建WindowManager的动态代理对象proxy
Object proxy = Proxy.newProxyInstance(Handler.class.getClassLoader(), new Class[]{WindowManager.class}, this);
5、实现InvocationHandler的invoke。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Logger.d(TAG, "invoke");;
try {
//拦截方法mWindowManager.addView(View view, ViewGroup.LayoutParams params);
if (method != null && method.getName() != null && method.getName().equals("addView")
&& args != null && args.length == 2) {
Logger.d(TAG, "invoke - addView");;
//获取WindowManager.LayoutParams,即:ViewGroup.LayoutParams
WindowManager.LayoutParams params = (WindowManager.LayoutParams) args[1];
//禁止录屏
setNoScreenRecord(params);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return method.invoke(mWindowManager, args);//mWindowManager是3中获取的
}
6、注入动态代理对象proxy
//注入动态代理对象proxy(即:mWindowManager对象由proxy对象来代理)
windowManagerField.set(popupWindow, proxy);
2、代理对象是一个接口,
举例NotificationManager
1、首选获取成员函数的真名。
Method getService = NotificationManager.class.getDeclaredMethod("getService");
2、设置setAccessible(true);
getService.setAccessible(true);
3、首选获取NotificationManager对象,因为是唯一,所以可以自己获取。
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
4、得到被代理对象
sOriginService = getService.invoke(notificationManager);
5、得到被代理的类
Class iNotiMngClz = Class.forName("android.app.INotificationManager");
6、创建代理类
Object proxyNotiMng = Proxy.newProxyInstance(context.getClass().getClassLoader(), new
Class[]{iNotiMngClz}, this);
7、实现InvocationHandler的invoke。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.d(TAG, "invoke(). method:" + method);
String name = method.getName();
Log.d(TAG, "invoke: name=" + name);
if (args != null && args.length > 0) {
for (Object arg : args) {
Log.d(TAG, "invoke: arg=" + arg);
}
}
// 操作交由 sOriginService 处理,不拦截通知
return method.invoke(sOriginService, args);
// return null;
}
8、得到1中获取的方法赋值给的成员变量sService,并且设置setAccessible(true);
Field sServiceField = NotificationManager.class.getDeclaredField("sService");
sServiceField.setAccessible(true);
9、设置代理
sServiceField.set(notificationManager, proxyNotiMng);
Class<?> WindowManagerImpl = Class.forName("android.view.WindowManagerImpl");
// WindowManagerImpl.getMethod("getService");//这是获取方法的
Field field = WindowManagerImpl.getDeclaredField("mGlobal");//这是获取成员变量的