Android BroadcastReceiver學習總結

BroadCast(廣播),概念:一種在系統內進行通信的機制.通過這種機制,它能夠將系統中的某個進程的信息或者意圖傳遞到其他的對這些信息或者意圖感興趣的進程.

廣播發送者:想要主動傳遞自己的信息或者意圖給系統或者特定的接收者,以便其作出響應.

廣播接收者:想要接收系統或者特定進程的某些信息或意圖,以便作出相應的響應.

Android廣播機制包含三個基本要素:

廣播(Broadcast)—– 用於發送廣播。

廣播接收器(BroadcastReceiver)—– 用於接收廣播。

意圖內容(Intent)—– 用於保存廣播相關信息的媒介。

廣播的過程:首先在需要發送信息的地方,把要發送的信息和用於過濾的信息(如Action、Category)裝入一個Intent對象,然後通過調用Context.sendBroadcast()、Context.sendOrderBroadcast()方法,把Intent對象以廣播的方式發出去。當Intent發送以後,所有已經註冊的BroadcastReceiver會檢查註冊時的Intentfilter是否與發送的Intent相匹配,若匹配就會調用BroadcastReceiver的void
onReceive(Context curContext, Intent broadcastMsg)方法,onReceiver()方法執行完成後,BroadcastReceiver的實例就會銷毀。

sendBroadCast():發送普通廣播可以在同一時刻被所有接收者收到

優點:消息傳遞效率高

缺點:各個接收者之間無法通信,無法終止消息傳播

sendOrderedBroadCast:發送有序廣播

接收者將按預先聲明的優先級依次接收廣播消息

優先級設置: android:priority (-1000∽1000)數越大級別越高 也可調用IntentFilter對象的setPriority()設置

上一個接收者可往廣播中壓入數據傳遞給下一個接收者

任意一個接收者都可終止廣播的傳播,下一個就不能接收

註意:

如果找不到合適的BroadcastReceiver組件,應用不會有任何問題。

onReceiver()方法不能在10秒執行完成,會認為該進程無響應。彈出ANR(application no response)的對話框。

源代碼實例如下:

發送普通廣播:

Aactivity:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent();
intent.setAction(“com.coslay.action.CUSTOM_BROADCAST”);
intent.putExtra(“msg”,”簡單的消息”);
sendBroadcast(intent);
}
});
}

程序啟動BroadcastReceiver隻需要兩步:

創建需要啟動的BroadcastReceiver的Intent

調用Context的sendBroadcast()或sendOrderedBroadcast()方法來啟動指定的BroadcastReceiver

BroadcastReceiver:

public class CustomReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context arg0, Intent arg1) {
Toast.makeText(arg0, “接收到的Intent的Action為:”+arg1.getAction()+”\n消息內容是:”+arg1.getStringExtra(“msg”), Toast.LENGTH_LONG).show();
}
}

隻要重寫BroadcastReceiver的onReceive(Context context,Intent intent)方法即可。然後在如下註冊監聽器即可。

AndroidManifest.xml:


指定該BroadcastReceiver能匹配的Intent有兩種方式:

1.使用代碼進行指定:

IntentFilter filter = new IntentFilter(“android.provider.Telephony.SMS_RECEIVED”);

SomeReceiver receiver = new SomeReceiver();

registerReceiver(receiver,filter);

2.在AndroidManifest.xml文件中配置。如上所示。

發送有序廣播:

Aactivity:

button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(“com.coslay.action.SORTED_BROADCAST”);
intent.putExtra(“msg”, “簡單的消息”);
sendOrderedBroadcast(intent, null);
}
});

BroadcastReceiver:

public class SortedBroadcastReceiver
extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, “接收到的Intent的Action為:”+intent.getAction()+”\n消息內容是:”+intent.getStringExtra(“msg”), Toast.LENGTH_LONG).show();
//創建一個Bundle對象,並存入數據
Bundle bundle = new Bundle();
//將bundle存入結果中
bundle.putString(“first”, “第一個BroadcastReceiver存入的消息”);
setResultExtras(bundle);
//取消Broadcast的繼續傳播
//abortBroadcast();
}
}

優先接收到Broadcast的接收者可以通過 setResultExtras(bundle);方法將處理結果存入Broadcast中,然後傳給下一個接收者,下一個接收者通過代碼:Bundle bundle = getResultExtras(true)可以獲取上一個接收者存入的數據。

AndroidManifest.xml:


<intent-filter android:priority=”0″>

接收系統廣播(接收開機廣播啟動服務):

BroadcastReceiver如下:

public class LaunchReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Intent tIntent = new Intent(context
, LaunchService.class);
// 啟動指定Service
context.startService(tIntent);
}
}

Service如下:

public class LaunchService extends Service
{
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onCreate()
{
// 定義1秒執行一行輸出
new Timer().schedule(new TimerTask()
{

@Override
public void run()
{
System.out.println(“—–“
+ new Date() + “—–“);
}
}, 0, 1000);
}
}

AndroidManifest.xml:



BroadcastReceiver可以實現Service與Activity之間的通信:

Activity如下:

