其不受 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
沒有留言:
張貼留言