編寫:kesenhoo - 原文:http://developer.android.com/training/run-background-service/report-status.html
這章節(jié)會(huì)演示如何回傳IntentService中執(zhí)行的任務(wù)狀態(tài)與結(jié)果給發(fā)送方。 例如,回傳任務(wù)的執(zhí)行狀態(tài)給Activity并進(jìn)行更新UI。推薦的方式是使用LocalBroadcastManager,這個(gè)組件可以限制broadcast intent只在自己的app中進(jìn)行傳遞。
為了在IntentService中向其他組件發(fā)送任務(wù)狀態(tài),首先創(chuàng)建一個(gè)Intent并在data字段中包含需要傳遞的信息。作為一個(gè)可選項(xiàng),還可以給這個(gè)Intent添加一個(gè)action與data URI。
下一步,通過(guò)執(zhí)行LocalBroadcastManager.sendBroadcast()
來(lái)發(fā)送Intent。Intent被發(fā)送到任何有注冊(cè)接受它的組件中。為了獲取到LocalBroadcastManager的實(shí)例,可以執(zhí)行g(shù)etInstance()。代碼示例如下:
public final class Constants {
...
// Defines a custom Intent action
public static final String BROADCAST_ACTION =
"com.example.android.threadsample.BROADCAST";
...
// Defines the key for the status "extra" in an Intent
public static final String EXTENDED_DATA_STATUS =
"com.example.android.threadsample.STATUS";
...
}
public class RSSPullService extends IntentService {
...
/*
* Creates a new Intent containing a Uri object
* BROADCAST_ACTION is a custom Intent action
*/
Intent localIntent =
new Intent(Constants.BROADCAST_ACTION)
// Puts the status into the Intent
.putExtra(Constants.EXTENDED_DATA_STATUS, status);
// Broadcasts the Intent to receivers in this app.
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
...
}
下一步是在發(fā)送任務(wù)的組件中接收發(fā)送出來(lái)的broadcast數(shù)據(jù)。
為了接受廣播的數(shù)據(jù)對(duì)象,需要使用BroadcastReceiver的子類并實(shí)現(xiàn)BroadcastReceiver.onReceive()
的方法,這里可以接收LocalBroadcastManager發(fā)出的廣播數(shù)據(jù)。
// Broadcast receiver for receiving status updates from the IntentService
private class ResponseReceiver extends BroadcastReceiver
{
// Prevents instantiation
private DownloadStateReceiver() {
}
// Called when the BroadcastReceiver gets an Intent it's registered to receive
@
public void onReceive(Context context, Intent intent) {
...
/*
* Handle Intents here.
*/
...
}
}
一旦定義了BroadcastReceiver,也應(yīng)該定義actions,categories與data用過(guò)濾廣播。為了實(shí)現(xiàn)這些,需要使用IntentFilter。如下所示:
// Class that displays photos
public class DisplayActivity extends FragmentActivity {
...
public void onCreate(Bundle stateBundle) {
...
super.onCreate(stateBundle);
...
// The filter's action is BROADCAST_ACTION
IntentFilter mStatusIntentFilter = new IntentFilter(
Constants.BROADCAST_ACTION);
// Adds a data filter for the HTTP scheme
mStatusIntentFilter.addDataScheme("http");
...
為了給系統(tǒng)注冊(cè)這個(gè)BroadcastReceiver和IntentFilter,需要通過(guò)LocalBroadcastManager執(zhí)行registerReceiver()的方法。如下所示:
// Instantiates a new DownloadStateReceiver
DownloadStateReceiver mDownloadStateReceiver =
new DownloadStateReceiver();
// Registers the DownloadStateReceiver and its intent filters
LocalBroadcastManager.getInstance(this).registerReceiver(
mDownloadStateReceiver,
mStatusIntentFilter);
...
一個(gè)BroadcastReceiver可以處理多種類型的廣播數(shù)據(jù)。每個(gè)廣播數(shù)據(jù)都有自己的ACTION。這個(gè)功能使得不用定義多個(gè)不同的BroadcastReceiver來(lái)分別處理不同的ACTION數(shù)據(jù)。為BroadcastReceiver定義另外一個(gè)IntentFilter,只需要?jiǎng)?chuàng)建一個(gè)新的IntentFilter并重復(fù)執(zhí)行registerReceiver()即可。例如:
/*
* Instantiates a new action filter.
* No data filter is needed.
*/
statusIntentFilter = new IntentFilter(Constants.ACTION_ZOOM_IMAGE);
...
// Registers the receiver with the new filter
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mDownloadStateReceiver,
mIntentFilter);
發(fā)送一個(gè)廣播Intent并不會(huì)啟動(dòng)或重啟一個(gè)Activity。即使是你的app在后臺(tái)運(yùn)行,Activity的BroadcastReceiver也可以接收、處理Intent對(duì)象。但是這不會(huì)迫使你的app進(jìn)入前臺(tái)。當(dāng)你的app不可見(jiàn)時(shí),如果想通知用戶一個(gè)發(fā)生在后臺(tái)的事件,建議使用Notification。永遠(yuǎn)不要為了響應(yīng)一個(gè)廣播Intent而去啟動(dòng)Activity。