public class MusicBox extends Activity implements OnClickListener
{
// 獲取界面中顯示歌曲標題、作者文本框
TextView title, author;
// 播放/暫停、停止按鈕
ImageButton play, stop;
ActivityReceiver activityReceiver;
public static final String CTL_ACTION =
“org.crazyit.action.CTL_ACTION”;
public static final String UPDATE_ACTION =
“org.crazyit.action.UPDATE_ACTION”;
// 定義音樂的播放狀態,0x11代表沒有播放;0x12代表正在播放;0x13代表暫停
int status = 0x11;
String[] titleStrs = new String[] { “心願”, “約定”, “美麗新世界” };
String[] authorStrs = new String[] { “未知藝術傢”, “周蕙”, “伍佰” };

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 獲取程序界面界面中的兩個按鈕
play = (ImageButton) this.findViewById(R.id.play);
stop = (ImageButton) this.findViewById(R.id.stop);
title = (TextView) findViewById(R.id.title);
author = (TextView) findViewById(R.id.author);
// 為兩個按鈕的單擊事件添加監聽器
play.setOnClickListener(this);
stop.setOnClickListener(this);
activityReceiver = new ActivityReceiver();
// 創建IntentFilter
IntentFilter filter = new IntentFilter();
// 指定BroadcastReceiver監聽的Action
filter.addAction(UPDATE_ACTION);
// 註冊BroadcastReceiver
registerReceiver(activityReceiver, filter);
Intent intent = new Intent(this, MusicService.class);

// 啟動後臺Service
startService(intent);
}

// 自定義的BroadcastReceiver,負責監聽從Service傳回來的廣播
public class ActivityReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
// 獲取Intent中的update消息,update代表播放狀態
int update = intent.getIntExtra(“update”, -1);
// 獲取Intent中的current消息,current代表當前正在播放的歌曲
int current = intent.getIntExtra(“current”, -1);
if (current >= 0)
{
title.setText(titleStrs[current]);
author.setText(authorStrs[current]);
}
switch (update)
{
case 0x11:
play.setImageResource(R.drawable.play);
status = 0x11;
break;
// 控制系統進入播放狀態
case 0x12:
// 播放狀態下設置使用暫停圖標
play.setImageResource(R.drawable.pause);
// 設置當前狀態
status = 0x12;
break;
// 控制系統進入暫停狀態
case 0x13:
// 暫停狀態下設置使用播放圖標
play.setImageResource(R.drawable.play);
// 設置當前狀態
status = 0x13;
break;
}
}
}

@Override
public void onClick(View source)
{
// 創建Intent
Intent intent = new Intent(“org.crazyit.action.CTL_ACTION”);
switch (source.getId())
{
// 按下播放/暫停按鈕
case R.id.play:
intent.putExtra(“control”, 1);
break;
// 按下停止按鈕
case R.id.stop:
intent.putExtra(“control”, 2);
break;
}
// 發送廣播,將被Service組件中的BroadcastReceiver接收到
sendBroadcast(intent);
}
}

Service的實例代碼如下:

public class MusicService extends Service
{
MyReceiver serviceReceiver;
AssetManager am;
String[] musics = new String[] { “wish.mp3”, “promise.mp3”,
“beautiful.mp3” };
MediaPlayer mPlayer;
// 當前的狀態,0x11 代表沒有播放 ;0x12代表 正在播放;0x13代表暫停
int status = 0x11;
// 記錄當前正在播放的音樂
int current = 0;

@Override
public IBinder onBind(Intent intent)
{
return null;
}

@Override
public void onCreate()
{
am = getAssets();
// 創建BroadcastReceiver
serviceReceiver = new MyReceiver();
// 創建IntentFilter
IntentFilter filter = new IntentFilter();
filter.addAction(MusicBox.CTL_ACTION);
registerReceiver(serviceReceiver, filter);

// 創建MediaPlayer
mPlayer = new MediaPlayer();
// 為MediaPlayer播放完成事件綁定監聽器
mPlayer.setOnCompletionListener(new OnCompletionListener() //①
{
@Override
public void onCompletion(MediaPlayer mp)
{
current++;
if (current >= 3)
{
current = 0;
}
// 發送廣播通知Activity更改文本框
Intent sendIntent = new Intent(MusicBox.UPDATE_ACTION);
sendIntent.putExtra(“current”, current);
// 發送廣播 ,將被Activity組件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
// 準備、並播放音樂
prepareAndPlay(musics[current]);
}
});
super.onCreate();
}

public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(final Context context, Intent intent)
{
int control = intent.getIntExtra(“control”, -1);
switch (control)
{
// 播放或暫停
case 1:
// 原來處於沒有播放狀態
if (status == 0x11)
{
// 準備、並播放音樂
prepareAndPlay(musics[current]);
status = 0x12;
}
// 原來處於播放狀態
else if (status == 0x12)
{
// 暫停
mPlayer.pause();
// 改變為暫停狀態
status = 0x13;
}
// 原來處於暫停狀態
else if (status == 0x13)
{
// 播放
mPlayer.start();
// 改變狀態
status = 0x12;
}
break;
// 停止聲音
case 2:
// 如果原來正在播放或暫停
if (status == 0x12 || status == 0x13)
{
// 停止播放
mPlayer.stop();
status = 0x11;
}
}
// 發送廣播通知Activity更改圖標、文本框
Intent sendIntent = new Intent(MusicBox.UPDATE_ACTION);
sendIntent.putExtra(“update”, status);
sendIntent.putExtra(“current”, current);
// 發送廣播 ,將被Activity組件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
}
}

private void prepareAndPlay(String music)
{
try
{
// 打開指定音樂文件
AssetFileDescriptor afd = am.openFd(music);
mPlayer.reset();
// 使用MediaPlayer加載指定的聲音文件。
mPlayer.setDataSource(afd.getFileDescriptor(),
afd.getStartOffset(), afd.getLength());
// 準備聲音
mPlayer.prepare();
// 播放
mPlayer.start();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

發佈留言