天天看點

廣播接收者那些事兒(一)

1 簡介

作為入門,本篇将對BroadCast做個簡單介紹。

2 什麼是廣播

廣播其實很簡答,直接拿現實中的廣播做比,其實主要分兩部分,一部分是發廣播,一部分是收廣播。換做我們的專業術語就是廣播發送者和廣播接收者。

3 廣播有什麼用處

  • 同一app内部的同一元件内的消息通信(單個或多個線程之間)
  • 同一app内部的不同元件之間的消息通信(單個程序)
  • 同一app具有多個程序的不同元件之間的消息通信;
  • 不同app之間的元件之間消息通信;
  • Android系統在特定情況下與App之間的消息通信。

4 廣播的類别

以下是幾種常見的廣播:

  • 有序廣播

    廣播的接收者會按照優先級接受廣播,廣播接受者還可以決定該廣播是否被後續接收者接收。

  • 無序廣播

    所有的廣播接收者都會無序收到廣播發送者發出的廣播

  • 系統廣播

    這裡說的系統廣播,其實就是系統已經定義好的一些廣播,比如系統開機廣播,電池電量改變的廣播等。

  • 粘性廣播

    粘性廣播在發送後就一直存在于系統的消息容器裡面,等待對應的處理器去處理,如果暫時沒有處理器處理這個消息則一直在消息容器裡面處于等待狀态,粘性廣播的Receiver如果被銷毀,那麼下次重建時會自動接收到消息資料。

  • 權限廣播

    使用廣播的同時,會遇到以下兩種需求。

    1.一些敏感的廣播并不想讓第三方的應用收到

    2.要限制自己的Receiver接收某廣播來源,避免被惡意的同樣的ACTION的廣播所幹擾

    這種情況,可以考慮使用有序廣播來實作。參考權限廣播的使用

  • App應用内廣播

    簡單來說就是限制了廣播發送者和廣播接收者的範圍,範圍限定在同一應用程序内,避免該應用收到其他應用的影響,又或者可以避免其他程序接收到該程序的廣播。

5 廣播接受者的注冊方式

常見的注冊方式有兩種:

  • 靜态注冊

    簡單來說就是使用XML進行代注冊的形式,例如:

<receiver android:name=".MyBroadcastReceiver" >
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
           

靜态注冊的廣播接收器即使app已經退出,主要有相應的廣播發出,依然可以接收到,但此種描述自Android 3.1開始有可能不再成立。

Android 3.1開始系統在Intent與廣播相關的flag增加了參數,分别是FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES。

FLAG_INCLUDE_STOPPED_PACKAGES:包含已經停止的包(停止:即包所在的程序已經退出)

FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已經停止的包

主要原因如下:

自Android3.1開始,系統本身則增加了對所有app目前是否處于運作狀态的跟蹤。在發送廣播時,不管是什麼廣播類型,系統預設直接增加了值為FLAG_EXCLUDE_STOPPED_PACKAGES的flag,導緻即使是靜态注冊的廣播接收器,對于其所在程序已經退出的app,同樣無法接收到廣播。

詳情參加Android官方文檔:http://developer.android.com/about/versions/android-3.1.html#launchcontrols

由此,對于系統廣播,由于是系統内部直接發出,無法更改此intent flag值,是以,3.1開始對于靜态注冊的接收系統廣播的BroadcastReceiver,如果App程序已經退出,将不能接收到廣播。

但是對于自定義的廣播,可以通過複寫此flag為FLAG_INCLUDE_STOPPED_PACKAGES,使得靜态注冊的BroadcastReceiver,即使所在App程序已經退出,也能能接收到廣播,并會啟動應用程序,但此時的BroadcastReceiver是重新建立的。

  • 動态注冊

    其實就是使用代碼動态注冊,例如:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BROADCAST_ACTION);
registerReceiver(mBroadcastReceiver, intentFilter);
           

繼續閱讀