115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root/* 215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Copyright (C) 2008 The Android Open Source Project 315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * you may not use this file except in compliance with the License. 615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * You may obtain a copy of the License at 715a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 815a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * http://www.apache.org/licenses/LICENSE-2.0 915a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 1015a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Unless required by applicable law or agreed to in writing, software 1115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 1215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * See the License for the specific language governing permissions and 1415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * limitations under the License. 1515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root */ 1615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.app; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.HandlerThread; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 276e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * IntentService is a base class for {@link Service}s that handle asynchronous 286e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * requests (expressed as {@link Intent}s) on demand. Clients send requests 29cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * through {@link android.content.Context#startService(Intent)} calls; the 30cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * service is started as needed, handles each Intent in turn using a worker 31cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * thread, and stops itself when it runs out of work. 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 336e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * <p>This "work queue processor" pattern is commonly used to offload tasks 346e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * from an application's main thread. The IntentService class exists to 356e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * simplify this pattern and take care of the mechanics. To use it, extend 366e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * IntentService and implement {@link #onHandleIntent(Intent)}. IntentService 376e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * will receive the Intents, launch a worker thread, and stop the service as 386e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * appropriate. 396e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 406e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * <p>All requests are handled on a single worker thread -- they may take as 416e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * long as necessary (and will not block the application's main loop), but 426e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * only one request will be processed at a time. 436e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 44b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <div class="special reference"> 45b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <h3>Developer Guides</h3> 46b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <p>For a detailed discussion about how to create services, read the 47b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> developer guide.</p> 48b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * </div> 49b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * 506e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * @see android.os.AsyncTask 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class IntentService extends Service { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private volatile Looper mServiceLooper; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private volatile ServiceHandler mServiceHandler; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mName; 56f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn private boolean mRedelivery; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final class ServiceHandler extends Handler { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ServiceHandler(Looper looper) { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(looper); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onHandleIntent((Intent)msg.obj); 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stopSelf(msg.arg1); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 706e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor /** 716e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * Creates an IntentService. Invoked by your subclass's constructor. 726e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 736e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * @param name Used to name the worker thread, important only for debugging. 746e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor */ 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public IntentService(String name) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 80f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn /** 816e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * Sets intent redelivery preferences. Usually called from the constructor 826e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * with your preferred semantics. 836e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 846e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * <p>If enabled is true, 85f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn * {@link #onStartCommand(Intent, int, int)} will return 866e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * {@link Service#START_REDELIVER_INTENT}, so if this process dies before 876e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * {@link #onHandleIntent(Intent)} returns, the process will be restarted 886e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * and the intent redelivered. If multiple Intents have been sent, only 896e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * the most recent one is guaranteed to be redelivered. 906e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 916e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * <p>If enabled is false (the default), 926e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * {@link #onStartCommand(Intent, int, int)} will return 936e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent 946e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * dies along with it. 95f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn */ 96f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn public void setIntentRedelivery(boolean enabled) { 97f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn mRedelivery = enabled; 98f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn } 996e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onCreate() { 1026e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor // TODO: It would be nice to have an option to hold a partial wakelock 1036e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor // during processing, and to have a static startService(Context, Intent) 1046e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor // method that would launch the service & hand off a wakelock. 1056e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onCreate(); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project thread.start(); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServiceLooper = thread.getLooper(); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServiceHandler = new ServiceHandler(mServiceLooper); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onStart(Intent intent, int startId) { 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Message msg = mServiceHandler.obtainMessage(); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.arg1 = startId; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.obj = intent; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServiceHandler.sendMessage(msg); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1227a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main /** 1237a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * You should not override this method for your IntentService. Instead, 1247a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * override {@link #onHandleIntent}, which the system calls when the IntentService 1257a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * receives a start request. 1267a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * @see android.app.Service#onStartCommand 1277a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main */ 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 129f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn public int onStartCommand(Intent intent, int flags, int startId) { 130f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn onStart(intent, startId); 131f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; 132f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn } 1336e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor 134f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn @Override 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onDestroy() { 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServiceLooper.quit(); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1397a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main /** 1407a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * Unless you provide binding for your service, you don't need to implement this 1417a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * method, because the default implementation returns null. 1427a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * @see android.app.Service#onBind 1437a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main */ 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public IBinder onBind(Intent intent) { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1506e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * This method is invoked on the worker thread with a request to process. 1516e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * Only one Intent is processed at a time, but the processing happens on a 1526e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * worker thread that runs independently from other application logic. 1536e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * So, if this code takes a long time, it will hold up other requests to 1546e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * the same IntentService, but it will not hold up anything else. 1557a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * When all requests have been handled, the IntentService stops itself, 1567a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * so you should not call {@link #stopSelf}. 1576e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 158cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * @param intent The value passed to {@link 159cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * android.content.Context#startService(Intent)}. 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected abstract void onHandleIntent(Intent intent); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 163