1. 程式人生 > >Android廣播接收器

Android廣播接收器

Android中的廣播,即BroadcastReceiver,是應用開發中四大元件之一,通過傳送/接收廣播,可以實現不同元件的通訊。

廣播的分類

根據是否跨程序,可分為全域性廣播和本地廣播。
全域性廣播:廣播可以傳送給不同程序,可以接收不同程序廣播訊息

本地廣播:
使用LocalBroadcastManager.getInstance(context).sendBroadcast傳送本地廣播
使用本地廣播相比全域性廣播有如下優勢:
1.保護隱私: 廣播的資料不會離開當前程序,不用擔心資料會洩露;
2.安全: 其他應用不可能傳送該廣播給當前程序, 因此不用擔心安全漏洞;
3.效率: 與全域性廣播在整個系統傳播相比,本地廣播效率更高;

根據廣播接收順序,可分為兩類:
1.普通廣播
- 通過Context.sendBroadcast傳送
- 廣播是以非同步方式傳送
- 廣播的接收者執行順序不確定
- 廣播接收者不能使用彼此之間的結果,不能放棄廣播

2.有序廣播
- 通過Context.sendOrderedBroadcast傳送
- 一次傳送給一個接收者,接收者按順序進行
- 當前廣播接收者可以傳遞結果給下一個接收者
- 當前廣播接收者可以放棄廣播,則它後面的廣播接收都將收不到該廣播
- 可以通過設定android:priority屬性控制廣播接收的順序,如果優先順序相同則順序不確定


普通廣播又有:
1.粘性廣播
- 可通過Context.sendStickyBroadcast傳送粘性廣播。
- 粘性廣播發送的是訊息是粘性的(sticky),Receiver如果在接收粘性廣播前被銷燬,那麼下次重新建立時會再次接收到該廣播。
- 傳送粘性廣播需要許可權 android.permission.BROADCAST_STICKY
- 在onReceive中接收粘性廣播:
 if(isInitialStickyBroadcast){
//接收粘性訊息
 }else{
//接收新訊息
 }

2.定向廣播
給指定的應用傳送廣播
Intent intent = new Intent(action);
intent.setComponent(new ComponentName(packageName,className));
sendBroadcast(intent);

安全問題

(1)Intent的名稱空間是全域性的。確保廣播的Intent action只適用於你自己的名稱空間中,否則可能和其他應用衝突。
(2)當使用registerReceiver(BroadcastReceiver, IntentFilter)註冊廣播接收者時,任何應用都有可能傳送廣播給該接收者。可以新增許可權來控制誰可以給它發廣播。
(3)在應用的manifest指定廣播接收者並且指定intent-filters時,任何其他應用都可以給它傳送廣播而不管這個filter。為阻止其他應用給它傳送廣播,可使用android:exported="false"
(4)當使用sendBroadcast(Intent)或相關API時,一般情況任意其他應用都有可能收到廣播。可以通過設定許可權來控制誰可以接收該廣播。從ICS開始,可以通過使用Intent.setPackage限制廣播只發給單個應用。
所有以上問題在LocalBroadcastManager中都沒有,因為廣播的intent不會超出當前程序。

傳送廣播時強加許可權,可以通過給sendBroadcast(Intent, String)或sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)
傳遞非空的許可權引數來完成。只有擁有相應許可權(在AndroidManifest.xml中使用<uses-permission>申請許可權)的廣播接收者才能收到傳送的廣播。

接收廣播時強加許可權,可以通過在註冊廣播時提供非空許可權引數來完成(靜態或動態註冊都可以)。

只有擁有相應許可權(在AndroidManifest.xml中使用<uses-permission>申請許可權)的廣播發送者才能給該接收者傳送廣播。

廣播生命週期

一個BroadcastReceiver物件只在onReceive(Context, Intent)方法執行期間有效,一旦該方法返回,系統認為該物件已經結束,不再處於活動狀態。
實現onReceive(Context, Intent) 方法時應注意,不要使用非同步的操作,因為你需要在方法結束後呼叫非同步處理程式,但那個時候廣播接收器已經不處於活動狀態,系統隨時可以在非同步操作完成之前殺掉程序。

特別是不要在廣播接收器中顯示對話方塊或繫結服務。對於前者,應使用NotificationManager API來代替,對於後者,可以使用Context.startService()啟動服務。

onReceive方法執行在主執行緒(UI執行緒),因此不要做耗時操作,否則執行時間超過10s 會造成ANR現象。

當前執行廣播(即當前執行廣播接收器onReceive方法)的程序會被系統認為是前臺程序,除非是記憶體極度不夠的情況,否則系統不會殺掉該程序。
一旦onReceive方法返回,廣播接收器不是活動狀態,它的宿主程序的重要程度只和任何其他執行的應用元件一樣。這點特別重要,因為假如程序只執行廣播接收器,那麼onReceive方法返回後系統認為該程序是空程序,從而容易殺掉它以便給其他更重要的程序提供更多資源。
這意味著對於長時間的操作,應該使用service,結合廣播接收器以使整個操作期間程序處於活躍狀態。