代理模式
--摘自《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用到了动态代理的思想
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2017-12-08 更新手机图库