代理模式
--摘自《android插件化开发指南》
1.设计模式
2.远程代理(AIDL)
3.保护代理(权限控制)
比如:老板的秘书
4.虚代理(图片占位)
比如:微信图片查看,先用模糊的小图占位,然后替换成清晰的大图
5.协作开发
A要用到B中的方法,但是B还没有开发完,那么B就提供一个假的方法,返回假的死值,等开发完成再替换掉
6.四大组件和AMS通信都是通过AMN/AMP进行的
启动Activity:AcitivityManagerNative.getDefault().startActivity();
发送消息sendBroadcast:ActivityManagerNative.getDefault().broadcastIntent()
7.对AMN的Hook
import java.lang.reflect.Field; import java.lang.reflect.Proxy; /** * @author weishu * @date 16/3/7 */ public final class HookHelper { public static void hookActivityManager() { try { //获取AMN的gDefault单例gDefault,gDefault是静态的 Object gDefault = RefInvoke.getStaticFieldObject("android.app.ActivityManagerNative", "gDefault"); // gDefault是一个 android.util.Singleton对象; 我们取出这个单例里面的mInstance字段,IActivityManager类型 Object rawIActivityManager = RefInvoke.getFieldObject( "android.util.Singleton", gDefault, "mInstance"); // 创建一个这个对象的代理对象iActivityManagerInterface, 然后替换这个字段, 让我们的代理对象帮忙干活 Class<?> iActivityManagerInterface = Class.forName("android.app.IActivityManager"); Object proxy = Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), new Class<?>[] { iActivityManagerInterface }, new HookHandler(rawIActivityManager)); //把Singleton的mInstance替换为proxy RefInvoke.setFieldObject("android.util.Singleton", gDefault, "mInstance", proxy); } catch (Exception e) { throw new RuntimeException("Hook Failed", e); } } }
import android.util.Log; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Arrays; /** * 一个简单的用来演示的动态代理对象 (PMS和AMS都使用这一个类) * 只是打印日志和参数; 以后可以修改参数等达到更加高级的功能 */ class HookHandler implements InvocationHandler { private static final String TAG = "HookHandler"; private Object mBase; public HookHandler(Object base) { mBase = base; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Log.d(TAG, "hey, baby; you are hooked!!"); Log.d(TAG, "method:" + method.getName() + " called with args:" + Arrays.toString(args)); return method.invoke(mBase, args); } }
8.PMS是系统服务,是没办法Hook的,只能修改它在APP进程中的代理对象,它是PackageManagaer类型的
import android.content.Context; import android.content.pm.PackageManager; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author weishu * @date 16/3/7 */ public final class HookHelper { public static void hookPackageManager(Context context) { try { // 获取全局的ActivityThread对象 Object currentActivityThread = RefInvoke.getStaticFieldObject("android.app.ActivityThread", "sCurrentActivityThread"); // 获取ActivityThread里面原始的 sPackageManager Object sPackageManager = RefInvoke.getFieldObject(currentActivityThread, "sPackageManager"); // 准备好代理对象, 用来替换原始的对象 Class<?> iPackageManagerInterface = Class.forName("android.content.pm.IPackageManager"); Object proxy = Proxy.newProxyInstance(iPackageManagerInterface.getClassLoader(), new Class<?>[] { iPackageManagerInterface }, new HookHandler(sPackageManager)); // 1. 替换掉ActivityThread里面的 sPackageManager 字段 RefInvoke.setFieldObject(currentActivityThread, "sPackageManager", proxy); // 2. 替换 ApplicationPackageManager里面的 mPm对象 PackageManager pm = context.getPackageManager(); RefInvoke.setFieldObject(pm, "mPM", proxy); } catch (Exception e) { throw new RuntimeException("hook failed", e); } } }
import android.util.Log; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Arrays; /** * 一个简单的用来演示的动态代理对象 (PMS和AMS都使用这一个类) * 只是打印日志和参数; 以后可以修改参数等达到更加高级的功能 */ class HookHandler implements InvocationHandler { private static final String TAG = "HookHandler"; private Object mBase; public HookHandler(Object base) { mBase = base; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Log.d(TAG, "hey, baby; you are hooked!!"); Log.d(TAG, "method:" + method.getName() + " called with args:" + Arrays.toString(args)); return method.invoke(mBase, args); } }
Hook用到了动态代理的思想