Android 轻量插件化:BroadcastReceiver 的代理其实有两种情况

BroadcastReceiver 是四大组件里面代码最短的一个,但插件化以后有一个非常明显的分叉:

动态注册和 Manifest 注册,要分开看。

1. 动态 Receiver

如果插件自己调用:

1
context.registerReceiver(receiver, filter);

我们其实可以让插件的 PluginContext 接管这个方法。

插件写:

1
registerReceiver(myReceiver, filter);

最终变成框架自己的注册逻辑。

例如:

1
2
3
4
5
6
7
public void registerReceiver(
PluginReceiver receiver,
IntentFilter filter) {

ProxyReceiver proxy = new ProxyReceiver(receiver);
hostContext.registerReceiver(proxy, filter);
}

这里最简单的方式甚至不需要修改系统。

2. ProxyReceiver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ProxyReceiver extends BroadcastReceiver {

private final PluginReceiver target;

public ProxyReceiver(PluginReceiver target) {
this.target = target;
}

@Override
public void onReceive(Context context, Intent intent) {
target.onReceive(
new PluginContext(context, pluginManager),
intent
);
}
}

所以动态 Receiver 是最好处理的。

3. Manifest Receiver 就不同了

插件 Manifest 里可能有:

1
2
3
4
5
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

插件没有安装,PackageManager 就不会替它建立这份注册信息。

因此系统广播到来的时候,不会找到插件 Receiver。

4. 最轻量的办法

启动插件的时候读取插件 APK 的 Manifest 信息,把 Receiver 定义解析出来。

然后由宿主统一注册代理 Receiver:

1
2
3
4
5
6
7
8
9
10
11
plugin Manifest

PackageManager.getPackageArchiveInfo()

解析 receivers

宿主 registerReceiver()

ProxyReceiver

插件 Receiver

例如:

1
2
3
4
5
PackageInfo info = packageManager
.getPackageArchiveInfo(
apkPath,
PackageManager.GET_RECEIVERS
);

拿到:

1
info.receivers

再读取每个 Receiver 的信息。

不过 PackageInfo 主要告诉我们有哪些组件,真正的 intent-filter 还需要进一步解析 APK Manifest,工程实现时建议专门做一个 PluginManifestParser

5. 一个容易忽略的问题

并不是所有广播都可以随便动态注册。

Android 不同版本对隐式广播、后台行为以及动态 Receiver 都做过不少限制。

所以这个教学框架不要承诺“任何系统广播都能工作”。

我们先验证普通自定义广播:

1
2
Intent intent = new Intent("com.demo.PLUGIN_EVENT");
context.sendBroadcast(intent);

这样最容易观察整个链路。

6. Receiver 的核心其实很简单

只要记住:

1
2
3
动态注册:PluginContext 接管注册

静态注册:解析 Manifest + 宿主注册 ProxyReceiver

这两个方案组合起来,就能覆盖大部分教学场景。

真正困难的四大组件其实还在后面——ContentProvider。

因为 Provider 的创建时机和系统启动过程更特殊。

坚持原创技术分享,您的支持将鼓励我继续创作!