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 17 package android.app; 18 19 import android.annotation.WorkerThread; 20 import android.content.Intent; 21 import android.os.Handler; 22 import android.os.HandlerThread; 23 import android.os.IBinder; 24 import android.os.Looper; 25 import android.os.Message; 26 27 /** 28 * IntentService is a base class for {@link Service}s that handle asynchronous 29 * requests (expressed as {@link Intent}s) on demand. Clients send requests 30 * through {@link android.content.Context#startService(Intent)} calls; the 31 * service is started as needed, handles each Intent in turn using a worker 32 * thread, and stops itself when it runs out of work. 33 * 34 * <p>This "work queue processor" pattern is commonly used to offload tasks 35 * from an application's main thread. The IntentService class exists to 36 * simplify this pattern and take care of the mechanics. To use it, extend 37 * IntentService and implement {@link #onHandleIntent(Intent)}. IntentService 38 * will receive the Intents, launch a worker thread, and stop the service as 39 * appropriate. 40 * 41 * <p>All requests are handled on a single worker thread -- they may take as 42 * long as necessary (and will not block the application's main loop), but 43 * only one request will be processed at a time. 44 * 45 * <div class="special reference"> 46 * <h3>Developer Guides</h3> 47 * <p>For a detailed discussion about how to create services, read the 48 * <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> developer guide.</p> 49 * </div> 50 * 51 * @see android.os.AsyncTask 52 */ 53 public abstract class IntentService extends Service { 54 private volatile Looper mServiceLooper; 55 private volatile ServiceHandler mServiceHandler; 56 private String mName; 57 private boolean mRedelivery; 58 59 private final class ServiceHandler extends Handler { ServiceHandler(Looper looper)60 public ServiceHandler(Looper looper) { 61 super(looper); 62 } 63 64 @Override handleMessage(Message msg)65 public void handleMessage(Message msg) { 66 onHandleIntent((Intent)msg.obj); 67 stopSelf(msg.arg1); 68 } 69 } 70 71 /** 72 * Creates an IntentService. Invoked by your subclass's constructor. 73 * 74 * @param name Used to name the worker thread, important only for debugging. 75 */ IntentService(String name)76 public IntentService(String name) { 77 super(); 78 mName = name; 79 } 80 81 /** 82 * Sets intent redelivery preferences. Usually called from the constructor 83 * with your preferred semantics. 84 * 85 * <p>If enabled is true, 86 * {@link #onStartCommand(Intent, int, int)} will return 87 * {@link Service#START_REDELIVER_INTENT}, so if this process dies before 88 * {@link #onHandleIntent(Intent)} returns, the process will be restarted 89 * and the intent redelivered. If multiple Intents have been sent, only 90 * the most recent one is guaranteed to be redelivered. 91 * 92 * <p>If enabled is false (the default), 93 * {@link #onStartCommand(Intent, int, int)} will return 94 * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent 95 * dies along with it. 96 */ setIntentRedelivery(boolean enabled)97 public void setIntentRedelivery(boolean enabled) { 98 mRedelivery = enabled; 99 } 100 101 @Override onCreate()102 public void onCreate() { 103 // TODO: It would be nice to have an option to hold a partial wakelock 104 // during processing, and to have a static startService(Context, Intent) 105 // method that would launch the service & hand off a wakelock. 106 107 super.onCreate(); 108 HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); 109 thread.start(); 110 111 mServiceLooper = thread.getLooper(); 112 mServiceHandler = new ServiceHandler(mServiceLooper); 113 } 114 115 @Override onStart(Intent intent, int startId)116 public void onStart(Intent intent, int startId) { 117 Message msg = mServiceHandler.obtainMessage(); 118 msg.arg1 = startId; 119 msg.obj = intent; 120 mServiceHandler.sendMessage(msg); 121 } 122 123 /** 124 * You should not override this method for your IntentService. Instead, 125 * override {@link #onHandleIntent}, which the system calls when the IntentService 126 * receives a start request. 127 * @see android.app.Service#onStartCommand 128 */ 129 @Override onStartCommand(Intent intent, int flags, int startId)130 public int onStartCommand(Intent intent, int flags, int startId) { 131 onStart(intent, startId); 132 return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; 133 } 134 135 @Override onDestroy()136 public void onDestroy() { 137 mServiceLooper.quit(); 138 } 139 140 /** 141 * Unless you provide binding for your service, you don't need to implement this 142 * method, because the default implementation returns null. 143 * @see android.app.Service#onBind 144 */ 145 @Override onBind(Intent intent)146 public IBinder onBind(Intent intent) { 147 return null; 148 } 149 150 /** 151 * This method is invoked on the worker thread with a request to process. 152 * Only one Intent is processed at a time, but the processing happens on a 153 * worker thread that runs independently from other application logic. 154 * So, if this code takes a long time, it will hold up other requests to 155 * the same IntentService, but it will not hold up anything else. 156 * When all requests have been handled, the IntentService stops itself, 157 * so you should not call {@link #stopSelf}. 158 * 159 * @param intent The value passed to {@link 160 * android.content.Context#startService(Intent)}. 161 */ 162 @WorkerThread onHandleIntent(Intent intent)163 protected abstract void onHandleIntent(Intent intent); 164 } 165