Android实现免安装APK插件(三)

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的生命周期,到这里有些大功告成的感觉,但是一运行,马上就是资源报错,宿主可不知道还有插件的资源存在。

猜你喜欢

转载自blog.csdn.net/rhythmjay/article/details/80705777