BroadcastReceiver的簡介
BroadcastReceiver翻譯爲廣播接收者,Broadcast是一種廣泛運用在應用程序之間的傳輸信息的機制,簡單的可以理解爲傳統意義上的電臺廣播,通俗一點,發佈失物招領
廣播機制是一個典型的發佈—訂閱模式,也就是我們所說的觀察者模式。廣播最大的特點就是發送方並不關心接收方是否接到數據,也不關心接收方是如何處理數據的,通過這樣的形式來達到接、收雙方的完全解耦合
普通廣播(自定義廣播)
普通廣播是完全異步的,通過Context的sendBroadcast()方法來發送,消息傳遞效率比較高,但所有receivers(接收器)的執行順序不確定。缺點是:接收者不能將處理結果傳遞給下一個接收者,並且無法終止廣播Intent的傳播,直到沒有與之匹配的廣播接收器爲止。下面以自定義的普通廣播進行演示
一、創建廣播
創建廣播非常簡單,只要繼承BroadcastReceiver並實現onReceive()方法
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("receive","onReceive");
}
}
二、註冊廣播
BroadcastReceiver是四大組件之一,所以毫不疑問需要註冊,BroadcastReceiver的註冊有兩種方法:
- 通過manifests配置
- 通過代碼動態配置
1、方法一:通過manifests配置
<receiver android:name=".BroadcastReceiver.MyBroadcastReceiver">
<intent-filter>
<action android:name="com.handsome.hensen" />
</intent-filter>
</receiver>
這裏需要加入intent-filter的action中的name屬性,表示我們監聽的內容。當有廣播發送時,需要判斷該廣播是否和我們監聽的內容一致,如果一致則接收
2、方法二:通過代碼動態配置
//創建廣播
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
//註冊廣播
registerReceiver(receiver, new IntentFilter("com.handsome.hensen"));
三、反註冊廣播
如果你是使用動態註冊廣播的則需要在Activity的onDestroy的時候反註冊廣播
@Override
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
四、發送廣播
這裏我們以一個按鈕來發送廣播,通過sendBroadcast()方法發送我們的創建的Intent自定義廣播
final Intent intent = new Intent();
//廣播內容
intent.setAction("com.handsome.hensen");
bt_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendBroadcast(intent);
}
});
五、運行代碼
運行程序後,我們點擊發送廣播。我們以Log信息來驗證發出的廣播被我們準確的接收
11-25 10:27:43.341 5188-5188/com.handsome.boke2 E/receive: onReceive
有序廣播
有序廣播通過Context.sendOrderedBroadcast()來發送,所有的廣播接收器優先級依次執行,廣播接收器的優先級通過receiver的intent-filter中的android:priority屬性來設置,數值越大優先級越高。
當廣播接收器接收到廣播後,可以使用setResult()函數來結果傳給下一個廣播接收器接收,然後通過getResult()函數來取得上個廣播接收器接收返回的結果。當廣播接收器接收到廣播後,也可以用abortBroadcast()函數來讓系統攔截下來該廣播,並將該廣播丟棄,使該廣播不再傳送到別的廣播接收器接收
一、創建廣播
我們創建一個類,存放三個有優先級的廣播接收者,並在最高級廣播中傳遞結果到下一個廣播
public class PriorityBroadcastReceiver {
public static class HighPriority extends BroadcastReceiver {
//高級廣播接收者
@Override
public void onReceive(Context context, Intent intent) {
Log.e("receive", "High");
//傳遞結果到下一個廣播接收器
int code = 0;
String data = "hello";
Bundle bundle = null;
setResult(code, data, bundle);
}
}
public static class MidPriority extends BroadcastReceiver {
//中級廣播接收者
@Override
public void onReceive(Context context, Intent intent) {
Log.e("receive", "Mid");
//獲取上一個廣播接收器結果
int code = getResultCode();
String data = getResultData();
Log.e("receive", "獲取到上一個廣播接收器結果:" + "code=" + code + "data=" + data);
}
}
public static class LowPriority extends BroadcastReceiver {
//低級廣播接收者
@Override
public void onReceive(Context context, Intent intent) {
Log.e("receive", "Low");
}
}
}
要注意的是:
- 內部類的BroadcastReceiver必須由public static修飾,否則會報錯
二、註冊廣播
這裏的註冊方式和普通廣播是一樣的,這裏的區別在於priority屬性,確定了他們之間的優先級
<receiver android:name=".BroadcastReceiver.PriorityBroadcastReceiver$HighPriority">
<intent-filter android:priority="3000">
<action android:name="com.handsome.hensen2" />
</intent-filter>
</receiver>
<receiver android:name=".BroadcastReceiver.PriorityBroadcastReceiver$MidPriority">
<intent-filter android:priority="2000">
<action android:name="com.handsome.hensen2" />
</intent-filter>
</receiver>
<receiver android:name=".BroadcastReceiver.PriorityBroadcastReceiver$LowPriority">
<intent-filter android:priority="1000">
<action android:name="com.handsome.hensen2" />
</intent-filter>
</receiver>
要注意的是:
- BroadcastReceiver類名與內部類的名字之間用$符號隔開,否則會報錯
三、發送廣播
和之前的不一樣的地方,這裏是使用sendOrderedBroadcast()發送有序廣播
final Intent intent = new Intent();
intent.setAction("com.handsome.hensen2");
bt_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendOrderedBroadcast(intent,null);
}
});
要注意的是:
- 這裏需要發送的是有序廣播,否則在接收者中通過setResult()和getResult()方法會報錯,因爲只有有序廣播才能傳遞結果
四、運行代碼
運行程序後,我們點擊發送廣播。我們以Log信息來驗證發出的廣播被我們準確的接收,數據被我們準確的傳遞
11-25 11:50:07.207 12777-12777/com.handsome.boke2 E/receive: High
11-25 11:50:07.217 12777-12777/com.handsome.boke2 E/receive: Mid
11-25 11:50:07.218 12777-12777/com.handsome.boke2 E/receive: 獲取到上一個廣播接收器結果:code=0data=hello
11-25 11:50:07.233 12777-12777/com.handsome.boke2 E/receive: Low
攔截廣播
上面我們提到過有序廣播中可以攔截廣播,那麼我們在上面程序的基礎上修改代碼,在HighPriority接收器中加上攔截廣播
一、創建廣播
通過在BroadcastReceiver中,執行abortBroadcast()方法,廣播就不會繼續往下傳遞了
public static class HighPriority extends BroadcastReceiver {
//高級廣播接收者
@Override
public void onReceive(Context context, Intent intent) {
Log.e("receive", "High");
//攔截廣播
abortBroadcast();
//傳遞結果到下一個廣播接收器
int code = 0;
String data = "hello";
Bundle bundle = null;
setResult(code, data, bundle);
}
}
二、運行代碼
運行程序後,我們點擊發送廣播。我們以Log信息來驗證我們攔截了廣播
11-25 12:12:36.405 30867-30867/com.handsome.boke2 E/receive: High
可以看到,後面的Mid和Low廣播都沒有Log信息,說明我們攔截成功了
三、有序廣播、攔截廣播的拓展——終結廣播
現在有這樣的一個應用場景,按照上面的程序走,只能在第一個廣播中被攔截住了,後面的廣播則不執行。如果這個時候我們需要一個不管有沒有被攔截都必須執行的廣播,我們稱爲終結廣播,那應該怎麼辦。同樣的,發送有序廣播也考慮到這一點,通過以下代碼來發送廣播,並指定我們不管有沒有被攔截都必須執行的終結廣播
bt_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendOrderedBroadcast(intent, null, new PriorityBroadcastReceiver.LowPriority(),
new Handler(), 0, null, null);
}
});
運行代碼,我們查看Log信息
11-25 12:22:33.466 4764-4764/com.handsome.boke2 E/receive: High
11-25 12:22:33.468 4764-4764/com.handsome.boke2 E/receive: Low
可以發現,之前只是有High的Log信息,因爲是被攔截了,而Log信息多了一條Low,說明我們攔截後,還要執行終結廣播
本地廣播
在API21的Support v4包中新增本地廣播,也就是LocalBroadcastManager。由於之前的廣播都是全局的,所有應用程序都可以接收到,這樣就會帶來安全隱患,所以我們使用LocalBroadcastManager只發送給自己應用內的信息廣播,限制在進程內使用
它的用法很簡單,只需要把調用context的sendBroadcast、registerReceiver、unregisterReceiver的地方換爲LocalBroadcastManager.getInstance(Context context)中對應的函數即可。這裏創建廣播的過程和普通廣播是一樣的過程,這裏就不過多介紹了
一、註冊Receiver
//創建廣播
receiver = new MyBroadcastReceiver();
//註冊本地廣播
LocalBroadcastManager.getInstance(ReceiverActivity.this).registerReceiver(receiver,
new IntentFilter("com.handsome.hensen"));
二、反註冊Receiver
LocalBroadcastManager.getInstance(ReceiverActivity.this).unregisterReceiver(receiver);
三、發送異步廣播
final Intent intent = new Intent();
intent.setAction("com.handsome.hensen2");
LocalBroadcastManager.getInstance(ReceiverActivity.this).sendBroadcast(intent);
四、發送同步廣播
LocalBroadcastManager.getInstance(ReceiverActivity.this).sendBroadcastSync(intent);
Sticky廣播
sticky廣播通過Context.sendStickyBroadcast()函數來發送,用此函數發送的廣播會一直滯留,當有匹配此廣播的廣播接收器被註冊後,該廣播接收器就會收到此條信息。使用此函數需要發送廣播時,需要獲得BROADCAST_STICKY權限
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
sendStickyBroadcast只保留最後一條廣播,並且一直保留下去,這樣即使已經有廣播接收器處理了該廣播,當再有匹配的廣播接收器被註冊時,此廣播仍會被接收。如果你只想處理一遍該廣播,可以通過removeStickyBroadcast()函數來實現。這裏創建廣播的過程和普通廣播是一樣的過程,這裏就不過多介紹了
系統廣播
當然系統中也會有很多自帶的廣播,當符合一定條件時,系統會發送一些定義好的廣播,比如:重啓、充電、來電電話等等。我們可以通過action屬性來監聽我們的系統廣播
<receiver android:name=".BroadcastReceiver.MyBroadcastReceiver">
<intent-filter>
<!--重啓設備-->
<action android:name="android.intent.action.REBOOT" />
</intent-filter>
</receiver>
這裏創建廣播的過程和普通廣播是一樣的過程,這裏就不過多介紹了。常用的廣播action屬性有
- 屏幕被關閉之後的廣播:Intent.ACTION_SCREEN_OFF
- 屏幕被打開之後的廣播:Intent.ACTION_SCREEN_ON
- 充電狀態,或者電池的電量發生變化:Intent.ACTION_BATTERY_CHANGED
- 關閉或打開飛行模式時的廣播:Intent.ACTION_AIRPLANE_MODE_CHANGED
- 表示電池電量低:Intent.ACTION_BATTERY_LOW
- 表示電池電量充足,即電池電量飽滿時會發出廣播:Intent.ACTION_BATTERY_OKAY
- 按下照相時的拍照按鍵(硬件按鍵)時發出的廣播:Intent.ACTION_CAMERA_BUTTON
轉自:https://blog.csdn.net/qq_30379689/article/details/53341313