Activity免注册跳转

要实现免注册跳转需要解决的问题:

1、未注册的activity怎么通过系统验证

2、怎么在handleMessage中监听 LAUNCH_ACTIVITY 的消息



解决的方法

1、使用动态代理activity替换未注册activity,使其通过系统验证

2、hook到ActivityThread、mH变量、H类;在Callback中监听 LAUNCH_ACTIVITY 的消息



//第一步:

	Class<?> clazz = Class.forName("android.app.ActivityManagerNative");
        //第一种 方式获取 通过gDefault
        Field gDefault = clazz.getDeclaredField("gDefault");
        gDefault.setAccessible(true);
        //静态类型字段不用传入所属对象
        Object defaultValue = gDefault.get(null);
        Class<?> aClass = Class.forName("android.util.Singleton");
        Field mInstace = aClass.getDeclaredField("mInstance");
        mInstace.setAccessible(true);
        Object iActivityManagerValue = mInstace.get(defaultValue);
//        第二种方式
//        Method getDefault = clazz.getDeclaredMethod("getDefault"); //获取的是子类 ActivityManagerProxy 
//        getDefault.setAccessible(true);
//        //获取主线程对象
//        Object defaultValue = getDefault.invoke(null);
//        Class<?> aClass = Class.forName("android.util.Singleton");
//        Field mInstace = aClass.getDeclaredField("mInstance");
//        mInstace.setAccessible(true);
//        Object iActivityManagerValue = mInstace.get(defaultValue); //不能获取
//创建新的接口对象
          Class<?> iActivityManagerProxy = Class.forName("android.app.IActivityManager");      
          AmsInvocationHandler handler = new AmsInvocationHandler(iActivityManagerValue);     
          Object IActivityManager = Proxy.newProxyInstance(context.getClassLoader(), new Class[]{iActivityManagerProxy}, handler);
//        替换掉原有的IActivityManager      
           mInstace.set(defaultValue, IActivityManager);



        
/**
 * 拦截未注册的Activity ,替换为已 注册代理Activity
 */

 class AmsInvocationHandler implements InvocationHandler {

        private Object iActivityManagerValue;

        public AmsInvocationHandler(Object iActivityManagerValue) {
            this.iActivityManagerValue = iActivityManagerValue;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//          替换系统方法
            if ("startActivity".contains(method.getName())) {

                int index = 0;
                for (int i = 0; i < args.length; i++) {
                    //找到 参数中的意图
                    if (args[i] instanceof Intent) {
                        index = i;//非法意图的索引
                        break;
                    }
                }

                for (int i = 0; i < args.length; i++) {
                    Log.e("tag", "args:" + args[i]);
                }

                Intent proxyIntnet = new Intent();
                ComponentName cn = new ComponentName(context, proxyActivity);
                proxyIntnet.setComponent(cn);
                //将 非法的意图附带在合法的意图中 作为参数
                proxyIntnet.putExtra("oldIntent", (Intent)args[index]);
                args[index] = proxyIntnet;
                return method.invoke(iActivityManagerValue, args);
            }

            return method.invoke(iActivityManagerValue, args);
        }
    }
//第二步:
 // 获取到回调 使用插件意图 替换
    public void hookSystemHandler() {
        try {

            Class<?> aClass = Class.forName("android.app.ActivityThread");

            //获取ActivityThread 方式一 (api17 以上适用)

//            Field sCurrentActivityThread = aClass.getDeclaredField("sCurrentActivityThread");
//            sCurrentActivityThread.setAccessible(true);
//            ActivityThreadValue = sCurrentActivityThread.get(null);
//            获取ActivityThread 方式二 
            Method currentActivityThreadMethod = aClass.getDeclaredMethod("currentActivityThread");
            currentActivityThreadMethod.setAccessible(true);
            //获取主线程对象
            Object activityThread = currentActivityThreadMethod.invoke(null);
            //ActivityThread 的mH字段
            Field mH = aClass.getDeclaredField("mH");
            mH.setAccessible(true);
            Handler handlerObject = (Handler) mH.get(activityThread);
            //获取H类中mCallback字段

            Field mCallbackField = Handler.class.getDeclaredField("mCallback");
            mCallbackField.setAccessible(true);

		//将处理后的 Handler对象替换系统的
mCallbackField.set(handlerObject, new ActivityThreadHandlerCallback(handlerObject));
     } catch (ClassNotFoundException e) {   
         e.printStackTrace();     
   } catch (IllegalAccessException e) {  
          e.printStackTrace();     
   } catch (NoSuchFieldException e) {    
        e.printStackTrace();      
  } catch (NoSuchMethodException e) {         
   e.printStackTrace();      
  } catch (InvocationTargetException e) {   
         e.printStackTrace();    
    }  
  }  
  class ActivityThreadHandlerCallback implements Handler.Callback {   
     Handler handler;     
   public ActivityThreadHandlerCallback(Handler handler) { 
           super();        
    this.handler = handler;      
  }        @Override       
 public boolean handleMessage(Message msg) {   
         //把非法intent替换回来        
    if (msg.what == 100) {         
       try {              
      handleLaunchActivity(msg);    
            } catch (NoSuchFieldException e) {     
               e.printStackTrace();           
     } catch (IllegalAccessException e) {     
               e.printStackTrace();          
      }    
        }        
    handler.handleMessage(msg);  
          return true;      
  }  
  }
	//替换原有的验证前的合法意图
    private void handleLaunchActivity(Message msg) throws NoSuchFieldException, IllegalAccessException {
        Object obj = msg.obj; //获取当前ActivityRecord的记录信息
        Field intentField = obj.getClass().getDeclaredField("intent");
        intentField.setAccessible(true);

        Intent proxyIntent = (Intent) intentField.get(obj);
        Intent oldIntent = proxyIntent.getParcelableExtra("oldIntent");

        //判断如果使用的动态代理,就使用插件intent替换掉
        if (oldIntent != null) {
            proxyIntent.setComponent(oldIntent.getComponent());
        }
    }

//第三步
在Application中调用
AmsUtils amsUtils = new AmsUtils(ProxyActivity.class, this);
amsUtils.hookSystemHandler();
try {
    amsUtils.hookAms();
} catch (Exception e) {
    e.printStackTrace();
}





1、api18 以下没有 sCurrentActivityThread 静态变量,但是都有一个 静态方法 currentActivityThread 返回值为 ActivityThread,可以通过返回值 获取

2、未注册的类(OtherActivity)只能直接继承自Activity才能正常跳转,继承AppCompatActivity 显示找不到




发布了49 篇原创文章 · 获赞 17 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章