[心得]Android程序間通訊之Broadcast Receiver
Android框架層提供的一些通訊機制Broadcast、Intent、Content Provider,主要用於應用程式開發時提供跨程序或應用程式內部的通訊。
android中,通過廣播(broadcast)可以通知廣播接受者某個事件發生了。比如一些系統時間:電源不足,時間改變等,也可以是自定義的事件。
有兩種方式可以註冊:靜態註冊(冷註冊)和動態註冊(熱註冊)。
l 冷註冊,就是Broadcast Receiver的相關資訊寫在配置檔案中,系統會負責在相關事件發生的時候及時通知到該Broadcast Receiver。這種模式適合於這樣的場景:某事件發生 -> 通知Broadcast ->
l 熱註冊,顧名思義,註冊這樣的事情都是由應用自己來處理的,通常是在OnResume事件中通過registerReceiver進行註冊,在OnPause等事件中通過unregisterReceiver反註冊,通過這種方式使其能夠在執行期間保持對相關事件的關注。比如,一款優秀的詞典軟體,可能會有在執行期間關注網路狀況變化的需求,使其可以在有廉價網路的時候優先使用網路查詢詞彙,在其他情況下,首先通過本地詞庫來查詞。而這樣的監聽,只需要在其工作狀態下保持就好,不執行的時候,管你是天大的網路變化,與我何干。其模式可以歸結為:啟動應用
冷註冊:
Activity中:
public class MainActivity extends Activity { public static final String NEW_LIFEFROM_DETECTED = "com.android.broadcasttest.BRDEMO1"; private int count=0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn=(Button) findViewById(R.id.btn); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent=new Intent(NEW_LIFEFROM_DETECTED); intent.putExtra("text", String.valueOf(count++)); sendBroadcast(intent); } }); }
繼承一個Broadcast類
public class MyBroadReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.i("BROAD", "receive");
String str=intent.getStringExtra("text");
Toast.makeText(context, "receive:"+str, Toast.LENGTH_LONG).show();
}
}
AndroidManifest中註冊:
<receiver android:name=".MyBroadReceiver"
>
<intent-filter >
<action android:name="com.android.broadcasttest.BRDEMO1"/>
</intent-filter>
</receiver>
熱註冊:
public class MainActivity extends Activity {
BroadcastReceiver br=null;
public static final String NEW_LIFEFROM_DETECTED = "com.android.broadcasttest.BRDEMO1";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn =(Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Date date=new Date();
String str=date.toLocaleString();
Log.i("btn", str);
Intent intent=new Intent(NEW_LIFEFROM_DETECTED);
intent.putExtra("demo2", str);
sendBroadcast(intent);
}
});
br=new BroadcastReceiver() {//在onCreat()中定義
@Override
public void onReceive(Context context, Intent intent) {
System.out.println(intent.getStringExtra("demo2"));
}
};
}
@Override
protected void onResume() {
super.onResume();
IntentFilter intentf=new IntentFilter();
intentf.addAction(NEW_LIFEFROM_DETECTED);
//intentf.addAction(Intent.ACTION_TIME_TICK);
registerReceiver(br, intentf);//在onResume()中註冊
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(br);//不要忘了在onPause()中登出
}
測試結果:
從結果可以看到,點選按鈕之後,通過Log.i("btn", str)列印了一行程式碼,然後通過Intent傳到BroadCast中,通過System.out 列印結果
但最後一行又冒出來一句,PID是不同的,這是前一個Demo也接收到了這個事件(相同的標識)。但反過來,在第一個應用中點選send 第二個卻接收不到。如果要讓第一個不接受別的App的BroadCast,應將第一個的AndroidManifest中的receiver標籤新增一個屬性為:
<receiver android:name=".MyBroadReceiver"
android:exported="false">
<intent-filter >
<action android:name="com.android.broadcasttest.BRDEMO1"/>
</intent-filter>
</receiver>
如果要第二個APP能夠接收到該Broadcast,那麼要在AndroidManifest中新增uses-permission標籤
需要注意的是,當Broadcast Receiver接收到相關的訊息,在OnReceive中不要執行很消耗時間的操作,通常把消耗時間的操作放到一個Service中,在OnReceive中啟動該Service。