Android廣播機制分析

來源:互聯網
上載者:User

標籤:android開發   安全   broadcast   broadcastreceiver   

1.1. 廣播簡介
        Android 廣播與生活中的廣播概念不同,它是指系統中產生事件後的通知。Android 廣播不關心接收者是否收到處理或者如何處理廣播,可以說是一種單向的通知。
        Android 通過 BraodcastReceiver 來監聽系統發出的廣播,不同的 BraodcastReceiver 通過設定不同的 fliter 來區分監聽廣播的類型。有些廣播的監聽需要相應的許可權。

1.2. 註冊廣播
        BraodcastReceiver 必須經過註冊才能具有監聽功能,註冊的方式有兩種:
1.2.1. 靜態註冊
        通過在 AndroidManifest.xml 中註冊對應的 receiver,並設定要監聽的 action


        其中 MyReceiver 為繼承 BroadcastReceiver 的類,重寫了 onReceiver 方法,並在 onReceiver方法中對廣播進行處理。<intent-filter>標籤設定過濾器,接收指定 action 廣播。靜態註冊方式的特點:不管改應用程式是否處於活動狀態,都會進行監聽。action 可以為自訂 action,也可以是系統內建的 action。


1.2.2. 動態註冊
動態註冊是在程式中對 BroadcastReceiver 完成監聽註冊
MyReceiver receiver = new MyReceiver();//建立過濾器,並指定 action,使之用於接收同 action 的廣播IntentFilter filter = new IntentFilter("MyReceiver_Action");//註冊廣播接收器registerReceiver(receiver, filter);在 activity 中註冊廣播,必須在 activity 結束時登出廣播,一般在 onStart 中註冊BroadcastReceiver,在 onStop 中取消 BroadcastReceiver,廣播接收器跟隨 Activity 的生命週期//登出廣播接收器unregisterReceiver(receiver);


1.3. 生命週期
        BroadcastReceiver 生命週期只有 8 秒左右,如果在 onReceive()內做超過 8 秒內的事情,就會報ANR(Application Not Response)程式無響應的錯誤資訊。它的生命週期為從回調 onReceive()方法開始到該方法返回結果後結束。因此,如果要在收到廣播後做耗時操作,最好放到 service 中去做,子線程也不好,當子線程未結束的時候,BroadcastReceiver 已經銷毀。


1.4. 發送廣播
1.4.1. Android 中發送廣播的三種形式
        廣播被分為三種不同的類型:“普通廣播(Normal broadcasts)”、“有序廣播(Ordered broadcasts)”和“粘性廣播(Sticky broadcast)”。普通廣播是完全非同步,可以在同一時刻(邏輯上)被所有廣播接收者接收到,訊息傳遞的效率比較高,但缺點是:接收者不能將處理結果傳遞給下一個接收者,並且無法終止廣播 Intent 的傳播;然而有序廣播是按照接收者聲明的優先順序別(聲明在intent-filter 元素的 android:priority 屬性中,數越大優先順序別越高,取值範圍:-1000 到 1000(其實最大可以為 int 最大值即:2147483647)。也可以調用 IntentFilter 對象的 setPriority()進行設定),被接收者依次接收廣播。如:A 的層級高於 B,B 的層級高於 C,那麼,廣播先傳給 A,再傳給 B,最後傳給 C。A 得到廣播後,可以往廣播裡存入資料,當廣播傳給 B 時,B 可以從廣播中得到 A 存入的資料。Context.sendBroadcast()發送的是普通廣播,所有訂閱者都有機會獲得並進行處理。Context.sendOrderedBroadcast()發送的是有序廣播,系統會根據接收者聲明的優先順序別按順序逐個執行接收者,前面的接收者有權終止廣播。BroadcastReceiver.abortBroadcast()如果廣播被前面的接收者終止,後面的接收者就再也無法擷取到廣播。對於有序廣播,前面的接收者可以將處理結果存放進廣播 Intent,然後傳給下一個接收者。Context.sendStickyBroadcast()是發送粘性廣播,使用這個 api需要許可權 android.Manifest.permission.BROADCAST_STICKY,粘性廣播的特點是 Intent 會一直保留到廣播事件結束,而這種廣播也沒有所謂的 8 秒限制,即上文所講,如果 onReceive 方法執行時間太長,超過 8 秒的時候系統會將這個廣播置為可以幹掉的 candidate,一旦系統資源不夠的時候,就會幹掉這個廣播而讓它不執行。
1.5. 廣播優先順序
1.5.1. 基本原則
接收無序廣播的接收器接收到廣播的順序是有序的(由優先順序決定順序)
接收無序廣播的接收器也一樣可以設定優先權的
動態註冊廣播優先順序高於靜態註冊廣播
同等優先順序的動態接收器,先註冊的先接收
同等優先順序的靜態接收器,接收廣播的順序與 String[] java.io.File.list()順序一致
Ps:這裡有一點需要注意的是,同等優先順序的靜態接收器的接收順序具有不確定性,原因就是File.list()的方法返回的順序具有不確定性,如果需要查看某接收器的接收順序,最好是實驗大量的 apk 名。

