3、 Activity生命周期怎么实现
虽然startActivity正常了,但是这不是要启动的Activity,岂不是做了无用功。然而事情往往没那么简单,既然系统服务那关已经过了,我们得自己做点事情了。Activity的创建及生命周期都是在自己进程中完成的,所以ActivityThread这个类似乎可以帮我们做事情。
注意到ActivityThread中mH完成了Activity的创建和生命周期的事件处理,所以我们只需要在mH处理事件前,把壳Activity又替换为要启动的Activity不就可以了。所以这又涉及到消息拦截了,我们来看下handleMessage如何拦截:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
正常情况mCallback为null,我们只需要设置一个mCallback就可以拦截消息,把msg中intent取出来替换为新的intent,接着交给handleMessage继续处理就可以了。如下:
public void invokeActivityThread() {
try {
Class clazz = Class.forName("android.app.ActivityThread");
Method method = clazz.getMethod("currentActivityThread");
Object object = method.invoke(null);
Field field = clazz.getDeclaredField("mH");
field.setAccessible(true);
Object handler = field.get(object);
Class handlerClass = Class.forName("android.os.Handler");
Field callback = handlerClass.getDeclaredField("mCallback");
callback.setAccessible(true);
callback.set(handler, mCallBack);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
private Handler.Callback mCallBack = new Handler.Callback() {
private static final int LAUNCH_ACTIVITY = 100;
@Override
public boolean handleMessage(Message msg) {
if (msg.what == LAUNCH_ACTIVITY) {
Log.i(TAG, "LAUNCH_ACTIVITY");
try {
Class clazz = Class.forName("android.app.ActivityThread$ActivityClientRecord");
Field field = clazz.getDeclaredField("intent");
field.setAccessible(true);
Intent orig = (Intent) field.get(msg.obj);
String className = orig.getComponent().getClassName();
Log.i(TAG, "className = " + className);
Log.i(TAG, "mForkActivity.getName() = " + mForkActivity.getName());
if (TextUtils.equals(className, mForkActivity.getName())) {
String plugActivity = orig.getStringExtra(LoadDexUtils.EXTRA_PLUG_ACTIVITY);
Log.i(TAG, "plugActivity = " + plugActivity);
Intent intent = new Intent();
ComponentName componentName = new ComponentName(LoadDexUtils.PLUG_PACKAGE_NAME, plugActivity);
intent.setComponent(componentName);
field.set(msg.obj, intent);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
return false;
}
};
由于我们只是替换了intent中的component内容,系统照样会帮助我们完成Activity的生命周期,到这里有些大功告成的感觉,但是一运行,马上就是资源报错,宿主可不知道还有插件的资源存在。