Android过滤startActivity请求

原理:

context.startActivity跳转间接使用Instrumentation对象execStartActivity方法,而Instrumentation存在于ActivityThread中,有趣的是在应用启动后,有且只有一个ActivityThread对象,那么Instrumentation也只有一个,也就是说不管哪个Context使用startActivity方法都是间接使用同一个Instrumentation对象。既然要过滤startActivity请求,那么可以通过替换原来的Instrumentation来达到我们的目的。这里使用代理模式,在做具体实现之前,先执行我们设定的动作(过滤)。

注:如果使用JDK自带的代理处理模块,在Android上不能运行,因为Android使用的Dalvik字节码,而不是java字节码,需要使用第三方库dexmaker。


完整项目下载


1、实现代理接口

作用:在执行execStartActivity方法前先过滤。

public class MyInvocationHandler implements InvocationHandler {
	
	private Instrumentation instrumentation;
	
	public void bind(Instrumentation instrumentation) {
		this.instrumentation = instrumentation;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		
		Object result = null;
		
		boolean flag = false;
		
		if ("execStartActivity".equals(method.getName())) {
			Intent intent = (Intent) args[4];
			String className = intent.getComponent().getClassName();
			Log.v("class-name:", String.valueOf(className));
			if (className != null && "com.example.select.TestB".equals(className)) {
				flag = true;
				Log.v("filter", String.valueOf(className));
			}
		}
		
		/*如果不是我们过滤的意图,那么按照原来的方式运行.*/
		if (!flag) {
			result= method.invoke(instrumentation, args);  
		}
		
		return result;
	}
	
}

2、替换Instrumentation

作用:自定义Instrumentation功能

	private void selectActivity() {
		
		try {
			
			Class
   
    c = Class.forName("android.app.ActivityThread");
			Field mInstrumentationField = c.getDeclaredField("mInstrumentation");
			mInstrumentationField.setAccessible(true);
			
			// 通过currentActivityThread静态方法获得ActivityThread对象.
			Object activityThread = c.getMethod("currentActivityThread").invoke(null);
			Instrumentation instrumentation = (Instrumentation) mInstrumentationField.get(activityThread);
			
			MyInvocationHandler myMyInvocationHandler = new MyInvocationHandler();
			myMyInvocationHandler.bind(instrumentation); //绑定Instrumentation
			
			/*生成Instrumentation代理对象*/
			Instrumentation minInstrumentation = ProxyBuilder.forClass(Instrumentation.class).dexCache(getApplicationContext().getDir("dx", Context.MODE_PRIVATE))
			         .handler(myMyInvocationHandler)
			         .build();
			
			/*替换原来的Instrumentation对象.*/
			mInstrumentationField.set(activityThread, minInstrumentation);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值