android學習筆記之Intent與BroadcastReceiver(二)

安卓系統大量的使用了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,不要作耗時的操做。

 

略微完整的DEMO:

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(); 
}

 

在Mainfest中註冊:

<receiver android:name=」.LifeformDetectedReceiver」> 
  <intent-filter> 
     <action android:name=」com.paad.alien.action.NEW_LIFEFORM」/> 
  </intent-filter> 
</receiver>

 

廣播有序的Intents

就是發送有序的廣播,根據廣播接受者的優先級不一樣,優先級高的接收者能夠優先接受到發來的有序廣播,除非你中途停止了廣播(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到這些值。

廣播Sticky Intents

英文意思解釋起來貌似是粘性的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).

相關文章
相關標籤/搜索