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