注册BroadcastReceiver
通过ActivityManagerService#registerReceiver注册到AMS中
介绍几个跟注册有关的重要成员
* mRegisteredReceivers : HashMap ReceiverList
ReceiverList extends ArrayList,持有PorcessRecord和IIntentReceiver,并且保存了该IIntentReceiver对应的所有BroadcastIntent。
其中IIntentReceiver持有BroadcastReceiver。
在注册的时候,有一种stickyBroadcast,发送过一次后,AMS会记录下来,每次有新注册的Receiver,都会发给这个新的Receiver。
发送广播(sendBroadcast):
ActivityManagerService#broadcastIntentLocked(…)
* 若是特殊广播,如UID_REMOVED, PACKEAGE_REMOVED, PACKAGE_ADDED,
TIMEZONE变化广播,CLEAR_DNS_CACHE广播,PROXY_CHANGE广播等
需要特殊处理
* 关于sticky广播的一些处理
* 在该方法中,定义了两个List,分别是receivers:Lsit和registeredReceivers
分别保存所有符合条件的广播接收者(包括静态和动态)和动态接收者。
receiver = AppGlobals.getPackageManager().queryIntentReceivers(inent, resolvedType, STOCK_PM_FLAGS);
registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
* 若不是有序广播,创建一个BroadcastRecord,代表了一个广播,该对象持有所有能接收该广播的动态接收者的引用。
将该广播加入一个queue,并开始广播,即与各进程通信,使receiver的onreceive方法在各自进程中执行。
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
queque:BroadcastQueue,其中scheduleBroadcastsLocked会触发processNextBroadcast
BroadcastQueue#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 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);
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
逐个启动各进程中的receiver的onreceive方法。最后将给broadcasstRecord放入History中。
* 还要处理静态的接收者,因静态接收者所在进程可能没有启动,所以不能像静态接收者一样处理。
需要逐个处理,像有序广播那样处理
ActivityThread#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的实例类型是LoadedAPK.ReceiverDispatcher,而ReceiverDispatcher持有BroadcastReceiver
最终去到LoadedAPK.ReceiverDispatcher.Args#run()
public void run() {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
if (ActivityThread.DEBUG_BROADCAST) {
int seq = mCurIntent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
+ " seq=" + seq + " to " + mReceiver);
Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
+ " mOrderedHint=" + ordered);
}
final IActivityManager mgr = ActivityManagerNative.getDefault();
final Intent intent = mCurIntent;
mCurIntent = null;
if (receiver == null || mForgotten) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing null broadcast to " + mReceiver);
sendFinished(mgr);
}
return;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);//在此调用了onreceive()
} catch (Exception e) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing failed broadcast to " + mReceiver);
sendFinished(mgr);
}
if (mInstrumentation == null ||
!mInstrumentation.onException(mReceiver, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Error receiving broadcast " + intent
+ " in " + mReceiver, e);
}
}
if (receiver.getPendingResult() != null) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
1.注册广播
/*
功能和前面类似,但增加了两个参数,分别是broadcastPermission和scheduler,作用有
两个:
其一:对广播者的权限增加了控制,只有拥有相应权限的广播者发出的广播才能被此接收者接收
其二:BroadcastReceiver对象的onReceiver函数可调度到scheduler所在的线程中执行
*/
publicIntent registerReceiver(BroadcastReceiver receiver,
IntentFilterfilter, String broadcastPermission, Handler scheduler) {
/*
用上面这些参数通过LoadedApk.ReceiverDispatcher.getIIntentReceiver(…)构造一个个IIntentReceiver,传给AMS,同时ApplicationThread也会传给AMS,调用AMS以下方法:
public Intent registerReceiver(IApplicationThreadcaller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission)
注册时并没有把本地创建的 BroadcastReceiver对象保存到本应用进程的某个结构体中,而是
2.接收广播。
IIntentReceiver是一个Binder对象,但是最后AMS和应用进程通信时使用的是ApplicationThread,通过ApplicationThread#scheduleRegisteredReceiver的方法
public voidscheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
intresultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky) throws RemoteException {
//又把receiver对象传了回来。还记得注册时传递的一个IIntentReceiver类型
//的对象吗?
receiver.performReceive(intent,resultCode, dataStr, extras, ordered,
sticky);
}
通过该方法把注册时传递过去的IIntentReceiver又传回来了。然后就调用该对象performReceiver,最终会调用到BroadcastReceiver#onReceive()。