IntentService.java revision 6e3d9884e4d4e202c9b3b9a5539dd22ffac6467b
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.app; 18 19import android.content.Intent; 20import android.os.Handler; 21import android.os.HandlerThread; 22import android.os.IBinder; 23import android.os.Looper; 24import android.os.Message; 25 26/** 27 * IntentService is a base class for {@link Service}s that handle asynchronous 28 * requests (expressed as {@link Intent}s) on demand. Clients send requests 29 * through {@link Context#startService(Intent)} calls; the service is started as 30 * needed, handles each Intent in turn using a worker thread, and stops itself 31 * when it runs out of work. 32 * 33 * <p>This "work queue processor" pattern is commonly used to offload tasks 34 * from an application's main thread. The IntentService class exists to 35 * simplify this pattern and take care of the mechanics. To use it, extend 36 * IntentService and implement {@link #onHandleIntent(Intent)}. IntentService 37 * will receive the Intents, launch a worker thread, and stop the service as 38 * appropriate. 39 * 40 * <p>All requests are handled on a single worker thread -- they may take as 41 * long as necessary (and will not block the application's main loop), but 42 * only one request will be processed at a time. 43 * 44 * @see android.os.AsyncTask 45 */ 46public abstract class IntentService extends Service { 47 private volatile Looper mServiceLooper; 48 private volatile ServiceHandler mServiceHandler; 49 private String mName; 50 private boolean mRedelivery; 51 52 private final class ServiceHandler extends Handler { 53 public ServiceHandler(Looper looper) { 54 super(looper); 55 } 56 57 @Override 58 public void handleMessage(Message msg) { 59 onHandleIntent((Intent)msg.obj); 60 stopSelf(msg.arg1); 61 } 62 } 63 64 /** 65 * Creates an IntentService. Invoked by your subclass's constructor. 66 * 67 * @param name Used to name the worker thread, important only for debugging. 68 */ 69 public IntentService(String name) { 70 super(); 71 mName = name; 72 } 73 74 /** 75 * Sets intent redelivery preferences. Usually called from the constructor 76 * with your preferred semantics. 77 * 78 * <p>If enabled is true, 79 * {@link #onStartCommand(Intent, int, int)} will return 80 * {@link Service#START_REDELIVER_INTENT}, so if this process dies before 81 * {@link #onHandleIntent(Intent)} returns, the process will be restarted 82 * and the intent redelivered. If multiple Intents have been sent, only 83 * the most recent one is guaranteed to be redelivered. 84 * 85 * <p>If enabled is false (the default), 86 * {@link #onStartCommand(Intent, int, int)} will return 87 * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent 88 * dies along with it. 89 */ 90 public void setIntentRedelivery(boolean enabled) { 91 mRedelivery = enabled; 92 } 93 94 @Override 95 public void onCreate() { 96 // TODO: It would be nice to have an option to hold a partial wakelock 97 // during processing, and to have a static startService(Context, Intent) 98 // method that would launch the service & hand off a wakelock. 99 100 super.onCreate(); 101 HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); 102 thread.start(); 103 104 mServiceLooper = thread.getLooper(); 105 mServiceHandler = new ServiceHandler(mServiceLooper); 106 } 107 108 @Override 109 public void onStart(Intent intent, int startId) { 110 Message msg = mServiceHandler.obtainMessage(); 111 msg.arg1 = startId; 112 msg.obj = intent; 113 mServiceHandler.sendMessage(msg); 114 } 115 116 @Override 117 public int onStartCommand(Intent intent, int flags, int startId) { 118 onStart(intent, startId); 119 return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; 120 } 121 122 @Override 123 public void onDestroy() { 124 mServiceLooper.quit(); 125 } 126 127 @Override 128 public IBinder onBind(Intent intent) { 129 return null; 130 } 131 132 /** 133 * This method is invoked on the worker thread with a request to process. 134 * Only one Intent is processed at a time, but the processing happens on a 135 * worker thread that runs independently from other application logic. 136 * So, if this code takes a long time, it will hold up other requests to 137 * the same IntentService, but it will not hold up anything else. 138 * 139 * @param Intent The value passed to {@link Context#startService(Intent)}. 140 */ 141 protected abstract void onHandleIntent(Intent intent); 142} 143