- 普通广播
sendBroadcast()这个方法的广播按照BroadcastReceiver注册的先后顺序发送给所有的BroadcastReceiver。如果BroadcastReceiver设置了优先级并且优先级与注册顺序相同,则不会出任何问题,但是如果优先级与注册顺序不同,则会抛出异常- 有序广播
sendOrderedBroadcas方法用来发送有序广播,优先级高的BroadcastReceiver先收到,并且先收到的BroadcastReceiver可以拦截广播- 粘性广播
- 静态注册:在AndroidManifest.xml中注册,常驻系统,不受组件生命周期影响,即便应用退出,广播还是可以被接收,这种BroadcastReceiver耗电、占内存
- 动态注册:代码中注册,非常驻系统,收到组件生命周期影响,组件结束,便不接收广播。当组件结束时我们应该手动注销前面动态注册的BroadcastReceiver,否则会出现内存泄漏
我们在Activity或者Service中注册BroadcastReceiver其实最终都是调用到ContextWrapper.registerReceiver这个方法里
public class ContextWrapper extends Context {
Context mBase;
......
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
......
}
这里面的mBase是ContextImpl实例,所以最终会调用到ContextImpl.registerReceiver
class ContextImpl extends Context {
......
@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, filter, broadcastPermission,
scheduler, getOuterContext());
}
private Intent registerReceiverInternal(BroadcastReceiver receiver,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
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 {
......
}
}
try {
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(),
rd, filter, broadcastPermission);
} catch (RemoteException e) {
return null;
}
}
......
}
这里的mPackageInfo是LoadApk实例,getOuterContext()得到的就是我们注册这个BroadcastReceiver的context了,可能是Activity,也可能是Service,都是继承自Context。scheduler = mMainThread.getHandler();返回的是ActivityThread的mH成员变量,这个一个Handler,用来分发后面ActivityManagerService发送过来的广播。
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
这一句代码返回的是一个IIntentReceiver接口对象,这是一个Binder对象,接下来会将它传递给ActivityManagerService,当ActivityManagerService收到相应的广播的时候就是通过它来通知Activity或Service的。我们来看一下这句代码的具体实现
final class LoadedApk {
......
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
HashMap map = null;
if (registered) {
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
if (rd == null) {
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
if (map == null) {
map = new HashMap();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
return rd.getIIntentReceiver();
}
}
......
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference mDispatcher;
......
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference(rd);
......
}
......
}
......
final IIntentReceiver.Stub mIIntentReceiver;
final Handler mActivityThread;
......
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
......
mIIntentReceiver = new InnerReceiver(this, !registered);
mActivityThread = activityThread;
......
}
......
IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver;
}
}
......
}
代码很简单,其实就是先判断LoadedApk中是否存在BroadcastReceiver对应的ReceiverDispather,如果不存在就创建,然后保存。这是Android里普遍用到的思想。
我们再回到ContextImpl.registerReceiverInternal里面,利用Binder通信最终会调用到ActivityManagerService.registerReceiver中
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
public Intent registerReceiver(IApplicationThread caller,
IIntentReceiver receiver, IntentFilter filter, String permission) {
synchronized(this) {
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
......
}
}
List allSticky = null;
// Look for any matching sticky broadcasts...
Iterator actions = filter.actionsIterator();
if (actions != null) {
while (actions.hasNext()) {
String action = (String)actions.next();
allSticky = getStickiesLocked(action, filter, allSticky);
}
} else {
......
}
// The first sticky in the list is returned directly back to
// the client.
Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
......
if (receiver == null) {
return sticky;
}
ReceiverList rl
= (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp,
Binder.getCallingPid(),
Binder.getCallingUid(), receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
......
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
rl.add(bf);
......
mReceiverResolver.addFilter(bf);
// Enqueue broadcasts for all existing stickies that match
// this filter.
if (allSticky != null) {
......
}
return sticky;
}
}
......
}
代码很长,但是做的事很简单,就是讲BroadcastReceiver和其对应的filter保存在ActivityManagerService中,以便以后收到相应的广播时进行处理。
同样,发送广播还是会调用到ContextImpl.sendBroadcast方法,最终通过Binder机制调用到ActivityManagerService.broadcastIntent方法
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized, boolean sticky) {
synchronized(this) {
intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo,
resultCode, resultData, map, requiredPermission, serialized,
sticky, callingPid, callingUid);
Binder.restoreCallingIdentity(origId);
return res;
}
}
······
private final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle map, String requiredPermission,
boolean ordered, boolean sticky, int callingPid, int callingUid) {
intent = new Intent(intent);
......
// Figure out who all will receive this broadcast.
List receivers = null;
List registeredReceivers = null;
try {
if (intent.getComponent() != null) {
......
} else {
......
registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
}
} catch (RemoteException ex) {
......
}
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
// If we are not serializing this broadcast, then send the
// registered receivers separately so they don't wait for the
// components to be launched.
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
registeredReceivers, resultTo, resultCode, resultData, map,
ordered, sticky, false);
......
boolean replaced = false;
if (replacePending) {
for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
......
mParallelBroadcasts.set(i, r);
replaced = true;
break;
}
}
}
if (!replaced) {
mParallelBroadcasts.add(r);
scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
......
}
......
}
从其中的代码
registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
可以看到,broadcastIntentLocked方法中首先根据发送广播传递的intent来查询与之对应的注册过的BroadcastReceiver,之后调用scheduleBroadcastsLocked(); 进一步执行
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final void scheduleBroadcastsLocked() {
......
if (mBroadcastsScheduled) {
return;
}
mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
mBroadcastsScheduled = true;
}
......
}
当ActivityManagerService收到广播时直接把广播放进消息队列中去了,根本不管广播后续是如何处理的,从这里可以看出广播的发送和处理都是异步的。
final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
......
case BROADCAST_INTENT_MSG: {
......
processNextBroadcast(true);
} break;
......
}
}
}
······
private final void processNextBroadcast(boolean fromMsg) {
synchronized(this) {
BroadcastRecord r;
......
if (fromMsg) {
mBroadcastsScheduled = false;
}
// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
......
final int N = r.receivers.size();
......
for (int i=0; i
processNextBroadcast方法中,r.receivers对应的是这个广播所有对应的BroadcastReceiver,因为有可能会针对一个广播注册多个BroadcastReceiver。通过循环中的deliverToRegisteredReceiverLocked方法分别给每个BroadcastReceiver来发送广播
private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered) {
boolean skip = false;
if (filter.requiredPermission != null) {
......
}
if (r.requiredPermission != null) {
......
}
if (!skip) {
// If this is not being sent as an ordered broadcast, then we
// don't want to touch the fields that keep track of the current
// state of ordered broadcasts.
if (ordered) {
......
}
try {
......
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, r.ordered, r.initialSticky);
......
} catch (RemoteException e) {
......
}
}
}
······
static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky) throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null && app.thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky);
} else {
......
}
}
performReceiveLocked方法中,app.thread对应的是注册BroadcastReceiver时传递进来的ApplicationThreadProxy远程Binder对象,用于通知注册者接收广播。通过Binder机制,最终会调用到ApplicaitonThread.scheduleRegisteredReceiver方法
public final class ActivityThread {
......
private final class ApplicationThread extends ApplicationThreadNative {
......
// This function exists to make sure all receiver dispatching is
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky) throws RemoteException {
receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
}
......
}
......
}
这里的receiver是之前注册BroadcastReceiver时创建的,具体类型是LoadedApk.ReceiverDispatcher.InnerReceiver
final class LoadedApk {
......
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
......
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered, boolean sticky) {
LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
......
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky);
} else {
......
}
}
}
......
}
......
}
这里只是简单的调用了ReceiverDispatcher.performReceive方法
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered, boolean sticky) {
......
Args args = new Args();
args.mCurIntent = intent;
args.mCurCode = resultCode;
args.mCurData = data;
args.mCurMap = extras;
args.mCurOrdered = ordered;
args.mCurSticky = sticky;
if (!mActivityThread.post(args)) {
......
}
}
......
}
这里的mActivityThread是一个Handler对象,是我们注册BroadcastReceiver时传递进来的那个scheduler = mMainThread.getHandler(); 对象,而args是一个Runnable,最终会调用到Args.run方法中。从这里也可以看出这是一个异步的过程。
final class LoadedApk {
......
static final class ReceiverDispatcher {
......
final class Args implements Runnable {
......
public void run() {
BroadcastReceiver receiver = mReceiver;
......
Intent intent = mCurIntent;
......
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
if (mCurMap != null) {
mCurMap.setClassLoader(cl);
}
receiver.setOrderedHint(true);
receiver.setResult(mCurCode, mCurData, mCurMap);
receiver.clearAbortBroadcast();
receiver.setOrderedHint(mCurOrdered);
receiver.setInitialStickyHint(mCurSticky);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
......
}
......
}
......
}
......
}
......
}
这里的BroadcastReceiver receiver = mReceiver; 其实就是我们注册BroadcastReceiver时创建的实例了,最终就会调用到BroadcastReceiver.onReceive方法中。
到这里我们的广播发送的过程就结束了,我们来总结一下这个过程:
- ContextImpl.sendBroadcast通过Binder机制将广播发送到ActivityManagerService,ActivityManagerService根据传递过来的Intent的Action找到与之对应的BroadcastReceiver,然后将这个广播放到自己的消息队列中去,完成了广播的第一步异步分发
- ActivityManagerService在消息循环中处理广播,通过Binder机制将这个广播分发给注册BroadcastReceiver时创建的ReceiverDispatcher,然后ReceiverDispatcher将广播放进注册BroadcastReceiver的Activity或Service所在的线程的消息队列中去,这就完成了广播的第二步异步分发
- ReceiverDispatcher的内部类Args在注册BroadcastReceiver所在的线程消息队列中处理广播,最终分发给BroadcastReceiver,执行其onReceive方法
以上就是广播的种类、注册方式、注册过程、发送过程的分析,水平有限,有错之处请理解。
本文参考老罗的
Android应用程序注册广播接收器(registerReceiver)的过程分析
Android应用程序发送广播(sendBroadcast)的过程分析