1.5.2. ordered 廣播
假設有如下優先順序的 5 個接收器
1.動態 A(優先順序=1)
2.動態 B(優先順序=2)
3.動態 C(優先順序=2)
4.靜態 D(優先順序=1)
5.靜態 E(優先順序=2)
並且 B 先於 C 註冊
那麼實際接收順序應為
B C E A D
也就是說,如果靜態接收器的優先順序高於動態接收器的優先順序,那麼還是靜態接收器先接收到廣播(比如接收 SMS 廣播)

1.5.3. 非 ordered 廣播
        動態接收器高優先順序>動態接收器低優先順序>靜態接收器高優先順序>靜態接收器低優先順序

1.6. 只能動態接受廣播源碼分析
有些廣播,我們無法用靜態接收器接收,比如 ACTION_SCREEN_ON,當螢幕被點亮的時候系統發送此廣播。
1. void com.android.server.PowerManagerService.initInThread()2. Java 代碼3. void initInThread() {4. ??5. mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);6. mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);7. mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);8. mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);9. ??10. }

        Intent 中都設定了 Intent.FLAG_RECEIVER_REGISTERED_ONLY,所以,如果要接收,必須動態註冊廣播接收器 ACTION_SCREEN_OFF 也是如此。

1.6.1. 關於 FLAG_RECEIVER_REGISTERED_ONLY 的說明
public static final int
FLAG_RECEIVER_REGISTERED_ONLY
Added in API level 1
If set, when sending a broadcast only registered receivers will be called -- no
BroadcastReceiver components will be launched.
Constant Value: 1073741824 (0x40000000)
ACTION_BATTERY_CHANGED(電池電量發生變化的時候,系統發送此廣播)該廣播就是這樣
void com.android.server.BatteryService.sendIntent()
Java 代碼1. private final void sendIntent() {2. //3. Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);4. intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY5.Pack up the values and broadcast them to everyone6.7. }

1.7. 廣播註冊過程分析
1.7.1. 靜態註冊 Receiver 的流程
        靜態 receiver 的註冊是由 PackageManagerService 開機的時候負責初始 PMS 在開機的時候會對系統一些目錄逐個掃描,解析 apk 檔案。靜態廣播接收器就是在 PMS 做這件事情的時候順便處理的。
PMS 會解析 apk 的 manifest 檔案,尋找這裡註冊的 receiver,然後載入到記憶體中。
PMS 初始化掃描目錄的順序:
system/framework
system/app
vendor/app
data/appd
rm/app-private
        我們看到了 PMS 如何在初始化的時候如何解析 manifest 並把其中的 element 存放到記憶體中的其中receiver 儲存到了 owner 的成員變數 receivers 中,owner 的類型是
android.content.pm.PackageParser.Package 也就是說 scanPackageLI 返回結果就是已經包含了manifest 資訊的 Package 對象。

1.7.2. 動態註冊 Receiver 的流程
        動態註冊最終會調用到 AMS 中的 registerReceiver 函數,最終所有動態註冊的 receiver 都儲存到 AMS 的成員變數 mReceiverResolver 中。靜態廣播和動態廣播如何註冊的,我們已經全部分析完了。靜態廣播是 PackageManagerService負責,儲存到其成員變數 mReceivers 中,動態廣播是 ActivityManagerService 負責,儲存到其成員變數 mReceiverResolver 中。
1.8. 廣播發送過程分析
1.8.1. 分析
Context 中的 sendBroadCast 函數的實現是在 ContextImpl 中,和發送廣播相關的有如下六個函數:

void android.app.ContextImpl.sendBroadcast(Intent intent)void android.app.ContextImpl.sendBroadcast(Intent intent, String receiverPermission)void android.app.ContextImpl.sendOrderedBroadcast(Intent intent, String receiverPermission)void android.app.ContextImpl.sendOrderedBroadcast(Intent intent, String receiverPermission,BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,Bundle initialExtras)void android.app.ContextImpl.sendStickyBroadcast(Intent intent)void android.app.ContextImpl.sendStickyOrderedBroadcast(Intent intent, BroadcastReceiverresultReceiver, Handler scheduler, int initialCode, String initialData, BundleinitialExtras)
        可以分為 3 組:1 普通廣播;2 Ordered 廣播;3 Sticky 廣播。不論哪種,最後都會由 AMS 處理        如果是非 ordered 廣播,那麼 mParallelBroadcasts 將儲存所有動態接收器,然後合并的時候,mParallelBroadcasts 設定為 null,所以不會合并到 receivers 中,如果是 ordered 廣播,那麼mParallelBroadcasts 將合并到 receivers 中,然後,不管是哪種廣播,最後都是調用scheduleBroadcastsLocked 繼續處理,最終到 processNextBroadcast 函數上。廣播是否有序,即通過 Boolean 變數 ordered 進行設定。

1.8.2. 總結
        發送過程情況分為兩種(scheduleBroadcastsLocked),ordered 廣播和非 ordered 廣播、非ordered 廣播。先處理動接收器,然後處理靜態接收器 ordered 廣播同時處理動態接收器和靜態接收器先將動態接收器與靜態接收器合并,保持著與優先順序相同的順序,優先順序高的在前面,否則順序不變。靜態接收器與動態接收器優先順序相同的話,動態接收器在前。






聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.