启动未注册activity。8.0系统报错如下:
05-06 10:25:31.312 13973-13973/com.bolex.androidhookstartactivity W/System.err: java.lang.NoSuchFieldException: No field gDefault in class Landroid/app/ActivityManagerNative; (declaration of 'android.app.ActivityManagerNative' appears in /system/framework/framework.jar)
at java.lang.Class.getDeclaredField(Native Method)
如何启动一个未注册过的Activity
几乎所有的插件化都会要的一个需求,启动一个未注册的Activiy,即加载插件包中的Activity,并且主应用并不知道插件应用中会有什么Activity,这是各个插件化框架主力解决的问题之一。
今天我们学习一下占坑式插件化框架的启动Activity原理。
关于动态代理的知识,了解过Retrofit
的源码的或者看过Java设计模式之代理模式
的高级使用的,应该都了解了。本章不做介绍,主介绍hook+反射
Hook是什么?
Hook直白点说就是拦截方法,自己对其参数等进行修改,或者替换返回值,达到自己不可告人的目的的一件事。
寻找Hook点
对于启动Activity,老实说光startActivity
便有很多要说,很多文章会带着你一直追到ActivityManagerService
中的若干个方法,最后再调用本地的ActivityThread
里面的方法去启动本进程的Activity。
所以光上面的流程我们看出,我们把要启动的Activity信息发给AMS,其做了各种检查各种操作后真正让Activity
启动的还是我们的ActivityThread
实现欺骗
欺骗系统就欺骗两个地方,我们在AndroidManifest
里面申明一个假Activity
,然后在启动真实Activity
的地方,将Intent
里面的Activity
替换成我们已经注册过的。再在ActivityThread
launch Activity的时候,替换成我们需要启动的便实现了启动一个未注册过的Activity的效果。
实行代码如下:
安卓系统8.0以下手机启动未注册activity方法
private static void hookActivityManager() {try {// 获取gDefaultClass activityManagerClass = Class.forName("android.app.ActivityManagerNative");Field gDefaultField = activityManagerClass.getDeclaredField("gDefault");gDefaultField.setAccessible(true);Object gDefault = gDefaultField.get(null);// 获取mIntanceClass singletonClass = Class.forName("android.util.Singleton");Field mInstanceField = singletonClass.getDeclaredField("mInstance");mInstanceField.setAccessible(true);Object mInstance = mInstanceField.get(gDefault);// 替换mIntanceObject proxy = Proxy.newProxyInstance(mInstance.getClass().getClassLoader(),new Class[]{Class.forName("android.app.IActivityManager")},new IActivityManagerHandler(mInstance));mInstanceField.set(gDefault, proxy);} catch (Exception e) {Log.e("hook", "err", e);}
}
Android系统8.0及以上手机启动方法就不再调用ActivityManagerNative类,而是ActivityManager类,部分代码如下
Class activityManagerClass = Class.forName("android.app.ActivityManager");
demo链接:https://download.csdn.net/download/meixi_android/11161392
云盘demo链接:https://pan.baidu.com/s/1CjWTpmueLrBMpxlsR7Jjew
在线回复云盘密码:QQ1085220040