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 1983c6896cbf402623ef7d97f13ed65098df63429fTor Norbyeimport android.annotation.WorkerThread; 20ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothianimport android.annotation.Nullable; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.HandlerThread; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 296e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * IntentService is a base class for {@link Service}s that handle asynchronous 306e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * requests (expressed as {@link Intent}s) on demand. Clients send requests 31cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * through {@link android.content.Context#startService(Intent)} calls; the 32cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * service is started as needed, handles each Intent in turn using a worker 33cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * thread, and stops itself when it runs out of work. 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 356e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * <p>This "work queue processor" pattern is commonly used to offload tasks 366e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * from an application's main thread. The IntentService class exists to 376e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * simplify this pattern and take care of the mechanics. To use it, extend 386e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * IntentService and implement {@link #onHandleIntent(Intent)}. IntentService 396e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * will receive the Intents, launch a worker thread, and stop the service as 406e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * appropriate. 416e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 426e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * <p>All requests are handled on a single worker thread -- they may take as 436e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * long as necessary (and will not block the application's main loop), but 446e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * only one request will be processed at a time. 456e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 46b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <div class="special reference"> 47b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <h3>Developer Guides</h3> 48b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * <p>For a detailed discussion about how to create services, read the 491918214589a24b9decd6a70d9f97b8056ae92dcaHemal Patel * <a href="{@docRoot}guide/components/services.html">Services</a> developer 501918214589a24b9decd6a70d9f97b8056ae92dcaHemal Patel * guide.</p> 51b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * </div> 52b54e7a3d9f60ac605f404f9eb3c5e92ca51bbd23Joe Fernandez * 536e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * @see android.os.AsyncTask 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class IntentService extends Service { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private volatile Looper mServiceLooper; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private volatile ServiceHandler mServiceHandler; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mName; 59f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn private boolean mRedelivery; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final class ServiceHandler extends Handler { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ServiceHandler(Looper looper) { 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(looper); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onHandleIntent((Intent)msg.obj); 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stopSelf(msg.arg1); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 736e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor /** 746e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * Creates an IntentService. Invoked by your subclass's constructor. 756e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 766e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * @param name Used to name the worker thread, important only for debugging. 776e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor */ 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public IntentService(String name) { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 83f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn /** 846e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * Sets intent redelivery preferences. Usually called from the constructor 856e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * with your preferred semantics. 866e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 876e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * <p>If enabled is true, 88f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn * {@link #onStartCommand(Intent, int, int)} will return 896e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * {@link Service#START_REDELIVER_INTENT}, so if this process dies before 906e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * {@link #onHandleIntent(Intent)} returns, the process will be restarted 916e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * and the intent redelivered. If multiple Intents have been sent, only 926e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * the most recent one is guaranteed to be redelivered. 936e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 946e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * <p>If enabled is false (the default), 956e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * {@link #onStartCommand(Intent, int, int)} will return 966e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent 976e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * dies along with it. 98f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn */ 99f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn public void setIntentRedelivery(boolean enabled) { 100f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn mRedelivery = enabled; 101f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn } 1026e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onCreate() { 1056e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor // TODO: It would be nice to have an option to hold a partial wakelock 1066e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor // during processing, and to have a static startService(Context, Intent) 1076e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor // method that would launch the service & hand off a wakelock. 1086e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onCreate(); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project thread.start(); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServiceLooper = thread.getLooper(); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServiceHandler = new ServiceHandler(mServiceLooper); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 118ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothian public void onStart(@Nullable Intent intent, int startId) { 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Message msg = mServiceHandler.obtainMessage(); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.arg1 = startId; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.obj = intent; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServiceHandler.sendMessage(msg); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1257a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main /** 1267a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * You should not override this method for your IntentService. Instead, 1277a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * override {@link #onHandleIntent}, which the system calls when the IntentService 1287a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * receives a start request. 1297a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * @see android.app.Service#onStartCommand 1307a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main */ 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 132ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothian public int onStartCommand(@Nullable Intent intent, int flags, int startId) { 133f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn onStart(intent, startId); 134f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; 135f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn } 1366e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor 137f6f9f2d0256930ce0bb4913b2260b8480914edc2Dianne Hackborn @Override 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onDestroy() { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServiceLooper.quit(); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1427a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main /** 1437a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * Unless you provide binding for your service, you don't need to implement this 144ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothian * method, because the default implementation returns null. 1457a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * @see android.app.Service#onBind 1467a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main */ 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 148ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothian @Nullable 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public IBinder onBind(Intent intent) { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1546e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * This method is invoked on the worker thread with a request to process. 1556e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * Only one Intent is processed at a time, but the processing happens on a 1566e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * worker thread that runs independently from other application logic. 1576e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * So, if this code takes a long time, it will hold up other requests to 1586e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * the same IntentService, but it will not hold up anything else. 1597a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * When all requests have been handled, the IntentService stops itself, 1607a14b93bee8e14ace67b8b7dc1579f76e4831773Scott Main * so you should not call {@link #stopSelf}. 1616e3d9884e4d4e202c9b3b9a5539dd22ffac6467bDan Egnor * 162cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * @param intent The value passed to {@link 163cae57d6205a8ebc8599ff89629307ecb8cabb3b8Wu-cheng Li * android.content.Context#startService(Intent)}. 164ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothian * This may be null if the service is being restarted after 165ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothian * its process has gone away; see 166ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothian * {@link android.app.Service#onStartCommand} 167ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothian * for details. 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16983c6896cbf402623ef7d97f13ed65098df63429fTor Norbye @WorkerThread 170ce8d4f51b9405003e664736d81e2374dfc117db9Ryan Lothian protected abstract void onHandleIntent(@Nullable Intent intent); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 172