广播分为动态注册和静态注册,其中静态注册是在AndroidManifeat中声明,然后应用安装时由PackageManagerService来注册。动态注册是调用registerReceiver方法来注册。
下面来看看动态注册的时序图
当调用registerReceiver的时候会调用到ContextImpl的registerReceiverInternal方法
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
这里会先判断LoadedApk类型的mPackageInfo是否为null,context是否为null,如果都不为null,则通过mPackageInfo的getReceiverDispatcher方法获取IIntentReceiver。IIntentReceiver是一个Binder接口,用于广播的跨进程通信。他的实现在LoadedApk.ReceiverDispatcher.InnerReceiver。否则会创建一个新的IIntentReceiver。最后调用AMS的registerReceiver方法并将获取到的IIntentReceiver传入。
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
enforceNotIsolatedCaller("registerReceiver");
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
final boolean visibleToInstantApps
= (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
int callingUid;
int callingPid;
boolean instantApp;
synchronized(this) {
if (caller != null) {
//获取到ProcessRecord,这个用来描述注册广播的Activity所在进程的信息
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when registering receiver " + receiver);
}
if (callerApp.info.uid != SYSTEM_UID &&
!callerApp.pkgList.containsKey(callerPackage) &&
!"android".equals(callerPackage)) {
throw new SecurityException("Given caller package " + callerPackage
+ " is not running in process " + callerApp);
}
//获取uid,pid
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
}
instantApp = isInstantApp(callerApp, callerPackage, callingUid);
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
//获取所有设置的action,如果没有,则添加一个null进去
Iterator<String> actions = filter.actionsIterator();
if (actions == null) {
ArrayList<String> noAction = new ArrayList<String>(1);
noAction.add(null);
actions = noAction.iterator();
}
// Collect stickies of users
int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
//遍历所有action
while (actions.hasNext()) {
String action = actions.next();
for (int id : userIds) {
//获取该id对的到所有黏性广播,id为应用程序id
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
if (stickies != null) {
ArrayList<Intent> intents = stickies.get(action);
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList<Intent>();
}
//将对应的黏性广播加入到stickyIntents中
stickyIntents.addAll(intents);
}
}
}
}
}
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
//遍历所有粘性广播的Intent
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
// 免安装应用直接跳过
if (instantApp &&
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
//将所有的intent加入到allSticky中
allSticky.add(intent);
}
}
}
//如果传过来的IIntentReceiver为null,则会直接把第一个黏性广播的Intent传给客户端。
//这里应该是静态注册的情况,动态注册IIntentReceiver不为null
Intent sticky = allSticky != null ? allSticky.get(0) : null;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);
if (receiver == null) {
return sticky;
}
synchronized (this) {
//判断一下注册广播的Activity是否还存在,如果已经不存在,直接返回null。
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
//获取广播接收者列表,ReceiverList是继承于ArrayList的集合
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
//如果列表为null,则直接创建一个
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
//如果前面获取的ProcessRecord不为null,则将新创建的ReceiverList
//添加到ProcessRecord的receivers当中
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
//将新创建的ReceiverList也加入到mRegisteredReceivers中
//mRegisteredReceivers是一个map,key的类型是IBinder,这里传入的是IIntentReceiver
//这个IIntentReceiver是注册广播的时候客户端传过来的InnerReceiver
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
...
//将传过来的IntentFilter和获取到的ReceiverList等参数用来创建BroadcastFilter
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
将新创建的BroadcastFilter添加到ReceiverList中
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
//将BroadcastFilter添加到IntentResolver类型的mReceiverResolver中
//当AMS收到广播的时候就可以从mReceiverResolver中找到对应的广播接收者。
//到这里注册广播就完成了
mReceiverResolver.addFilter(bf);
//将和BroadcastFilter匹配的所有粘性广播加入到队列
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);
final int stickyCount = allSticky.size();
for (int i = 0; i < stickyCount; i++) {
Intent intent = allSticky.get(i);
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, null,
null, -1, -1, false, null, null, AppOpsManager.OP_NONE, null, receivers,
null, 0, null, null, false, true, true, -1);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
return sticky;
}
}
到这里动态广播的注册就完成了。