<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                #### 9.4.2 廣播的發送和接收過程 上面分析了廣播的注冊過程,可以發現注冊過程的邏輯還是比較簡單的,下面來分析廣播的發送和接收過程。當通過send方法來發送廣播時,AMS會查找出匹配的廣播接收者并將廣播發送給它們處理。廣播的發送有幾種類型:普通廣播、有序廣播和粘性廣播,有序廣播和粘性廣播與普通廣播相比具有不同的特性,但是它們的發送/接收過程的流程是類似的,因此這里只分析普通廣播的實現。 廣播的發送和接收,其本質是一個過程的兩個階段。這里從廣播的發送可以說起,廣播的發送仍然開始于ContextWrapper的sendBroadcast方法,之所以不是Context,那是因為Context的sendBroadcast是一個抽象方法。和廣播的注冊過程一樣,ContextWrapper的sendBroadcast方法仍然什么都不做,只是把事情交給ContextImpl去處理,ContextImpl的sendBroadcast方法的源碼如下所示。 public void sendBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false, getUserId()); } catch (RemoteException e) { } } 從上面的代碼來看,ContextImpl也是幾乎什么事都沒干,它直接向AMS發起了一個異步請求用于發送廣播。因此,下面直接看AMS對廣播發送過程的處理,AMS的broadcastIntent方法的源碼如下所示。 public final int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, int appOp, boolean serialized, boolean sticky, int userId) { enforceNotIsolatedCaller("broadcastIntent"); 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, appOp, serialized, sticky, callingPid, callingUid, userId); Binder.restoreCallingIdentity(origId); return res; } } 從上面代碼來看,broadcastIntent調用了broadcastIntentLocked方法,AMS的broadcastIntentLocked方法有436行代碼,看起來比較復雜。在代碼最開始有如下一行: // By default broadcasts do not go to stopped apps. intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); 這表示在Android 5.0中,默認情況下廣播不會發送給已經停止的應用,其實不僅僅是Android 5.0,從Android 3.1開始廣播已經具有這種特性了。這是因為系統在Android 3.1中為Intent添加了兩個標記位,分別是FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES,用來控制廣播是否要對處于停止狀態的應用起作用,它們的含義如下所示。 * FLAG_INCLUDE_STOPPED_PACKAGES 表示包含已經停止的應用,這個時候廣播會發送給已經停止的應用。 * FLAG_EXCLUDE_STOPPED_PACKAGES 表示不包含已經停止的應用,這個時候廣播不會發送給已經停止的應用。 從Android 3.1開始,系統為所有廣播默認添加了FLAG_EXCLUDE_STOPPED_PACKAGES標志,這樣做是為了防止廣播無意間或者在不必要的時候調起已經停止運行的應用。如果的確需要調起未啟動的應用,那么只需要為廣播的Intent添加FLAG_INCLUDE_STOPPED_PACKAGES標記即可。當FLAG_EXCLUDE_STOPPED_PACKAGES和FLAG_INCLUDE_STOPPED_PACKAGES兩種標記位共存時,以FLAG_INCLUDE_STOPPED_PACKAGES為準。這里需要補充一下,一個應用處于停止狀態分為兩種情形:第一種是應用安裝后未運行,第二種是應用被手動或者其他應用強停了。Android 3.1中廣播的這個特性同樣會影響開機廣播,從Android 3.1開始,處于停止狀態的應用同樣無法接收到開機廣播,而在Android 3.1之前,處于停止狀態的應用是可以收到開機廣播的。 在broadcastIntentLocked的內部,會根據intent-filter查找出匹配的廣播接收者并經過一系列的條件過濾,最終會將滿足條件的廣播接收者添加到BroadcastQueue中,接著BroadcastQueue就會將廣播發送給相應的廣播接收者,這個過程的源碼如下所示。 if ((receivers ! = null && receivers.size() > 0) || resultTo ! = null) { BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, resolvedType, requiredPermission, appOp, receivers, resultTo, resultCode, resultData, map, ordered, sticky, false, userId); if (DEBUG_BROADCAST) Slog.v( TAG, "Enqueueing ordered broadcast " + r + ": prev had " + queue.mOrderedBroadcasts.size()); if (DEBUG_BROADCAST) { int seq = r.intent.getIntExtra("seq", -1); Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq); } boolean replaced = replacePending && queue.replaceOrderedBroadcast- Locked(r); if (! replaced) { queue.enqueueOrderedBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } } 下面看一下BroadcastQueue中廣播的發送過程的實現,如下所示。 public void scheduleBroadcastsLocked() { if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts [" + mQueueName + "]: current=" + mBroadcastsScheduled); if (mBroadcastsScheduled) { return; } mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); mBroadcastsScheduled = true; } BroadcastQueue的scheduleBroadcastsLocked方法并沒有立即發送廣播,而是發送了一個BROADCAST_INTENT_MSG類型的消息,BroadcastQueue收到消息后會調用process-NextBroadcast方法,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, "Processing parallel broadcast [" + mQueueName + "] " + r); for (int i=0; i<N; i++) { Object target = r.receivers.get(i); if (DEBUG_BROADCAST) Slog.v(TAG, "Delivering non-ordered on["+mQueueName + "] to registered " + target + ": " + r); deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); } addBroadcastToHistoryLocked(r); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast [" + mQueueName + "] " + r); } 可以看到,無序廣播存儲在mParallelBroadcasts中,系統會遍歷mParallelBroadcasts并將其中的廣播發送給它們所有的接收者,具體的發送過程是通過deliverToRegistered-ReceiverLocked方法來實現的。deliverToRegisteredReceiverLocked方法負責將一個廣播發送給一個特定的接收者,它內部調用了performReceiveLocked方法來完成具體的發送過程: performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky, r.userId); performReceiveLocked方法的實現如下所示。由于接收廣播會調起應用程序,因此app.thread不為null,根據前面的分析我們知道這里的app.thread仍然指ApplicationThread。 private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws Remote- Exception { // 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. app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.repProcState); } 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); } } ApplicationThread的scheduleRegisteredReceiver的實現比較簡單,它通過InnerReceiver來實現廣播的接收,如下所示。 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); } InnerReceiver的performReceive方法會調用LoadedApk.ReceiverDispatcher的perform-Receive方法,LoadedApk.ReceiverDispatcher的performReceive方法的實現如下所示。 public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 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, sendingUser); 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); } } } 在上面的代碼中,會創建一個Args對象并通過mActivityThread的post方法來執行Args中的邏輯,而Args實現了Runnable接口。mActivityThread是一個Handler,它其實就是ActivityThread中的mH, mH的類型是ActivityThread的內部類H,關于H這個類前面已經介紹過了,這里就不再多說了。在Args的run方法中有如下幾行代碼: final BroadcastReceiver receiver = mReceiver; receiver.setPendingResult(this); receiver.onReceive(mContext, intent); 很顯然,這個時候BroadcastReceiver的onReceive方法被執行了,也就是說應用已經接收到廣播了,同時onReceive方法是在廣播接收者的主線程中被調用的。到這里,整個廣播的注冊、發送和接收過程已經分析完了,讀者應該對廣播的整個工作過程有了一定的理解。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看