源码基于Android 11 API 30
BroadcastReceiver是一种消息型组件,用于在不同的组件或者是不同的应用之间传递信息。同样的BroadcastReceiver也不能被用户感知,BroadcastReceiver也叫广播,广播的注册有两种方式:静态注册和动态注册。静态注册是指在AndroidManifest中注册广播,这种广播在应用安装时会被系统解析,此种形式的广播不需要应用启动就可以收到相应的广播。动态注册广播需要通过Context.registerReceiver()来实现,并且在不需要的时候要通过Context.unRegisterReceiver()来解除广播,此种形态的广播必须要应用启动才能注册并接收广播,因为应用不启动就无法注册广播,无法注册广播就无法收到相应的广播。在实际开发中通过Context的一系列send方法来发送广播,被发送的广播会被系统发送给感兴趣的广播接收者,发送和接收过程的匹配是通过广播接收者的<intent-filter>来描述的。可以发现,BroadcastReceiver组件可以用来实现低耦合的观察者模式,观察者和被观察者之间可以没有任何耦合。由于BroadcastReceiver的特性,它不适合用来执行耗时操作。BroadcastReceiver组件一般来说不需要停止,它也没有停止的概念。
下面从广播的注册、发送与接收几个过程展开介绍。
1. 广播的注册
广播的注册分为动态注册与静态注册两种。静态注册的注册过程是在应用安装时由PackageManager-Service完成注册的。我们这里主要介绍动态注册的过程。下面是一个典型的动态注册、发送于接受广播的代码:
...
//通常需要自定义一个BroadcastReceiver,这里只是示例避免代码过长
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Do something
abortBroadcast();
}
};
IntentFilter intentFilter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcast);
intentFilter = new IntentFilter();
intentFilter.addAction("com.example.myapplication.DEMOBROADCAST");
registerReceiver(broadcastReceiver,intentFilter);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.myapplication.DEMOBROADCAST");
sendBroadcast(intent);
}
});
}
...
上面的代码可以明显的看到,广播的着册方法是registerReceiver,这个方法是在ContextWrapper中定义的,与Service的启动与绑定类似,registerReceiver方法有调用了mBase的方法,mBase的实现是ContextImpl,ContextImpl的registerReceiver方法在嵌套调用后最后调用了registerReceiverInternal方法,具体看下代码:
//ContextWrapper.java
...
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
...
//ContextImpl.java
...
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {//判断receiver是否存在
//判断mPackageInfo(LoadedApk类型)与Context是否都存在
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
//获取IIntentReceiver
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
//mPackageInfo不存在
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
//创建IIntentReceiver
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
//获取AMS调用registerReceiverWithFeature方法
final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
filter, broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
...
最后可以看到调用了AMS的registerReceiverWithFeature,上面代码中有一个重要变量rd,IIntentReceiver类型,这显然是一个Binder接口,具体实现在LoadedApk.ReceiverDispatcher.InnerReceiver:
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
...
}
回到AMS的registerReceiverWithFeature方法,方法比较长,核心处理添加了注释:
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, 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);
...
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
}
...
//根据传入的IntentFilter获取Action列表
Iterator<String> actions = filter.actionsIterator();
if (actions == null) {
ArrayList<String> noAction = new ArrayList<String>(1);
noAction.add(null);
actions = noAction.iterator();
}
// userIds表示应用程序的uid,对于Android系统来说,用户就是一个个的应用程序。
int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
while (actions.hasNext()) {
String action = actions.next();
for (int id : userIds) {
//根据Action列表与应用程序列表(userIds)获取所有粘性广播(StickyBroadcast)
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
if (stickies != null) {
//获取所有粘性广播的intent
ArrayList<Intent> intents = stickies.get(action);
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList<Intent>();
}
//保存粘性广播的intent
stickyIntents.addAll(intents);
}
}
}
}
}
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
// 查找匹配的粘性广播
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
// Don't provided intents that aren't available to instant apps.
if (instantApp &&
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
...
}
}
...
synchronized (this) {
...
//获取ReceiverList
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
//ReceiverList为空新建
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
//判断当前receiver是否超过允许的最的值
final int totalReceiversForApp = rl.app.receivers.size();
if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
throw new IllegalStateException("Too many receivers, total of "
+ totalReceiversForApp + ", registered for pid: "
+ rl.pid + ", callerPackage: " + callerPackage);
}
rl.app.receivers.add(rl);
} else {
...
}
}
//创建BroadcastFilter用来记录已注册的广播接收者信息
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
permission, callingUid, userId, instantApp, visibleToInstantApps);
//判断接收者列表ReceiverList中是否存在对应接收者,不存在则添加
if (rl.containsFilter(filter)) {
Slog.w(TAG, "Receiver with filter " + filter
+ " already registered for pid " + rl.pid
+ ", callerPackage is " + callerPackage);
} else {
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
//记录接收者,AMS全局变量,
//当AMS接收到广播时会从mReceiverResolver找到所有的接收者,实现注册的效果。
mReceiverResolver.addFilter(bf);
}
// 广播队列中入队所有将符合filter的粘性广播
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, null, -1, -1, false, null, null, OP_NONE, null, receivers,
null, 0, null, null, false, true, true, -1, false,
false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
return sticky;
}
}
以上就是广播注册的过程,具体的步骤在注释中一有所体现。
2. 广播的发送与接收
2.1 ContextImp 调用AMS
我们知道广播有标准广播(无序广播)、有序广播和粘性广播。下面还是以开始那个例子(标准广播)展开介绍。与广播的注册类似,首先是调用了ContextWraper的sendBroadcast:
...
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
...
sendBroadcast调用了ContextImp的sendBroadcast方法:
...
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false,
false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
...
上面的代码,很明显调用了AMS的broadcastIntentWithFeature方法:
public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle bOptions,
boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
//验证intent
intent = verifyBroadcastLocked(intent);
//获取应用程序进程信息
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
return broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, callingUid, callingPid, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
最后调用了AMS的broadcastIntentLocked方法,方法特别的长,这里这给出部分源码:
final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
@Nullable String callerFeatureId, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
@Nullable int[] broadcastWhitelist) {
...
//获取注册的粘性广播
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
if (stickies == null) {
stickies = new ArrayMap<>();
mStickyBroadcasts.put(userId, stickies);
}
//找到符合当前Action的广播
ArrayList<Intent> list = stickies.get(intent.getAction());
if (list == null) {
list = new ArrayList<>();
stickies.put(intent.getAction(), list);
}
...
//接收者存在
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
//获取广播队列,获取BroadcastRecord信息
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId,
allowBackgroundActivityStarts, timeoutExempt);
...
queue.enqueueOrderedBroadcastLocked(r);
//执行广播schedule
queue.scheduleBroadcastsLocked();
}
...
return ActivityManager.BROADCAST_SUCCESS;
}
从上面的代码可以看出,最后AMS调用了BroadcastQueue的scheduleBroadcastsLocked方法。
2.2 ContextImp 调用AMS调用BroadcastReceiver
接上一节的代码继续看,BroadcastQueue的scheduleBroadcastsLocked方法:
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
scheduleBroadcastsLocked方法内部,通过BroadcastHandler发送了一个消息:BROADCAST_INTENT_MSG,这肯定交由对应的handleMessage方法处理,我们再看下BroadcastHandler的handleMessage方法:
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG ["
+ mQueueName + "]");
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
}
}
上面代码很明显,处理BROADCAST_INTENT_MSG类型消息后,调用了processNextBroadcast方法,然后又调用了processNextBroadcastLocked方法,方法比较长,特殊处理也很多,这里只关注下标准广播的处理:
final void processNextBroadcast(boolean fromMsg) {
synchronized (mService) {
processNextBroadcastLocked(fromMsg, false);
}
}
...
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
...
if (fromMsg) {//已经处理了BROADCAST_INTENT_MSG类型的消息
mBroadcastsScheduled = false;
}
// 处理无序广播,也就是标准的广播
while (mParallelBroadcasts.size() > 0) {
//获取广播
r = mParallelBroadcasts.remove(0);
...
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering non-ordered on [" + mQueueName + "] to registered "
+ target + ": " + r);
//广播发送给相应的接收者
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
...
}
下面继续看下deliverToRegisteredReceiverLocked方法:
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
....//省略一堆验证
// 有序广播的处理.
if (ordered) {
r.receiver = filter.receiverList.receiver.asBinder();
r.curFilter = filter;
filter.receiverList.curBroadcast = r;
r.state = BroadcastRecord.CALL_IN_RECEIVE;
if (filter.receiverList.app != null) {
r.curApp = filter.receiverList.app;
filter.receiverList.app.curReceivers.add(r);
mService.updateOomAdjLocked(r.curApp, true,
OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
}
}
try {
if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
"Delivering to " + filter + " : " + r);
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
//如果是有序广播,继续传给下一个接收者.
if (ordered) {
skipReceiverLocked(r);
}
} else {
r.receiverTime = SystemClock.uptimeMillis();
maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
//各种检查及验证后最终调用的方法
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
if (r.allowBackgroundActivityStarts && !r.ordered) {
postActivityStartTokenRemoval(filter.receiverList.app, r);
}
}
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
} catch (RemoteException e) {
...
}
}
继续看performReceiveLocked方法:
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null) {//验证应用程序进程是否存在
if (app.thread != null) {//验证应用程序进程是否已运行
// If we have an app thread, do the call through that so it is
// 应用程序进程存在,执行一个单向请求
try {
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
} catch (RemoteException ex) {
...
}
} else {
throw new RemoteException("app.thread must not be null");
}
} else {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
上面的应用程序进程app自然是ApplicationThread,继续看其方法scheduleRegisteredReceiver:
//这个方法是为了保证所有接收者的分发是正确有序的
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
上面代码很简洁,调用了IIntentReceiver的performReceive方法,IIntentReceiver是通过LoadedApk中的InnerReceiver实现的:
final static class InnerReceiver extends IIntentReceiver.Stub {
...
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
rd = mDispatcher.get();
}
...
if (rd != null) {
//ReceiverDispatcher的调用
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
...
}
}
...
}
上面的IIntentReceiver通过AIDL实现进程间通信,最后调用了ReceiverDispatcher的performReceive方法:
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
//封装广播的intent信息
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
...
}
if (intent == null || !mActivityThread.post(args.getRunnable())) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
mActivityThread.post(args.getRunnable())的mActivityThread是个Handler,具体实现是H类,这里将args.getRunnable()作为参数传入Handler的post方法,看下Args的getRunnable方法:
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
...
//获取AMS
final IActivityManager mgr = ActivityManager.getService();
final Intent intent = mCurIntent;
...
try {
//创建BroadcastReceiver
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
//调用onReceive方法
receiver.onReceive(mContext, intent);
} catch (Exception e) {
...
}
...
};
}
}
代码最后创建了一个BroadcastReceiver并调用了onReceive方法。