其不受 UI 生命週期的影響,所以可以運行在一些 AsyncTask 會被關閉的情況
但限制有:
1. 它不會直接與 UI 進行交互,要顯示結果的話請送到 Activity
2. 同時只能有一個 IntentService 在跑,多個的話會排隊等待
3. IntentService 無法被中斷
使用條件為
1. extends IntentService
2. Override onHandleIntent(Intent)
public class RSSPullService extends IntentService {
@Override
protected void onHandleIntent(Intent workIntent) {
// 從參數的 intent 中取出資料
String dataString = workIntent.getDataString();
// 根據取出的資料進行一些工作
...(省略)
// 把結果放入 intent 中,然後 sendBroadcast 出去
Intent localIntent = new Intent(Constants.BROADCAST_ACTION)
.putExtra(Constants.EXTENDED_DATA_STATUS, status);
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
}
}public final class Constants {
...
// 定義用來收結果的 Intent action
public static final String BROADCAST_ACTION =
"com.example.android.threadsample.BROADCAST";
// 結果的資料欄位
public static final String EXTENDED_DATA_STATUS =
"com.example.android.threadsample.STATUS";
...
}在一般的 Service 類別會有的 onStartCommand() 之類的方法會被自動調用所以不需要去 Override
另外還需要在 manifest 進行宣告
<application
android:icon="@drawable/icon"
android:label="@string/app_name">
...
<!-- android:exported 設為 "false" 所以只能在這個 app 內被使用-->
<service
android:name=".RSSPullService"
android:exported="false"/>
...
<application/>這裡沒有宣告 intent-filter,是因為下面會明確呼叫這個 intent這也意謂只有同一個 app 內相同 user ID 才能存取它
//建立 Intent 並放入 data mServiceIntent = new Intent(getActivity(), RSSPullService.class); mServiceIntent.setData(Uri.parse(dataUrl)); // 執行 IntentService (在 onHandleIntent() 裡面的 code 就會開始執行) getActivity().startService(mServiceIntent);
從前面的 code 知道執行結果會透過 sendBroadcast 發出來
所以我們要用 BroadcastReceiver 收
private class DownloadStateReceiver extends BroadcastReceiver {
// 防止實體化
private DownloadStateReceiver() {}
@Override
public void onReceive(Context context, Intent intent) {
// 當 BroadcastReceiver 收到註冊的 Intent 時會執行 onReceive
...
}
}並在 activity 中定義 IntentFilter// Class that displays photos
public class DisplayActivity extends FragmentActivity {
...
public void onCreate(Bundle stateBundle) {
...
super.onCreate(stateBundle);
...
// 定義 IntentFilter
IntentFilter statusIntentFilter = new IntentFilter(Constants.ACTION_ZOOM_IMAGE);
IntentFilter mStatusIntentFilter = new IntentFilter(Constants.BROADCAST_ACTION);
// Adds a data filter for the HTTP scheme
mStatusIntentFilter.addDataScheme("http");
...
//註冊 BroadcastReceiver 跟 IntentFilter
DownloadStateReceiver mDownloadStateReceiver = new DownloadStateReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(
mDownloadStateReceiver, mStatusIntentFilter);
LocalBroadcastManager.getInstance(this).registerReceiver(
mDownloadStateReceiver, mIntentFilter);
...
BroadcastReceiver 並不會讓 Activity 自動顯示在 foreground所以如果要通知使用者可以用 Notification
(請不要採取收到 Broadcast 就去開啟新 Activity 的做法)
相關資料:
Creating a Background Service
Sending Work Requests to the Background Service
Reporting Work Status
沒有留言:
張貼留言