在《android--廣播接收者BroadcastReceiver的註冊過程》中分析了怎麼定義BroadcastReceiver接受者,下面咱們分析一下發送的過程。 java
當在某個service中想要發送廣播,咱們就會調用這麼的代碼: android
Intent intent = new Intent(BROADCAST_COUNTER_ACTION); intent.putExtra(COUNTER_VALUE, counter); sendBroadcast(intent);
下面咱們就對這幾行代碼進行分析 app
一、一個廣播使用intent來描述的,BROADCAST_COUNTER_ACTION名稱就是用來和廣播接收者的類型進行匹配的。 異步
public class Intent implements Parcelable, Cloneable { // --------------------------------------------------------------------- private String mAction; private Uri mData; private String mType; private String mPackage; private ComponentName mComponent; private int mFlags; private HashSet<String> mCategories; private Bundle mExtras; private Rect mSourceBounds; } 變量mAction和mExtras不爲空,其他爲空
二、 sendBroadcast(intent)的源碼: async
public class ContextWrapper extends Context { Context mBase; public ContextWrapper(Context base) { mBase = base; } @Override public void sendBroadcast(Intent intent) { mBase.sendBroadcast(intent); } 。。。 }
註釋:mBase是一個ContextImpl對象,因此調用的是ContextImpl中的sendBroadcast方法。 ide
三、 mBase.sendBroadcast(intent)的源碼: oop
@Override public void sendBroadcast(Intent intent) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, false, false); } catch (RemoteException e) { } }
註釋:(1) post
ActivityManagerNative. getDefault()得到是ActivityManagerProxy對象。 ui
(2) resolvedType爲空null this
四、ActivityManagerProxy中的broadcastIntent()方法的源碼:
public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, boolean serialized, boolean sticky) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); intent.writeToParcel(data, 0); data.writeString(resolvedType); data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null); data.writeInt(resultCode); data.writeString(resultData); data.writeBundle(map); data.writeString(requiredPermission); data.writeInt(serialized ? 1 : 0); data.writeInt(sticky ? 1 : 0); mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0); reply.readException(); int res = reply.readInt(); reply.recycle(); data.recycle(); return res; }
註釋:(1)將參數封裝成Parcel對象data中。
(2)binder代理對象mRemote向ActivityManagerService發送一個類型爲BROADCAST_INTENT_TRANSACTION的進程間通訊請求。
五、ActivityManagerService中的源碼:
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; } }
六、broadcastIntentLocked()方法源碼:
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); if (DEBUG_BROADCAST_LIGHT) Slog.v( TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent + " ordered=" + ordered); if ((resultTo != null) && !ordered) { Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!"); } // Handle special intents: if this broadcast is from the package // manager about a package being removed, we need to remove all of // its activities from the history stack. final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals( intent.getAction()); if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction()) || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction()) || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction()) || uidRemoved) { if (checkComponentPermission( android.Manifest.permission.BROADCAST_PACKAGE_REMOVED, callingPid, callingUid, -1) == PackageManager.PERMISSION_GRANTED) { if (uidRemoved) { final Bundle intentExtras = intent.getExtras(); final int uid = intentExtras != null ? intentExtras.getInt(Intent.EXTRA_UID) : -1; if (uid >= 0) { BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics(); synchronized (bs) { bs.removeUidStatsLocked(uid); } } } else { // If resources are unvailble just force stop all // those packages and flush the attribute cache as well. if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) { String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); if (list != null && (list.length > 0)) { for (String pkg : list) { forceStopPackageLocked(pkg, -1, false, true, true); } sendPackageBroadcastLocked( IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list); } } else { Uri data = intent.getData(); String ssp; if (data != null && (ssp=data.getSchemeSpecificPart()) != null) { if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) { forceStopPackageLocked(ssp, intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true); } if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED, new String[] {ssp}); } } } } } else { String msg = "Permission Denial: " + intent.getAction() + " broadcast from " + callerPackage + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED; Slog.w(TAG, msg); throw new SecurityException(msg); } } /* * If this is the time zone changed action, queue up a message that will reset the timezone * of all currently running processes. This message will get queued up before the broadcast * happens. */ if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) { mHandler.sendEmptyMessage(UPDATE_TIME_ZONE); } /* * Prevent non-system code (defined here to be non-persistent * processes) from sending protected broadcasts. */ if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID || callingUid == Process.SHELL_UID || callingUid == 0) { // Always okay. } else if (callerApp == null || !callerApp.persistent) { try { if (AppGlobals.getPackageManager().isProtectedBroadcast( intent.getAction())) { String msg = "Permission Denial: not allowed to send broadcast " + intent.getAction() + " from pid=" + callingPid + ", uid=" + callingUid; Slog.w(TAG, msg); throw new SecurityException(msg); } } catch (RemoteException e) { Slog.w(TAG, "Remote exception", e); return BROADCAST_SUCCESS; } } // Add to the sticky list if requested. if (sticky) { //(1)從上面的傳值,這裏sticky=false if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, callingPid, callingUid) != PackageManager.PERMISSION_GRANTED) { String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid=" + callingPid + ", uid=" + callingUid + " requires " + android.Manifest.permission.BROADCAST_STICKY; Slog.w(TAG, msg); throw new SecurityException(msg); } if (requiredPermission != null) { Slog.w(TAG, "Can't broadcast sticky intent " + intent + " and enforce permission " + requiredPermission); return BROADCAST_STICKY_CANT_HAVE_PERMISSION; } if (intent.getComponent() != null) { throw new SecurityException( "Sticky broadcasts can't target a specific component"); } ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction()); if (list == null) { list = new ArrayList<Intent>(); mStickyBroadcasts.put(intent.getAction(), list); } int N = list.size(); int i; for (i=0; i<N; i++) { if (intent.filterEquals(list.get(i))) { // This sticky already exists, replace it. list.set(i, new Intent(intent)); break; } } if (i >= N) { list.add(new Intent(intent)); } } // Figure out who all will receive this broadcast. List receivers = null; List<BroadcastFilter> registeredReceivers = null; try { if (intent.getComponent() != null) { ///(2 )intent.getComponent()得到是廣播接收者的名稱,發送給特定的廣播接收者。從上面的傳值來看mComponent爲null // Broadcast is going to one specific receiver class... ActivityInfo ai = AppGlobals.getPackageManager(). getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS); if (ai != null) { receivers = new ArrayList(); ResolveInfo ri = new ResolveInfo(); ri.activityInfo = ai; receivers.add(ri); } } else { // Need to resolve the intent to interested receivers... if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { ///(3)得到靜態註冊的廣播接收者 receivers = AppGlobals.getPackageManager().queryIntentReceivers( intent, resolvedType, STOCK_PM_FLAGS); } registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false); ///(4)得到動態註冊的廣播接收者 } } catch (RemoteException ex) { // pm is in same process, this will never happen. } final boolean replacePending = (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0; if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction() + " replacePending=" + replacePending); int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { ///(5)這裏爲true // 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); if (DEBUG_BROADCAST) Slog.v( TAG, "Enqueueing parallel broadcast " + r + ": prev had " + mParallelBroadcasts.size()); boolean replaced = false; if (replacePending) {///(6)這裏檢查是否存在一個這樣的無序廣播,若是存在替換,若是不存在擇添加。 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) { if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) { if (DEBUG_BROADCAST) Slog.v(TAG, "***** DROPPING PARALLEL: " + intent); mParallelBroadcasts.set(i, r); replaced = true; break; } } } if (!replaced) { mParallelBroadcasts.add(r); scheduleBroadcastsLocked(); //而後執行這個方法 } registeredReceivers = null; NR = 0; } // Merge into one list. int ir = 0; if (receivers != null) { // A special case for PACKAGE_ADDED: do not allow the package // being added to see this broadcast. This prevents them from // using this as a back door to get run as soon as they are // installed. Maybe in the future we want to have a special install // broadcast or such for apps, but we'd like to deliberately make // this decision. String skipPackages[] = null; if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction()) || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction()) || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) { Uri data = intent.getData(); if (data != null) { String pkgName = data.getSchemeSpecificPart(); if (pkgName != null) { skipPackages = new String[] { pkgName }; } } } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) { skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); } if (skipPackages != null && (skipPackages.length > 0)) { for (String skipPackage : skipPackages) { if (skipPackage != null) { int NT = receivers.size(); for (int it=0; it<NT; it++) { ResolveInfo curt = (ResolveInfo)receivers.get(it); if (curt.activityInfo.packageName.equals(skipPackage)) { receivers.remove(it); it--; NT--; } } } } } int NT = receivers != null ? receivers.size() : 0; int it = 0; ResolveInfo curt = null; BroadcastFilter curr = null; while (it < NT && ir < NR) { if (curt == null) { curt = (ResolveInfo)receivers.get(it); } if (curr == null) { curr = registeredReceivers.get(ir); } if (curr.getPriority() >= curt.priority) { // Insert this broadcast record into the final list. receivers.add(it, curr); ir++; curr = null; it++; NT++; } else { // Skip to the next ResolveInfo in the final list. it++; curt = null; } } } while (ir < NR) { if (receivers == null) { receivers = new ArrayList(); } receivers.add(registeredReceivers.get(ir)); ir++; } if ((receivers != null && receivers.size() > 0) || resultTo != null) { BroadcastRecord r = new BroadcastRecord(intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, receivers, resultTo, resultCode, resultData, map, ordered, sticky, false); if (DEBUG_BROADCAST) Slog.v( TAG, "Enqueueing ordered broadcast " + r + ": prev had " + mOrderedBroadcasts.size()); if (DEBUG_BROADCAST) { int seq = r.intent.getIntExtra("seq", -1); Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq); } boolean replaced = false; if (replacePending) { for (int i=mOrderedBroadcasts.size()-1; i>0; i--) { if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) { if (DEBUG_BROADCAST) Slog.v(TAG, "***** DROPPING ORDERED: " + intent); mOrderedBroadcasts.set(i, r); replaced = true; break; } } } if (!replaced) { mOrderedBroadcasts.add(r); scheduleBroadcastsLocked(); } } return BROADCAST_SUCCESS; }註釋:如上面的(1),(2)....
七、 scheduleBroadcastsLocked()的源碼:
private final void scheduleBroadcastsLocked() { if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current=" + mBroadcastsScheduled); if (mBroadcastsScheduled) { return; } mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG); mBroadcastsScheduled = true; }
註釋:mBroadcastsScheduled表示是否已經向全部運行的線程發送了一個類型爲BROADCAST_INTENT_MSG的消息。
到這裏,廣播就發送完了,能夠看出廣播發送和接受者是異步的
八、mHandler.sendEmptyMessage( BROADCAST_INTENT_MSG)的源碼:
final Handler mHandler = new Handler() { //public Handler() { // if (localLOGV) Slog.v(TAG, "Handler started!"); //} public void handleMessage(Message msg) { switch (msg.what) { case BROADCAST_INTENT_MSG: { if (DEBUG_BROADCAST) Slog.v( TAG, "Received BROADCAST_INTENT_MSG"); processNextBroadcast(true); } break; 。。。。 }}解釋:mHandler是定義在ActivityManagerService中的變量,用於發送消息。
九、processNextBroadcast(true)的源碼:
private final void processNextBroadcast(boolean fromMsg) { synchronized(this) { BroadcastRecord r; if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: " + mParallelBroadcasts.size() + " broadcasts, " + mOrderedBroadcasts.size() + " ordered broadcasts"); updateCpuStats(); if (fromMsg) { //(1)這裏爲true mBroadcastsScheduled = false; } // First, deliver any non-serialized broadcasts right away. while (mParallelBroadcasts.size() > 0) { //(2) 這裏爲true ,由於上面向mParallelBroadcasts添加了數據 r = mParallelBroadcasts.remove(0); r.dispatchTime = SystemClock.uptimeMillis(); final int N = r.receivers.size();///(3)這裏的r.receivers.就是上面建立BroadcastRecord對象時候傳入的registeredReceivers if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast " + r); for (int i=0; i<N; i++) { Object target = r.receivers.get(i); if (DEBUG_BROADCAST) Slog.v(TAG, "Delivering non-ordered to registered " + target + ": " + r); deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); //執行這行代碼 } addBroadcastToHistoryLocked(r); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast " + r); } // Now take care of the next serialized one... // If we are waiting for a process to come up to handle the next // broadcast, then do nothing at this point. Just in case, we // check that the process we're waiting for still exists. if (mPendingBroadcast != null) { if (DEBUG_BROADCAST_LIGHT) { Slog.v(TAG, "processNextBroadcast: waiting for " + mPendingBroadcast.curApp); } boolean isDead; synchronized (mPidsSelfLocked) { isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null); } if (!isDead) { // It's still alive, so keep waiting return; } else { Slog.w(TAG, "pending app " + mPendingBroadcast.curApp + " died before responding to broadcast"); mPendingBroadcast.state = BroadcastRecord.IDLE; mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex; mPendingBroadcast = null; } } boolean looped = false; do {// mOrderedBroadcasts這裏是處理有序隊列的,由於上面沒有傳值,就不分析了 if (mOrderedBroadcasts.size() == 0) { // No more broadcasts pending, so all done! scheduleAppGcsLocked(); if (looped) { // If we had finished the last ordered broadcast, then // make sure all processes have correct oom and sched // adjustments. updateOomAdjLocked(); } return; } 。。。。。 } }十、 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false)的源碼:
private final void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered) { boolean skip = false; if (filter.requiredPermission != null) { ///(1)檢查發送者權限 int perm = checkComponentPermission(filter.requiredPermission, r.callingPid, r.callingUid, -1); if (perm != PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Permission Denial: broadcasting " + r.intent.toString() + " from " + r.callerPackage + " (pid=" + r.callingPid + ", uid=" + r.callingUid + ")" + " requires " + filter.requiredPermission + " due to registered receiver " + filter); skip = true; } } if (r.requiredPermission != null) { ///(2)檢查接受者權限 int perm = checkComponentPermission(r.requiredPermission, filter.receiverList.pid, filter.receiverList.uid, -1); if (perm != PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Permission Denial: receiving " + r.intent.toString() + " to " + filter.receiverList.app + " (pid=" + filter.receiverList.pid + ", uid=" + filter.receiverList.uid + ")" + " requires " + r.requiredPermission + " due to sender " + r.callerPackage + " (uid " + r.callingUid + ")"); skip = true; } } 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) { //這裏爲false 。。。。 } try { if (DEBUG_BROADCAST_LIGHT) { int seq = r.intent.getIntExtra("seq", -1); Slog.i(TAG, "Delivering to " + filter + " (seq=" + seq + "): " + r); } performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky); if (ordered) { r.state = BroadcastRecord.CALL_DONE_RECEIVE; } } catch (RemoteException e) { Slog.w(TAG, "Failure sending broadcast " + r.intent, e); if (ordered) { r.receiver = null; r.curFilter = null; filter.receiverList.curBroadcast = null; if (filter.receiverList.app != null) { filter.receiverList.app.curReceiver = null; } } } } }十一、performReceiveLocked()源碼:
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 { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky); } }
App爲activity組件,app.thread即爲應用運行進程的一個ApplicationThread的代理對象。
十二、scheduleRegisteredReceiver源碼:
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(receiver.asBinder()); intent.writeToParcel(data, 0); data.writeInt(resultCode); data.writeString(dataStr); data.writeBundle(extras); data.writeInt(ordered ? 1 : 0); data.writeInt(sticky ? 1 : 0); mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); }1三、接下來是ActivityThread中的 的方法
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封裝了一個廣播接收者
14 、 receiver.performReceive源碼:
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky) { LoadedApk.ReceiverDispatcher rd = mDispatcher.get(); if (ActivityThread.DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null)); } if (rd != null) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky); } else { // The activity manager dispatched a broadcast to a registered // receiver in this process, but before it could be delivered the // receiver was unregistered. Acknowledge the broadcast on its // behalf so that the system's broadcast sequence can continue. if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing broadcast to unregistered receiver"); IActivityManager mgr = ActivityManagerNative.getDefault(); try { if (extras != null) { extras.setAllowFds(false); } mgr.finishReceiver(this, resultCode, data, extras, false); } catch (RemoteException e) { Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver"); } } }
1五、 rd.performReceive的源碼:
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky) { if (ActivityThread.DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq + " to " + mReceiver); } Args args = new Args(intent, resultCode, data, extras, ordered, sticky); if (!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); } } }
註釋:將intent所描述的廣播封裝成一個args對象,而後把它封裝成一個消息,添加到主程序的消息隊列中。
1六、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; } try { ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); setExtrasClassLoader(cl); receiver.setPendingResult(this); receiver.onReceive(mContext, intent); } 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)) { throw new RuntimeException( "Error receiving broadcast " + intent + " in " + mReceiver, e); } } if (receiver.getPendingResult() != null) { finish(); } }
註釋:請看這行代碼 receiver.onReceive(mContext, intent);,這就是調用了廣播接收器中的onReceive方法。咱們在自定義中的廣播接收器中,常常重寫這個方法