广播的注册分为静态注册和动态注册,静态注册是通过PackageManagerService(PMS)来完成整个的注册过程的,当然,除了广播外,其它三个组件也是在应用安装时通过PMS来完成解析和注册的。下面已动态注册为例分析广播的注册过程。在Activity中动态注册广播的代码如下:
IntentFilter intentFilter = new IntentFilter("com.android.skill");
myBroadcastReceiverFive = new MyBroadcastReceiverFive();
registerReceiver(myBroadcastReceiverFive,intentFilter);
private class MyBroadcastReceiverFive extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
LogUtil.e("动态注册 MyBroadcastReceiverFive");
}
}
在Activity中动态注册广播时,调用registerReceiver方法,会调用到ContextWrapper的registerReceiver方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/content/ContextWrapper.java
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
这个方法内部,mBase其实就是一个ContextImpl类型的对象,所以会执行ContextImpl类的registerReceiver方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.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);
}
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
//传入的 broadcastPermission 为null,scheduler 也是null,flags的值是0
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
// 满足条件,创建handler对象赋值给scheduler
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();
}
}
registerReceiver方法进过调用其重载方法,最后调用了registerReceiverInternal方法,这个方法中,会通过mPackageInfo.getReceiverDispatcher()方法创建一个IIntentReceiver类型的对象,这个对象其实就是一个LoadedApk.ReceiverDispatcher.InnerReceiver类型的对象,由于InnerReceiver是继承IIntentReceiver.Stub,所以这个InnerReceiver类型的对象其实就是一个Binder,它后面作为app进程和system_server进程进行通信的桥梁。mPackageInfo是LoadedApk类型的对象,下面看看LoadedApk类的getReceiverDispatcher方法的具体实现:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java
public final class LoadedApk {
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
// ...
if (rd == null) {
// 关键代码
rd = new ReceiverDispatcher(r, context, handler,
// ...
} else {
rd.validate(context, handler);
}
// ...
// 关键代码
return rd.getIIntentReceiver();
}
}
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;
}
// ...
}
final IIntentReceiver.Stub mIIntentReceiver;
// ...
//构造方法
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
if (activityThread == null) {
throw new NullPointerException("Handler must not be null");
}
//关键代码
mIIntentReceiver = new InnerReceiver(this, !registered);
// ...
}
// ...
IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver;
}
// ...
}
}
通过LoadedApk的getReceiverDispatcher方法,可以看出,它里面调用了LoadedApk.ReceiverDispatcher的构造方法,从上面贴出的代码可以看到,这个构造方法里面创建了一个InnerReceiver的对象,并将这个对象赋值给mIIntentReceiver这个变量,后面通过getIIntentReceiver方法获取的就是这个InnerReceiver类型的对象。下面接着看ContextImpl类的registerReceiverInternal方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
//传入的 broadcastPermission 为null,scheduler 也是null,flags的值是0
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
// 满足条件,创建handler对象赋值给scheduler
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 {
// 关键代码 2
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();
}
}
在完成了mPackageInfo.getReceiverDispatcher()创建InnerReceiver对象后,关键代码2 处,继续调用了AMS的registerReceiver方法
http://androidxref.com/9.0.0_r3/xref/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,
int flags) {
// ...
synchronized (this) {
// ...
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
// ...
//关键代码 1
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
// ...
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
if (rl.containsFilter(filter)) {
// ...
} else {
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
//关键代码 2
mReceiverResolver.addFilter(bf);
}
// ...
return sticky;
}
}
这个方法内部,进行将recevier和filter进行了保存,这样注册过程就完成了。
接下来看看广播的发送过程(本例按照,广播是动态注册的,并且发送的是普通的广播,未指定广播接收者,未指定权限,来分析广播的发送和接收过程):
在Activity中发送广播,sendBroadCast方法其实是调用了ContextWrapper的sendBroadcast方法,ContextWrapper类中的sendBroadcast方法,其实也是调用了ContextImpl的sendBroadcast方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
// 关键代码
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
这个方法中,通过进程间通信的的方式,调用了system_server进程的ActivityServiceManager的broadcastIntent方法
http://androidxref.com/9.0.0_r3/xref/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 bOptions,
boolean serialized, boolean sticky, int userId) {
//传入的 serialized 为false 表示发送的是无序广播, sticky 表示发送的是粘性广播
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
// ...
// 关键代码
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
@GuardedBy("this")
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, 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 userId) {
//传入的 serialized 为false 表示发送的是无序广播, sticky 表示发送的是粘性广播
intent = new Intent(intent);
// ...
// By default broadcasts do not go to stopped apps.
// Android系统对所有app的运行状态进行了跟踪
// 当应用第一次安装但未使用过,或从程序管理器被强行关闭后,将处于停止状态
// 在发送广播时,不管是什么广播类型,系统默认增加了FLAG_EXCLUDE_STOPPED_PACKAGES的flag
// 使得对于所有BroadcastReceiver而言,如果其所在进程的处于停止状态,该BroadcastReceiver将无法接收到广播
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// ...
//粘性广播由于在Android5.0 & API 21中已经失效,这里就不分析了
if (sticky) {
// ...
}
//广播没有指定特定接收者时
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
//这里的要求比较特殊,针对所有user,且从shell发送的广播
//即处理调试用的广播
for (int i = 0; i < users.length; i++) {
if (mUserController.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
continue;
}
List<BroadcastFilter> registeredReceiversForUser =
mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
registeredReceivers.addAll(registeredReceiversForUser);
}
}
} else {
//一般没有指定接收者的广播,都会走到这里,这是通常的处理流程
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, userId);
}
}
// ...
//由于分析的例子是不指定接收者,不需要权限的广播,所以,上面registeredReceivers赋值了,
//下面的NR这个变量的值是大于0的
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
//由于发送的是普通广播,这里的order传入的值是false,所以,这个if判断条件成立
if (!ordered && NR > 0) {
//非系统广播
if (isCallerSystem) {
checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
isProtectedBroadcast, registeredReceivers);
}
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId);
final boolean replaced = replacePending
&& (queue.replaceParallelBroadcastLocked(r) != null);
if (!replaced) {
//没有替换时,才需要将新的广播加入到BroadcastQueue.mParallelBroadcasts队列中
//这里非常重要,也就是说动态广播都放在了BroadcastQueue.mParallelBroadcasts中
queue.enqueueParallelBroadcastLocked(r);
//1 触发广播发送流程
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
//如果是发送的普通广播,则上面的NR 重新赋值为 0,由于分析的示例前提是,没有静态注册广播,所以这里
//的receivers为null(这个receiver为null的分析过程,需要结合PackageManagerService类的queryIntentReceiversInternal方法,
// 读者可以自己去分析,限于篇幅的原因,这里就不做详细的分析)
//所以下面这个判断就不成立,(如果是静态注册的广播,则会走下面的广播发送流程,本例是动态注册的广播,所以不走这个流程)
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId);
final BroadcastRecord oldRecord =
replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
if (oldRecord != null) {
if (oldRecord.resultTo != null) {
final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
try {
oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
oldRecord.intent,
Activity.RESULT_CANCELED, null, null,
false, false, oldRecord.userId);
}
// ...
}
} else {
//关键代码
//这里非常重要,如果发送的是有序广播,则所有的广播接收者都放在了BroadcastQueue.mOrderedBroadcasts中
//这个和上面如果发送的是普通广播时,将动态注册的广播存储在BroadcastQueue.mParallelBroadcasts中是不同的。
queue.enqueueOrderedBroadcastLocked(r);
// 2 触发广播发送流程
queue.scheduleBroadcastsLocked();
}
}
// ...
return ActivityManager.BROADCAST_SUCCESS;
}
这个方法内部,主要做了如下事情:
1.先获取动态注册的广播和静态注册的广播,并将这些广播分别存储到两个不同的列表中
2.判断是否是发送的普通广播,如果是,并且动态注册的广播,则先将动态注册的广播发送, 走后续的广播发送流程,接着判断是否有静态广播,如果有静态广播,则发送静态广播。(从源码代码逻辑可以知道,普通广播的发送,是动态广播优先静态广播发送)如果发送的是有序广播,则会将第一步的两个列表合并到receivers列表中,并按照优先级对广播进行排序,具体的排序规则是,优先级高的排前面,对于相同优先级的,动态优先静态,对于优先级相同,广播类型相同,如果都是动态广播类型,则先注册的优先后注册的,对于都是静态广播类型,则先扫描的由于后扫描的。
3.将广播将第二步的广播列表,添加到BroadcastQueue的mParallelBroadcasts或者mOrderedBroadcasts中,如果广播按照普通方式发送,则将广播存储在mParallelBroadcasts列表中,如果是静态广播存储在mOrderedBroadcasts列表中,如果发送方式是有序广播,则将所有的广播(不管是静态注册的还是动态注册的)都存储在mOrderedBroadcasts列表中。
4.调用BroadcastQueue的scheduleBroadcastsLocked方法发送广播。
由于前提是发送动态广播,并未注册静态广播,所以执行到关键代码1处,通过调用BroadcastQueue的enqueueOrderedBroadcastLocked方法将发送的广播存储在BroadcastQueue的mParallelBroadcasts列表中,然后通过
scheduleBroadcastsLocked方法发送广播。下面看看scheduleBroadcastsLocked方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
public void scheduleBroadcastsLocked() {
if (mBroadcastsScheduled) {
return;
}
// 关键代码
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
private final class BroadcastHandler extends Handler {
public BroadcastHandler(Looper looper) {
super(looper, null, true);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
//关键代码
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
}
}
}
final void processNextBroadcast(boolean fromMsg) {
synchronized (mService) {
processNextBroadcastLocked(fromMsg, false);
}
}
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
//传入的参数 fromMsg 为true ,skipOomAdj 为 false
BroadcastRecord r;
// ...
if (fromMsg) {
mBroadcastsScheduled = false;
}
//处理无序广播
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
// ...
final int N = r.receivers.size();
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
//发送无序广播
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
// ...
}
// 对于有序或静态广播而言,需要依次向每个BroadcastReceiver发送广播,前一个处理完毕后才能发送下一个广播
// 如果BroadcastReceiver对应的进程还未启动,则需要等待
// mPendingBroadcast就是用于保存,因为对应进程还未启动,而处于等待状态的BroadcastRecord
if (mPendingBroadcast != null) {
// ... 这里省略的代码是处理要触发的广播的进程还未启动的广播
}
boolean looped = false;
//如果发送的是有序广播,则将执行下面的逻辑
do {
//这块省略的逻辑是:处理有序广播
}while(r == null;
// ...
//中间进行很多的权限检查
// Is this receiver's application already running?
if (app != null && app.thread != null && !app.killed) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
processCurBroadcastLocked(r, app, skipOomAdj);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when sending broadcast to "
+ r.curComponent, e);
} catch (RuntimeException e) {
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
}
//如果要启动的广播的进程为创建,则要创建一个新的进程,mService.startProcessLocked()方法
//就是AMS中的startProcessLocked(),这个方法是用于新建一个进程
if ((r.curApp=mService.startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
"broadcast", r.curComponent,
(r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
== null) {
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
//在次重复发送过程,为什么要这么处理呢,这是因为,新建的进程中也可能存在
// 其它注册的广播,所以要在次执行这个广播的发送流程
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
// ...
}
无序广播,并调用deliverToRegisteredReceiverLocked方法发送无序广播。如果是发送的有序广播,则判断广播所属的进程是否存在,并且进程未被kill,则执行processCurBroadcastLocked处理后续的流程,如果广播所属的进程不存在,则新建一个进程,并重复广播的发送过程,这些情况的后续流程,读者可以自己去分析。本例中,只是发送普通股广播,并且广播就所属当前进程,所以直接执行deliverToRegisteredReceiverLocked方法,下面看看这个方法的具体实现:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/a
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
// ...
try {
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
if (ordered) {
skipReceiverLocked(r);
}
} else {
//关键代码
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
}
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
} catch (RemoteException e) {
if (ordered) {
r.receiver = null;
r.curFilter = null;
filter.receiverList.curBroadcast = null;
if (filter.receiverList.app != null) {
filter.receiverList.app.curReceivers.remove(r);
}
}
}
}
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
if (app != null) {
if (app.thread != null) {
try {
//关键代码
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} catch (RemoteException ex) {
synchronized (mService) {
app.scheduleCrash("can't deliver broadcast");
}
throw ex;
}
} else {
throw new RemoteException("app.thread must not be null");
}
} else {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
deliverToRegisteredReceiverLocked方法中,又会调用到performReceiveLocked方法,performReceiveLocked方法中,会调用app.thread.scheduleRegisteredReceiver方法,app.thread其实是ApplicationThread类型的对象,这个在之前就分析过,代码的执行又回到了ApplicationThread类中
http://androidxref.com/9.0.0_r3/xref/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) throws RemoteException {
updateProcessState(processState, false);
//关键代码
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
这个方法中的receiver其实就是之前分析的LoadedApk.ReceiverDispatcher.InnerReceiver类型的对象,下面看看LoadedApk.ReceiverDispatcher.InnerReceiver的performReceive方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java
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) {
rd = null;
} else {
rd = mDispatcher.get();
}
if (rd != null) {
//关键代码
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
}
// ...
}
}
这个方法内部又调用了LoadedApk.ReceiverDispatcher的performReceive方法
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
// 关键代码
if (intent == null || !mActivityThread.post(args.getRunnable())) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
args.sendFinished(mgr);
}
}
}
LoadedApk.ReceiverDispatcher的performReceive方法内部,调用了mActivityThread这个handler发送一个Runnable,下面看看这个Runnable的run方法
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
// ...
final IActivityManager mgr = ActivityManager.getService();
//...
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
//关键代码
receiver.onReceive(mContext, intent);
}
// ...
};
}
可以看到,这里调用了receiver的onReceive方法,至此,广播的onReceive方法就执行了。
总结:
1.动态广播的注册过程其实就是通过binder将BroadcastReceiver(广播接收者)保存AMS中。
2.当发送广播时,也是通过binder,在system_server进程中,将发送的广播保存到BroadcastQueue的广播列表中。
3.通过AMS在BroadcastQueue的广播列表中查找与之匹配的BroadcastReceiver,在将广播发送给BroadcastReceiver
所在的进程的消息队列中。
4.BroadcastReceiver所在的进程处理消息,并回调BroadcastReceiver中的onReceive方法。
5.处理完广播后,BroadcastReceiver进程按需将执行结果通知给AMS,以便触发下一次广播发送。
广播按照发送方式可以分为:
1.有序广播:一旦发送了无序广播,所有监听此广播的接收者都能接收到。
2.普通广播:广播接收者按照优先级顺序,可以中断广播,也可以对广播进行修改,如果优先级相同,则动态注册的广播优先于静态注册的广播。
3.粘性广播:当广播发出后,如果系统没有接受者,会一直等待,直到有接收者接收为止。由于在Android5.0 & API 21中已经失效
按照应用内外:
1.分为本地广播:只在app内发送和接收广播。
2.非本地广播
建议动态注册个广播,最好在Activity的onPause方法中进行unRegister,因为Activity在执行完onPause方法后,在系统内存不足的情况下,就可能被销毁,如果放到onStop后者onDestroy方法中,此时这两个方法都可能未执行,这样会导致内存泄漏。
广播的注册方式,不管是静态注册,还是动态注册,他们是按照有序执行还是无序执行,不是根据它的注册方式决定的,而是根据发送广播的方式决定,如果是发送普通广播,则每个广播接收者都能够接收到广播,广播不能够被其它广播中断。如果是发送的有序广播,则广播接收者按照优先级来接收广播,具体的接收顺序是,优先级高的先接收,如果优先级相同,动态注册的广播优先静态注册的广播,对于动态广播,如果优先级相同,先注册的优先于后注册的,对于优先级相同的静态广播,先扫描的优先于后扫描的。