说到广播的使用,就不得不提它的两种注册方式,动态注册和静态注册。静态注册在程序启动加载manifest文件时候完成。因此这里就以动态注册来看一下BroadcastReceiver 的工作过程。
注册广播
BroadcastReceiver 是一个抽象的类,因此我们需要继承BroadcastReceiver 实现一个我们自己的广播类
class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
}
}
然后在通过registerReceiver注册广播
mMyReceiver = new MyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.ZY_TEST");
registerReceiver(mMyReceiver, filter);
这里面我们就已经注册了一个action为"android.intent.action.ZY_TEST"的广播。
1、registerReceiver()
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
在前面两篇我们已经mBase的实现类是ContextImpl。所以查看ContextImpl的registerReceiver()。而ContextImpl.registerReceiver()又会执行ContextImpl.registerReceiverInternal方法
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
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 {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在registerReceiverInternal()主要做了两件事。
1、构造一个LoadedApk.ReceiverDispatcher对象,并获得通过其getIIntentReceiver()获得IIntentReceiver对象。
和Service的ServiceDispatcher作用是一样的,为BroadcastReceiver赋予跨进程通信的能力。
广播的本身并不具备跨进程通信的功能,所以需要通过Binder机制来实现跨进程通信。而ReceiverDispatcher的作用就是创建一个继承IIntentReceiver.Stub的InnerReceiver类,并保存InnerReceiver和BroadcastReceiver对象。
InnerReceiver相当于Binder机制的服务端,收到消息后,会通过ReceiverDispatcher对象来讲消息调度分发给BroadcastReceiver。
2、调用AMS的registerReceiver方法。这里同样使用Binder机制来完成registerReceiver()的调用
2、ActivityManagerService & registerReceiver()
广播会在SMS的registerReceiver完成注册。registerReceiver代码还是挺长的。这里我们只看一下注册部分的代码:
//从集合中获得注册广播接收器的集合类
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
//如果没有注册
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
//注册
mRegisteredReceivers.put(receiver.asBinder(), rl);
可以看到通过将Binder对象和ReceiverList对象以键值对的形式存储到HashMap的集合mRegisteredReceivers中,完成注册。
ReceiverList是一个广播接收器的集合类,因为在注册的时候我们可以一次注册多个广播。
发送广播
发送广播也分为普通广播,优先级广播和粘性广播。这里以普通广播为例。
Intent intent = new Intent();
intent.setAction("android.intent.action.ZY_TEST");
intent.putExtra("msg","你好");
sendBroadcast(intent);
sendBroadcast同样会调用ContextImpl的sendBroadcast方法
1、ContextImpl & sendBroadcast
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
ActivityManagerNative.getDefault().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();
}
继续执行AMS的broadcastIntent方法。broadcastIntent又会执行broadcastIntentLocked方法
2、AMS & broadcastIntentLocked
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) {
intent = new Intent(intent);
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
...
// Verify that protected broadcasts are only being sent by system code,
// and that system code is only sending protected broadcasts.
final String action = intent.getAction();
...
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
...
broadcastIntentLocked方法很长,首先会给广播添加一个默认的flag:不进入停止的应用内。
然后会校验发送广播的权限,因为有些事系统广播。
通过intent来查找注册的广播,执行 queue.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;
}
在handler接收消息的地方会执行processNextBroadcast方法:
// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
final int N = r.receivers.size();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
+ mQueueName + "] " + r);
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);
}
可以看到,如果是普通广播,则会立即遍历发送。mParallelBroadcasts就是我们在第一步注册广播时,存储广播的HashMap。
然后调用deliverToRegisteredReceiverLocked方法,在该方法中会执行performReceiveLocked()
BroadcastQueue & 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
// correctly ordered with other one-way calls.
try {
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
// TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
// DeadObjectException when the process isn't actually dead.
//} catch (DeadObjectException ex) {
// Failed to call into the process. It's dying so just let it die and move on.
// throw ex;
} catch (RemoteException ex) {
// Failed to call into the process. It's either dying or wedged. Kill it gently.
synchronized (mService) {
Slog.w(TAG, "Can't deliver broadcast to " + app.processName
+ " (pid " + app.pid + "). Crashing it.");
app.scheduleCrash("can't deliver broadcast");
}
throw ex;
}
} else {
// Application has died. Receiver doesn't exist.
throw new RemoteException("app.thread must not be null");
}
} else {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
下面则执行app.thread的scheduleRegisteredReceiver方法。app.thread也就是ApplicationThread。
// 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, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
然后调用receiver.performReceive()。这里的receiver也就是InnerReceiver。
而InnerReceiver的performReceive方法又会调用ReceiverDispatcher的performReceive方法。
final Handler mActivityThread;
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) {
Log.wtf(TAG, "Null intent received");
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver);
}
}
if (intent == null || !mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
}
然后通过mActivityThread.post(args)
执行Args 对象中的run方法。
public void run() {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
final IActivityManager mgr = ActivityManagerNative.getDefault();
final Intent intent = mCurIntent;
if (intent == null) {
Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
...
}
if (receiver.getPendingResult() != null) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
在run方法中会执行receiver.onReceive(mContext, intent); 接收广播消息
总结
其它三大组件工作流程:
参考:开发艺术探索