編寫:kesenhoo - 原文:http://developer.android.com/training/run-background-service/report-status.html
這章節會演示如何回傳IntentService中執行的任務狀態與結果給發送方。 例如,回傳任務的執行狀態給Activity並進行更新UI。推薦的方式是使用LocalBroadcastManager,這個組件可以限制broadcast intent只在自己的app中進行傳遞。
為了在IntentService中向其他組件發送任務狀態,首先創建一個Intent並在data字段中包含需要傳遞的信息。作為一個可選項,還可以給這個Intent添加一個action與data URI。
下一步,通過執行LocalBroadcastManager.sendBroadcast()
來發送Intent。Intent被髮送到任何有註冊接受它的組件中。為了獲取到LocalBroadcastManager的實例,可以執行getInstance()。代碼示例如下:
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);
...
}
下一步是在發送任務的組件中接收發送出來的broadcast數據。
為了接受廣播的數據對象,需要使用BroadcastReceiver的子類並實現BroadcastReceiver.onReceive()
的方法,這裡可以接收LocalBroadcastManager發出的廣播數據。
// 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,也應該定義actions,categories與data用過濾廣播。為了實現這些,需要使用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");
...
為了給系統註冊這個BroadcastReceiver和IntentFilter,需要通過LocalBroadcastManager執行registerReceiver()的方法。如下所示:
// Instantiates a new DownloadStateReceiver
DownloadStateReceiver mDownloadStateReceiver =
new DownloadStateReceiver();
// Registers the DownloadStateReceiver and its intent filters
LocalBroadcastManager.getInstance(this).registerReceiver(
mDownloadStateReceiver,
mStatusIntentFilter);
...
一個BroadcastReceiver可以處理多種類型的廣播數據。每個廣播數據都有自己的ACTION。這個功能使得不用定義多個不同的BroadcastReceiver來分別處理不同的ACTION數據。為BroadcastReceiver定義另外一個IntentFilter,只需要創建一個新的IntentFilter並重復執行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);
發送一個廣播Intent並不會啟動或重啟一個Activity。即使是你的app在後臺運行,Activity的BroadcastReceiver也可以接收、處理Intent對象。但是這不會迫使你的app進入前臺。當你的app不可見時,如果想通知用戶一個發生在後臺的事件,建議使用Notification。永遠不要為了響應一個廣播Intent而去啟動Activity。