The fourth part of Android plug-in development [load plug-in Activity]

introduction


In the previous article , we introduced how to obtain the resource of the plug-in and load its resources. The example supports loading material resources under the res folder, such as animations, pictures, layouts, strings, etc. This article introduces how the host jumps to the activity of the plug-in.

There are many ways to jump to the Activity of the plug-in, but so far it is a very complicated thing. The common methods are the host-agent Activity mode and the host dynamic creation Activity mode. The difference between the two is that the host agent does not need to register the Activity in the host, and all jumps are completed by a puppet Activity. The advantage of this is that the plug-in development can be completed without changing the host too much, but the plug-in Activity does not enjoy the life cycle provided by the system. , all of its life cycles must be passed by the host through reflection. The advantage of dynamic creation is that Activity has its own life cycle, but it must be registered in the host AndroidManifest file in advance. This article introduces a simple proxy Activity pattern. ( More details can be found here )

Demo creation


  1. Create BaseActivity.java in the PluginA project , the key code is as follows:
public class BaseActivity extends Activity {
    
    
    ....
    // 通过隐式调用宿主的ProxyActivity
    public static final String PROXY_VIEW_ACTION = "h3c.pluginapp.ProxyActivity";
    // 因为插件的Activity没有Context,所以一切与Context的行为都必须通过宿主代理Activity实现!
    protected Activity mProxyActivity;
    public void setProxy(Activity proxyActivity) {
        mProxyActivity = proxyActivity;
    }

    @Override
    public void setContentView(int layoutResID) {
        mProxyActivity.setContentView(layoutResID);
    }

    @Override
    public View findViewById(int id) {
        return mProxyActivity.findViewById(id);
    }

    // 插件的startActivity其实就是调用宿主开启另一个ProxyActivity
    public void startActivity(String className) {
        Intent intent = new Intent(PROXY_VIEW_ACTION);
        intent.putExtra("Class", className);
        mProxyActivity.startActivity(intent);
    }
    ....
}
  1. Create AActivity.java and BActivity.java in the PluginA project . Let AActivity click to jump to BActivity.
  2. Recompile PluginA and replace Apk into the host.
  3. Create ProxyActivity.java in the host project and register it in the AndroidManifest file. key code:
public class ProxyActivity extends Activity {
    
    
    ....
    // 因为插件Activity获得的是宿主的Context,这样就拿不到自己的资源,所以这里要用插件的Resource替换ProxyActivity的Resource!
    private Resources mBundleResources;

    @Override
    protected void attachBaseContext(Context context) {
        replaceContextResources(context);
        super.attachBaseContext(context);
    }

    public void replaceContextResources(Context context){
        try {
            Field field = context.getClass().getDeclaredField("mResources");
            field.setAccessible(true);
            if (null == mBundleResources) {
                mBundleResources = AssertsDexLoader.getBundleResource(context,                    context.getDir(AssertsDexLoader.APK_DIR, Context.MODE_PRIVATE).
                                getAbsolutePath() + "/app-debug.apk");
            }
            field.set(context, mBundleResources);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ProxyActivity要加载的插件Activity名字
        String className = getIntent().getStringExtra("Class");
        try {
            Class<?> localClass = AssertsDexLoader.loadClass(className);
            Constructor<?> localConstructor = localClass
                    .getConstructor(new Class[] {});
            Object instance = localConstructor.newInstance(new Object[] {});
            // 把当前的傀儡Activity注入到插件中
            Method setProxy = localClass.getMethod("setProxy",                new Class[] { Activity.class });
            setProxy.setAccessible(true);
            setProxy.invoke(instance, new Object[] { this });

            // 调用插件的onCreate()
            Method onCreate = localClass.getDeclaredMethod("onCreate",
                    new Class[] { Bundle.class });
            onCreate.setAccessible(true);
            onCreate.invoke(instance, new Object[] { null });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    ....
}
  1. jump
Intent intent = new Intent(MainActivity.this, ProxyActivity.class);
intent.putExtra("Class", "h3c.plugina.AActivity");
startActivity(intent);

explain


The host jumps to ProxyActivity, creates a plug-in Activity according to the incoming parameter reflection, injects the plug-in Resource into itself, and injects itself into the plug-in Activity to realize life cycle synchronization.

The above Demo can only realize the jump from the host to the AActivity of the plug-in, and from AActivity to BActivity. Mainly due to the synchronization problem of the life cycle, if you want to complete more functions, you need to improve the supplement of related methods as needed!

Summarize


This article briefly describes the main implementation of Android plug-in development, and you can get a general idea of ​​how Android implements plug-in development. For specific examples, please refer to dynamic-load-apk of Baidu singwhatiwanna

Generally speaking, the development of this kind of plug-in is difficult, not to mention the high learning cost. It must follow specific coding standards during development, and it will take a lot of time for the joint debugging of the host and the plug-in. Considering that most applications will be associated with the database, Use the network request library, image loading library, etc., and many network requests also require account login to obtain tokens, which shows that the plug-in development support in this mode is limited.

Next, we will see whether Qihoo 360's DroidPlugin and Wequick 's Small can solve the problem of difficult-to-use plug-ins.

Guess you like

Origin blog.csdn.net/h3c4lenovo/article/details/50739032