之前在進行Android開發的過程中,由於某些原因,對android中廣播的注冊等相關知識進行了回顧及總結。也查看了相關源碼及寫demo驗證。發現對廣播的認識更深了一層。下面將所學進行記錄,以備隨時查看。
這些內容在網上也參考了他人的博客,相關鏈接如下:
【1】、基於源碼分析的系統發送廣播的流程:http://blog.csdn.net/zhangyongfeiyong/article/details/52022935 (很詳細,推薦)
【2】、靜態注冊無法接收廣播的問題:http://blog.csdn.net/ocean2006/article/details/40806819
源碼路徑:frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
<一>廣播的發送過程比廣播的注冊過程復雜的多,主要有以下幾個步驟:(摘自上述【1】)
1.廣播的發送者將一個特定類型的廣播發送給ActivityManagerService。
2.AMS接收到這個廣播后,首先找到與這個廣播對應的廣播接收者,然后將它們添加到一個廣播調度隊列中,再將這個調度隊列傳遞給BroadcastQueue,最后向BroadcastQueue的消息隊列發送一個類型為BROADCAST_INTENT_MSG的消息,此時對於廣播發送者來說,一個廣播的發送就完成了。
3.當消息隊列中的BROADCAST_INTENT_MSG消息被處理時,BroadcastQueue就會從廣播調度隊列中找到需要接收廣播的接收者,並且將對應的廣播發送給它們所運行在的應用程序進程。
4.廣播接收者所運行在的應用程序進程接收到廣播后,並不是直接將接收到的廣播分發給各個廣播接收者來處理,而是將接收到的廣播封裝成一個消息,並且發送到主線程的消息隊列中。當這個消息被處理時,應用程序進程才會將它所描述的廣播發送給相應的廣播接收者處理。
<二>對於源碼可主要查看ActivityManagerService中的broadcastIntentLocked():用於查找目標廣播接收者。
<三>注:從Android3.1以后,由於AMS中添加了FLAG_EXCLUDE_STOPPED_PACKAGES標志,導致靜態注冊的廣播接收者在程序從未啟動過時,不會再接收到廣播。(已驗證)
關於Intent中下述兩個標志的說明:
Intent.FLAG_INCLUDE_STOPPED_PACKAGES:即使程序從未啟動過,設置該標志后,該廣播也可以被靜態注冊的廣播接收。
Intent.FLAG_EXCLUDE_STOPPED_PACKAGES:(AMS默認設置)與上述相反.值得注意的是,系統應用不受此標志的影響。(例:push到system/app下的應用,即使從未啟動過,靜態注冊的廣播接收者也可以收到廣播)
<四>另外需要注意的一點:動態廣播需要主動銷毀(unregister),否則易引起內存泄露。而其作用范圍,依賴於注冊其的Activity,應用關閉或注銷廣播則會結束。靜態則會常駐,無論應用程序是否關閉,都能收到廣播(除了上述所說的程序從未啟動過的情況)。
最后附上兩個其他的實際應用廣播的鏈接:
1、應用中監聽SD卡的插拔:http://blog.csdn.net/a443453087/article/details/8085555
----注冊時不要忘記寫<data android:scheme="file" />
2、Android中關於BroadcastReceiver使用的基礎+全面介紹:https://www.jianshu.com/p/ca3d87a4cdf3
關於應用中如何獲取設備外置存儲路徑的方法,請看我另一篇博客:Android獲取外置存儲路徑
聲明:有任何問題或侵犯了上述引用博客的地方請留言,謝謝!