dynamic-load-apk 插件与宿主方法互调

时间:2021-09-17 23:09:32

新建项目 DlPluginHost,下载dynamic-load-apk源码

1.将dynamic-load-apk 文件夹中的lib做为module导入到DlPlginHost

dynamic-load-apk 插件与宿主方法互调

2.导入到PluginHost后,PluginHost引用lib,项目文件目录如下:

dynamic-load-apk 插件与宿主方法互调

3.新建插件项目DlPluginFirst,将dynamic-load-apk下的lib模块编译生成的jar,丢到插件的libs目录下:

dynamic-load-apk 插件与宿主方法互调

修改插件的 gradle 文件:

dynamic-load-apk 插件与宿主方法互调

注意这里用provided只是为了让插件通过编译,最终打包出来的插件是不会包含这个lib的,因为宿主中已经包含了这个lib,如果用 compile去包含,虽然可能同样可以达到效果,但是插件包莫名增加了一个lib的大小,没必要

4.这样宿主跟插件都有了,宿主app是根据demo做的,所有我们把 DlPluginFirst build生成apk,放在根目录的 DynamicLoadHost目录下:

dynamic-load-apk 插件与宿主方法互调

5.启动宿主app(DlPluginHost),点击Item,就可以正常拉起 插件app(DlPluginFirst)了:

dynamic-load-apk 插件与宿主方法互调

下面我们开始处理插件与宿主间的方法互调:

1.我们先看一下dynamic-load-apk的源码(以下简称DL):

dynamic-load-apk 插件与宿主方法互调

注意红色箭头部分:

很明显这里获取到插件的 classname ,然后通过loadPluginClass 获取该类的实例,loadPluginClass代码如下:

dynamic-load-apk 插件与宿主方法互调

1.这里可以拿到类的实例的话,那么接下来的问题就好处理了,很多人想到的第一个处理方法就是,通过反射出该类的方法然后直接进行调用,but,这样实验下来是有问题的 ,method 是可以反射出来的,但是调用的时候 报错:class 不一致,这个方法pass.

那怎么解决这个问题呢,我们可以这么做,我们做一个host与plugin共同引用的interface,然后通过interface来达到调用的效果:

1.在 host中新建module plugininterface , 并添加接口类:

dynamic-load-apk 插件与宿主方法互调

由于反射出插件类是在 dl-lib中实现的 ,所以lib添加依赖 plugininterface, 再把plugininterface生成jar 拷贝到 plugin的libs 中

dynamic-load-apk 插件与宿主方法互调

由于后面还需要做插件调用宿主方法的jar,这边我们将这个class修改名字 区分一下:

dynamic-load-apk 插件与宿主方法互调

由于host中包含这个 module 所以放在libs下 同样用 provided 引用,防止重复。

接下来就是考虑怎么调用的问题了,我们可以这么做,在DL的  DlPluginManager中增加一下方法:

dynamic-load-apk 插件与宿主方法互调

将plugin类反射出来,由于plugin类是继承 plugininterface 接口的,所以通过反射出来的 PluginInterface,中的接口是可以调用到插件的方法的!!!

plugin的代码如下:

dynamic-load-apk 插件与宿主方法互调

dynamic-load-apk 插件与宿主方法互调

由于dl是通过代理实现的 所有plugin中activity其实都是host中代理的activity,所以通过上面的方法实施获取插件版本号是获取不到的 ,因为代理的问题,获取的context总是host的,获取出来的版本号其实是host的版本号。

反射出来之后,我们通过host 开始调用插件的方法(这个方法直接反射plugin的方法,不走plugin activity中生命周期):

dynamic-load-apk 插件与宿主方法互调

最后查看log日志,的确是可以调用到的:

dynamic-load-apk 插件与宿主方法互调

宿主调用插件的方法,到此就结束了,想想插件怎么调用宿主的方法呢,其实套路是一样的,我们在host中新建一个 hostinterface module,

dynamic-load-apk 插件与宿主方法互调

注意hostinterface 提供给plugin 调用的包名,类名以及方法名都要一直,这样plugin才能调用到host的 HostMethod.,  hostinterface 中的方法只是 host中方法的空壳,只是为了让plugin能找到host的具体实现方法:

dynamic-load-apk 插件与宿主方法互调

具体实现还是在host中:

dynamic-load-apk 插件与宿主方法互调

同样我们把 hostinterface 的jar包拷贝出来丢到plugin中,修改jar包名称以作区分 :

dynamic-load-apk 插件与宿主方法互调

接下来DlPluginFist编译成jar,丢到根目录DynamicLoadHost中,启动host拉起 plugin:

dynamic-load-apk 插件与宿主方法互调

invokeHostMethod 对应的代码如下:

dynamic-load-apk 插件与宿主方法互调

执行结果,查看log,调用成功:

dynamic-load-apk 插件与宿主方法互调

这样host, plugin的互调就到这里结束了,下一章将 通过 dynamic-load-apk实现 host 显示插件悬浮窗,类似九游游戏sdk,悬浮球。

本章代码:

DlPluginHost.zip

DlFirstPlugin.zip