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