廣播接收機分為兩類:
從廣播的傳播方式可以分為三類:
廣播在系統中記錄為BroadcastRecord對象,該對象有幾個與時間相關的成員變量。
廣播註冊,用於應用程序開發,經常調用Activity/Service中的registerReceiver()方法,Activity和Service都是從Context抽象類間接繼承的,真正的工作交給ContextImpl類。此外,調用getOuterContext()來獲取最外層的調用方活動或服務。
【ContextImpl.java】
其中broadcastPermission具有廣播的權限控制,scheduler用於在接收廣播時在遞歸執行線程上指定。當scheduler=null時,意味著默認情況下在主線程中執行,這也是最常見的用法。
【ContextImpl.java】
活動管理。getDefault()返回壹個ActivityManagerProxy對象,縮寫為AMP。
此方法中的參數是mmainthread。ApplicationThread(),它是Binder的Bn端,用於system_server進程與此進程之間的通信。
【-》;LoadedApk.java】
讓以BroadcastReceiver為鍵的ArrayMap和LoadedApk。ReceiverDispatcher作為值標記為a .這裏的mReceivers是壹個數組映射,上下文作為鍵,a作為值。對於ReceiverDispatcher,在它不存在時創建壹個。
這裏mActivityThread是先前傳遞的當前主線程的處理程序。
ReceiverDispatcher有壹個內部類InnerReceiver,它繼承自IIntentReceiver.Stub .顯然,這是壹個綁定服務器,廣播分發器可以通過rd.getIIntentReceiver()獲取綁定服務器對象InnerReceiver,用於綁定IPC通信。
【-》;ActivityManagerNative.java】
有兩個Binder服務器對象,caller和receiver,它們表示執行註冊廣播操作的過程。AMP通過Binder驅動程序將這些信息發送給system_server進程中的AMS對象,然後進入AMS.registerReceiver。
【-》;ActivityManagerService.java】
其中,mRegisteredReceivers記錄所有註冊的廣播,receiver IBinder作為鍵,Receiver List作為值和HashMap。
在廣播隊列中,有兩個廣播隊列mparallelbroadcasts和morderedroadcasts,它們都具有ArrayList的數據類型
mLruProcesses數據類型是ArrayList
此方法用於匹配啟動的意向數據是否匹配成功。有四個匹配項:動作、類型、數據、類別,任何不成功的匹配項都將失敗。
broadcastqueueforintent(intentintent)通過判斷intent.getFlags()是否包含FLAG_RECEIVER_FOREGROUND來確定是前臺還是後臺廣播,然後返回對應的廣播隊列mFgBroadcastQueue或mBgBroadcastQueue。
註冊廣播:
此外,當您註冊Sticky Radio時:
廣播註冊後,另壹個操作正在廣播傳輸過程中。
發送廣播是在活動或服務中調用sendBroadcast()方法,這些方法是從Context抽象類間接繼承的,真正的工作交給ContextImpl類。
【ContextImpl.java】
【-》;ActivityManagerNative.java】
【-》;ActivityManagerService.java】
broadcastIntent()方法有兩個布爾參數serialized和sticky,用於共同決定是正常廣播、有序廣播還是粘性廣播。這些參數如下:
BroadcastIntentLocked方法比較長,分為八個部分分別講解。
這個過程中最重要的工作是:
BroadcastReceiver還有其他標誌,位於Intent.java常數:
主要功能:
這主要是在系統相關的10廣播中,所以我在這裏解釋壹下。
這個過程主要是將粘性廣播添加到列表中,並將其放在mStickyBroadcasts中。
其他註意事項:
AMS.collectReceiverComponents:
廣播隊列中有壹個成員變量mParallelBroadcasts,類型為ArrayList
動態註冊的接收器都合並到接收器中,以串行模式處理。
廣播隊列中有壹個ArrayList類型的成員變量mOrderedBroadcasts
發送廣播流程:
處理方法:
可以看到,無論是哪種廣播模式,通過broadcastQueueForIntent()根據意圖的標誌判斷是前臺隊列還是後臺隊列,然後調用廣播隊列對應的scheduleBroadcastsLocked方法處理廣播;
在發送廣播的過程中,執行scheduleBroadcastsLocked方法來處理相關的廣播。
【-》;BroadcastQueue.java】
創建BroadcastQueue對象時,mhandler = newBroadcastHandler(處理程序。get looper());然後mHandler的handleMessage將在這裏處理它:
可以看到BroadcastHandler使用了“ActivityManager”線程的Looper。
【-》;BroadcastQueue.java】
這裏的MS mService是AMS,整個過程還是比較長的,壹直持有AMS鎖。因此,在廣播效率較低的情況下,這款手機的性能和流暢度將受到嚴重影響。這裏,我們應該考慮細化同步鎖的粒度。