在安卓中,广播的接收有动态注册和静态注册两种方式,这篇博客沿着动态广播的注册、发送和接收三条路线开展探究。
动态广播的注册
首先,先整理一波动态注册的鸟瞰图
从图中可以看到
1)代码中调用的egisterReceiver(BroadcastReceiver, IntentFilter),在ContextImpl.java中实现(关于Context和Activity的关联,可以翻看我的前一篇博文),实际真正是ActivityManagerService去注册广播。
2)再通过跨进程通讯(这里采用的是binder),来获取用注册广播的服务,该服务的实现类在ActivityServiceManager.java。
开始从源码进行分析:
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
接下来看registerReceiverInternal方法:
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
//IIntentReceiver是用于后续跨进程分发广播时的binder对象
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
...
//获取IIntentReceiver对象
//mPackageInfo是 当前进程的LoadedApk实例,LoadedApk用于记录 当前进程apk的本地信息。
// **--->1**
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
...
}
try {
//调用ams的registerReceiver(),并把IIntentReceiver类型的rd对象传入
// **--->2**
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
...
}
看看 (注释1处) LoadedApk.java里的getReceiverDispatcher()
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
if (registered) {
//从mReceivers取出 该context 所对应的 map
//了解下mReceivers的对象类型
//private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new ArrayMap<>();
//如果该 context ,首次注册广播,则 map 为空
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
if (rd == null) {
//新建ReceiverDispatcher对象
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);//存入map 于 mReceivers中
}
//map 存放广播接收者和对应的广播跨进程binder对象
map.put(r, rd);
}
}
...
//返回 rd 维护的 IIntentReceiver实例
return rd.getIIntentReceiver();
}
}
<