安卓系統大量的使用了Broadcast Intents去廣播系統的事件,好比網絡鏈接、底座模式的狀態、電話接聽狀態等。 java
固然也能夠自定義的去廣播。 android
當你廣播消息的時候,Intent指定action,data,和category,這樣準確去肯定由哪一個廣播接受者去接受廣播。 git
對於自定義的action,爲了避免重名,一般是以包名爲開頭,如:
public static final String NEW_LIFEFORM_DETECTED =「com.paad.action.NEW_LIFEFORM」; 網絡
咱們知道intent是能夠指定uri標識數據(setData),或者添加額外的基礎類型數據: app
例子:
框架
Intent intent = new Intent(LifeformDetectedReceiver.NEW_LIFEFORM); intent.putExtra(LifeformDetectedReceiver.EXTRA_LIFEFORM_NAME, detectedLifeform); intent.putExtra(LifeformDetectedReceiver.EXTRA_LONGITUDE, currentLongitude); intent.putExtra(LifeformDetectedReceiver.EXTRA_LATITUDE, currentLatitude); sendBroadcast(intent);
那就是大名鼎鼎的BroadcastReceiver(廣播接受者)來接收Broadcast Intents。 ide
做爲組件之一,像activity同樣,也能夠爲其定義intent-filter這裏先不討論。 ui
固然須要爲其註冊,像activity同樣,對於廣播接受者,註冊方式分爲2種:第一種在代碼中動態註冊,第二種就像activity同樣在mainfest中直接註冊聲明。 線程
在mainfest中的接受者,不須要自我的所在的app跑起來,當有合適的Intent發來的時候,它會自動啓動。 code
BroadcastReceiver 框架代碼:
public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //TODO: React to the Intent received. } }
這個Reiceiver的onReceive方法默認在主線程中執行,因此避免ANR,不要作耗時的操做。
public class LifeformDetectedReceiver extends BroadcastReceiver { public final static String EXTRA_LIFEFORM_NAME = 「EXTRA_LIFEFORM_NAME」; public final static String EXTRA_LATITUDE = 「EXTRA_LATITUDE」; public final static String EXTRA_LONGITUDE = 「EXTRA_LONGITUDE」; public static final String ACTION_BURN = 「com.paad.alien.action.BURN_IT_WITH_FIRE」; public static final String NEW_LIFEFORM = 「com.paad.alien.action.NEW_LIFEFORM」; @Override public void onReceive(Context context, Intent intent) { // Get the lifeform details from the intent. Uri data = intent.getData(); String type = intent.getStringExtra(EXTRA_LIFEFORM_NAME); double lat = intent.getDoubleExtra(EXTRA_LATITUDE, 0); double lng = intent.getDoubleExtra(EXTRA_LONGITUDE, 0); Location loc = new Location(「gps」); loc.setLatitude(lat); loc.setLongitude(lng); if (type.equals(「facehugger」)) { Intent startIntent = new Intent(ACTION_BURN, data); startIntent.putExtra(EXTRA_LATITUDE, lat); startIntent.putExtra(EXTRA_LONGITUDE, lng); context.startService(startIntent); } } }
private IntentFilter filter = new IntentFilter(LifeformDetectedReceiver.NEW_LIFEFORM); private LifeformDetectedReceiver receiver = new LifeformDetectedReceiver(); @Override public void onResume() { super.onResume(); // 在運行時註冊。 registerReceiver(receiver, filter); } @Override public void onPause() { // 在暫停狀態註銷。 unregisterReceiver(receiver); super.onPause(); }
<receiver android:name=」.LifeformDetectedReceiver」> <intent-filter> <action android:name=」com.paad.alien.action.NEW_LIFEFORM」/> </intent-filter> </receiver>
就是發送有序的廣播,根據廣播接受者的優先級不一樣,優先級高的接收者能夠優先接受到發來的有序廣播,除非你中途停止了廣播(abortBroadcast),否則會繼續往下傳播。
那麼如何廣播有序的Intents?
String requiredPermission = 「com.paad.MY_BROADCAST_PERMISSION」;
sendOrderedBroadcast(intent, requiredPermission);
<receiver android:name=」.MyOrderedReceiver」 android:permission=」com.paad.MY_BROADCAST_PERMISSION」> <intent-filter android:priority=」100」> <action android:name=」com.paad.action.ORDERED_BROADCAST」 /> </intent-filter> </receiver>
代碼中的話:
IntentFilter 對象的setPriority便可。
一個常見的例子來接收有序廣播:目標是接收一個處理過的結果集。首先把最終接收到結果的接受者優先級設低點,而後比它高的接受者優先處理了這些數據,層層處理,最後的接受者接收到的會是最終的結果。
//在未被最後個接受者接收時,所初始化的值。
int initialResult = Activity.RESULT_OK;
String initialData = null;
String initialExtras = null;
// A special Handler instance on which to receive the final result.
// Specify null to use the Context on which the Intent was broadcast.
Handler scheduler = null;
sendOrderedBroadcast(intent, requiredPermission, finalResultReceiver,
scheduler, initialResult, initialData, initialExtras);
怎麼得到最終的值?
在接受者的onReceive裏,能夠get到這些值。
英文意思解釋起來貌似是粘性的Intent(意圖),那麼什麼是粘性的呢?與其它的intent有什麼不一樣?
答:這種intent會保存與最後一個廣播相關的值,也就是說下一個接收到的也是最近的值。
IntentFilter battery = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent currentBatteryCharge = registerReceiver(null, battery);
上述代碼,你會發現註冊的接收者竟然是爲null,首先這裏是爲了接收到當前系統電池狀態的廣播intent---系統設備狀態廣播(好比電池、還有底座狀態等),它們廣播的是Sticky Intents,因此你常常不須要去弄個接收者去接收這些intents. 只要像上面代碼那樣registerReceiver它會返回最新的intent。
那麼我如何去廣播我本身的Sticky intents?
答:首先,你的App的mainfest必須包含BROADCAST_STICKY權限。而後在程序中,你就可使用sendStickyBroadcast(intent)去發送這樣的廣播。
既然你說這種Intent會保留下值來,那麼我不想要了,如何移除它呢?
答:removeStickyBroadcast(intent).