• 代理模式


    --摘自《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用到了动态代理的思想

  • 相关阅读:
    java主函数的含义
    this关键字简单应用
    如何将util.Date转化为sql.Date
    利用JavaScript来实现省份—市县的二级联动
    通过Ajax异步提交的方法实现从数据库获取省份和城市信息实现二级联动(xml方法)
    折半查找(java)(边学习边更新)
    第五章 上
    Jframe关闭窗口时的事件
    C#退出程序自动重新启动
    Extjs4.0 开发笔记与Easyui的整合
  • 原文地址:https://www.cnblogs.com/anni-qianqian/p/10088655.html
Copyright © 2020-2023  润新知