插件化技术:宿主访问插件资源

2,080 阅读2分钟

本文同步自wing的地方酒馆

最近在搞插件化,16年很火的东西,我又拖了1年才来研究,哈哈哈,正确下一个热门技术能提前一些吧。

今天想跟大家讨论一下我在研究插件化过程中,遇到的一个容易混淆的点,那就是资源访问。

首先感谢下在插件化道路上的老司机,无私的奉献资料。

看过很多插件化的文章,都提到了一大痛点是资源访问的问题。解决方法很通用,都是通过反射使用 AssetManager 的 addAssetPath 方法,把插件apk路径添加进去。再把系统的resource替换掉,就可以访问到资源了。

这时候,大部分博客会添加一句:

资源访问是一个痛点,所以用以上方式解决R引用

但是这里有一个及其容易混淆的地方,就是 “解决了R引用”,那么到底实际上是解决了谁的R引用问题呢? 是宿主访问插件的资源呢,还是插件访问插件的资源呢?

为了讲解清楚我来画一张图:

如上图在没有替换掉Resources的时候。

由于每个apk只能访问自己的res,所以这时候使用hook newActivity创建的Activity对象,是无法访问到插件res的,虽然这个Activity确实是插件中的Activity,但是实际上是加载在宿主里的resource,所以也就是有个隔离,因此必须替换resource

当AddPath以后,关系就变成了如上图的关系,此时创建的Activity的实例,也就是宿主的顺理成章能拿到插件的资源。

混淆点就是在这里,在之前网上博客文章中说的解决了资源访问问题,实际上是指插件Activity不能访问插件本身的资源,而不是说宿主Activity访问插件的资源

宿主Activity如何访问插件资源?

经过大量搜索,跟小伙伴讨论得知可以通过如下方式获得插件资源:

getResources().getString(getResources()
.getIdentifier("plugin", "string","com.your.name")),
 Toast.LENGTH_SHORT).show();

这个方法是根据资源名称,来获取资源id,所以就可以根据id拿到资源了。

比如上面的例子就是通过getIdentifier()方法寻找名称为plugin的string资源。当然你要提供插件的包名。