1.定义一个lib,然通信的两个apk都依赖它,这个依赖的lib提供了双方通信的接口。我们的test项目就命令lib为stander。因为这个test是处理activity的,所以就只放了一个接口,对应了activity的7个生命周期回调方法。
2.创建一个主工程,创建一个代理activity,加载插件的activity的时候,通过代理activity来绕过AMS的AndroidManifest配置检查。主工程中,需要先点击一下控件,触发加载其他apk的操作。具体加载包括apk中所有的类的加载和资源的加载,类的加载通过新建DexClassLoader()来实现,资源的加载通过反射给调用AssetManager中的方法,addAssetPath,从而给AssetManager设置了值
![](https://i-blog.csdnimg.cn/blog_migrate/3e1893e4d2e2375cd5423215dfd7cef3.jpeg)
3.启动插件activity的操作。通过代理activity来占位,也叫做插桩。也就是宿主加载插件的activity时候总是会加载代理activity,在代理activity里面做一些真正的加载的操作。具体的实现就是,在开启代理activity之前,通过PackageManager和apk包的路径来拿到插件包中的所有activity的信息。然后把想要打开的activity的类名信息,通过Intent的方式,传递给代理activity。这儿需要保证已经申请并通过了访问外部存储的权限。
![](https://i-blog.csdnimg.cn/blog_migrate/f80ea9a046c96f565eb196a90e768a9f.jpeg)
代理activity中通过反射的方式,来实现插件包中的activity的创建。同时转换创建出来的activity为我们在步骤1中定义的接口对象。通过接口对象来注入context给插件apk中的activity。之后调用接口对象的onCreate()方法。因为插件activity中实现的接口有这个方法,所以插件Activity()方法就被执行了。这儿需要注意,插件的生命周期方法都是我们通过代理接口对象来进行手动调用的。不再调用系统的生命周期方法了。同时对于需要用到context的地方,将都使用我们的宿主应用的上下文。
![](https://i-blog.csdnimg.cn/blog_migrate/362ecff5e89a364bf919ae858c11e99f.jpeg)
4.对于插件activity的内部跳转,需要我们使用宿主环境的context来进行跳转。前面也说过,插件内部是没有自己的上下文去调用context的方法的。所以在插件中,我们也要定义自己的startActivity()方法。
![](https://i-blog.csdnimg.cn/blog_migrate/73449dc021776504694e7f2527927577.jpeg)
通过对传递的Intent对象进行处理,插件activity的startActivity()方法实现再次跳到宿主应用的代理activity,然后在代理activity中,也要重写对应的方法startActivity()
![](https://i-blog.csdnimg.cn/blog_migrate/47cda3712bfd2c49ae86863be709dbd9.png)
在该方法中,拿到插件activity的intent的信息。然后回调宿主代理activity的onCreate()方法。里面再次通过反射方式实现对象创建,接着转换activity对象为约定的接口对象,然后这个接口对象再次注入宿主activity的上下文。通过调用该接口对象的生命周期方法,实现插件内部的界面跳转。