通过这篇文章,我们来梳理一下 BroadcastReceiver 的工作原理以及其中我们应该注意的细节
BroadcastReceiver 注册整体流程
BroadcastReceiver 的注册分为静态注册和动态注册
由于 Goolge 规定在 Android 7.0 以上的系统中不能静态注册 BroadcastReciver了 (即使你静态注册了 BroadcastReciver,该 BroadcastReciver 也不会运行)
对于我们开发者而言,可以直接忽略 BroadcastReceiver 的静态注册了
因此本篇博客只分析 BroadcastReceiver 动态注册流程
总体流程如下图:
流程其实很简单,就是将 BroadcastReciver 的相关信息保存到 AMS 中就完成动态注册了
Broadcast 发送整体流程
Broadcast 有几种类型:无序广播、有序广播和粘性广播,三者相比各自具有不同的特性,但它们的发送流程是类似的
为了方便理清整体流程,因此本篇博客只分析最简单的无序广播的发送流程
总体流程如下图:
这里我默认 BroadcastReciver 是通过动态注册的,因此 BroadcastReciver 运行在 UI 主线程中 (动态注册的 BroadcastReciver 都是运行在 UI 主线程中)
Broadcast 的发送主要由 AMS 管理,AMS 会将所要发送的 Broadcast 信息与所有已注册的 BroadcastReciver 信息 (权限 + IntentFilter) 进行比对,将广播发送给满足条件的 BroadcastReciver
由于 BroadcastReciver 运行在其他进程中,AMS 需要 AIDL 调用 BroadcastReciver 运行所在进程,传递 intent 等信息,并最终调用 BroadcastReceiver 的 onReceive()
函数
源码
BroadcastReceiver 注册流程
ContextImpl.registerReceiver()
// frameworks/base/core/java/android/app/ContextImpl.java
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
{
return registerReceiver(receiver, filter, null, null);
}
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler
){
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext());
}
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, // scheduler = null
Context context
){
IIntentReceiver rd = null;
// if 命中
if (receiver != null)
{
// APK 包信息不为空 且 上下文也不为空,if 命中
if (mPackageInfo != null && context != null)
{
if (scheduler == null)
{
scheduler = mMainThread.getHandler();
}
// 调用 LoadedApk 的 getReceiverDispatcher 函数,
// 从 mReceivers 缓存中获取 BroadcastReceiver 的 Binder 通信接口
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
}
else
{
......
}
}
// AIDL 调用 ActivityManagerService 的 registerReceiver 函数
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
}
所有可用 (已注册的) 的 BroadcastReceiver 信息都保存在 mReceivers 缓存中
mReceivers 是一个 ArrayMap,以 Context 为 key,以 ReceiverDispatcher 为 value
可以把 ReceiverDispatcher 理解为是一个对于 BroadcastReceiver 及其 Binder 通信接口的封装类
ActivityManagerService.registerReceiver()
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter,
String permission, int userId
){
......
synchronized (this)
{
......
// 判断该 BroadcastReceiver 是否已经注册
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
// rl = null,表示该 BroadcastReceiver 还没有注册
if (rl == null)
{
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
......
// 将该 BroadcastReceiver 的 Binder 通信接口缓存
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
......
// 创建该 BroadcastReceiver 的 IntentFilter 对象
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId);
rl.add(bf);
// 将该 IntentFilter 对象缓存
mReceiverResolver.addFilter(bf);
......
}
}
Broadcast 发送流程
ContextImpl.sendBroadcast()
// frameworks/base/core/java/android/app/ContextImpl.java
public void sendBroadcast(Intent intent)
{
......
// AIDL 调用 ActivityManagerService 的 broadcastIntent 函数
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null,
false, false, getUserId());
......
}
ActivityManagerService.broadcastIntent()
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle options,
boolean serialized, boolean sticky, int userId
){
synchronized(this)
{
// 验证 intent 是否合法
intent = verifyBroadcastLocked(intent);
......
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, null, serialized, sticky,
callingPid, callingUid, userId);
......
return res;
}
}
ActivityManagerService.verifyBroadcastLocked()
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
final Intent verifyBroadcastLocked(Intent intent)
{
// 如果 intent 含有文件描述符,则抛出异常,防止出现泄漏
if (intent != null && intent.hasFileDescriptors() == true)
{
throw new IllegalArgumentException("File descriptors passed in Intent");
}
int flags = intent.getFlags();
// 如果 APP 进程正在启动中
if (!mProcessesReady)
{
// 如果 flag 设置了 FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
// (APP 启动检查时只接受动态注册的 BroadcastReceiver)
if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0)
{
}
// 如果 flag 没有设置 FLAG_RECEIVER_REGISTERED_ONLY,则抛出异常
// (只接受动态注册的 BroadcastReceiver)
else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0)
{
throw new IllegalStateException("Cannot broadcast before boot completed");
}
}
if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0)
{
throw new IllegalArgumentException("Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
}
return intent;
}
ActivityManagerService.broadcastIntentLocked()
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp,
Bundle options, boolean ordered, boolean sticky, int callingPid,
int callingUid, int userId
){
intent = new Intent(intent);
// 添加 FLAG_EXCLUDE_STOPPED_PACKAGES 标志 (广播不会发送给已经停止的 APP 应用)
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// 将动态注册的 BroadcastReceiver 和静态注册的 BroadcastReceiver
// 按照优先级高低缓存在不同的集合中,再将这两个集合合并到 receivers 集合中
// 其中的代码细节与主流程无关,有兴趣可以自行了解
......
// receivers 集合包含所有已注册的 BroadcastReceiver,if 命中
if ((receivers != null && receivers.size() > 0) || resultTo != null)
{
// 获取 BroadcastQueue
BroadcastQueue queue = broadcastQueueForIntent(intent);
// 创建 BroadcastRecord 并传入 receivers 进行记录
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId);
......
queue.scheduleBroadcastsLocked();
}
return ActivityManager.BROADCAST_SUCCESS;
}
BroadcastQueue.scheduleBroadcastsLocked()
// frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
public void scheduleBroadcastsLocked()
{
......
// 发送消息 (BROADCAST_INTENT_MSG) 给 BroadcastQueue 中的内部类 BroadcastHandler (Handler)
// 从 Binder 线程切换到主线程执行
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
......
}
BroadcastHandler.handleMessage()
// frameworks/base/services/core/java/com/android/server/am/BroadcastQueue$BroadcastHandler.java
public void handleMessage(Message msg)
{
switch (msg.what)
{
case BROADCAST_INTENT_MSG: {
......
processNextBroadcast(true);
} break;
......
}
}
BroadcastQueue.processNextBroadcast()
// frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
final void processNextBroadcast(boolean fromMsg)
{
synchronized(mService)
{
BroadcastRecord r;
......
// fromMsg = true,if 命中
if (fromMsg)
{
// 由于 BroadcastHandler 使用的是主线程传递消息,消息可能会延迟
// mBroadcastsScheduled 用于表示 BROADCAST_INTENT_MSG 已被处理
mBroadcastsScheduled = false;
}
// mParallelBroadcasts 集合用于存储无序广播,遍历 mParallelBroadcasts
while (mParallelBroadcasts.size() > 0)
{
// 取出 mParallelBroadcasts 集合中的首部
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
// 遍历所有已注册的 BroadcastReceiver
final int N = r.receivers.size();
for (int i=0; i<N; i++)
{
// 获取 BroadcastReceiver
Object target = r.receivers.get(i);
// 将无序广播发送给 BroadcastReceiver
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
}
......
}
// 将有序广播发送给对应的 BroadcastReceiver
// 其中的代码细节与本次流程无关,有兴趣可以自行了解
......
}
}
BroadcastQueue.deliverToRegisteredReceiverLocked()
// frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered
){
boolean skip = false;
// 检查该 BroadcastReceiver 是否拥有权限
// 其中的代码细节与主流程无关,有兴趣可以自行了解
......
// 如果该 BroadcastReceiver 拥有权限,则 skip = false
if (!skip)
{
......
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
......
}
}
BroadcastQueue.performReceiveLocked()
// frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser
){
// 如果 app 不为空,表示该 BroadcastReceiver 运行所在进程存在
if (app != null)
{
// 如果 app.thread 不为空,表示该 BroadcastReceiver 运行所在进程正在运行中
if (app.thread != null)
{
// AIDL 调用该 BroadcastReceiver 运行所在进程
// ApplicationThread 的 scheduleRegisteredReceiver 函数
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
}
else // 如果该 BroadcastReceiver 运行所在进程未启动 / 该 BroadcastReceiver 不存在,
// 则抛出异常
{
throw new RemoteException("app.thread must not be null");
}
}
else
{
......
}
}
ApplicationThread.scheduleRegisteredReceiver()
// frameworks/base/core/java/android/app/ActivityThread.java
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState
){
updateProcessState(processState, false);
// 调用该 BroadcastReceiver 的 Binder 通信接口的 performReceive 函数
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
InnerReceiver.performReceive()
// frameworks/base/core/java/android/app/LoadedApk$ReceiverDispatcher$InnerReceiver.java
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser
){
// 获取 ReceiverDispatcher (弱引用,防止内存泄漏)
LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
......
if (rd != null)
{
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
}
......
}
ReceiverDispatcher.performReceive()
// frameworks/base/core/java/android/app/LoadedApk$ReceiverDispatcher.java
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser
){
......
// 将广播的 intent 等相关信息封装为 Args (本质上是 Runnable)
Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
// 发送消息给 ActivityThread 中的内部类 H (Handler)
if (!mActivityThread.post(args))
{
......
}
}
Args.run()
// frameworks/base/core/java/android/app/LoadedApk$ReceiverDispatcher$Args.java
public void run()
{
......
// 通过反射创建该 BroadcastReceiver
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
// 回调该 BroadcastReceiver 的 onReceive 函数,传入 intent
receiver.onReceive(mContext, intent);
......
}
总结
本篇文章分析了 BroadcastReceiver 的注册流程和 Broadcast 的发送流程,将其中对于我们开发者而言比较有意义的部分代码进行了分析
由于 BroadcastReceiver 分为静态注册和动态注册,Broadcast 又分为无序广播、有序广播和粘性广播等多种类型,需要多情况讨论,一篇博客显然是无法将其全部分析完的
希望读者能够参照本篇文章尝试自己去阅读源码,加深理解