| package android.app; |
| |
| import android.content.Intent; |
| import android.os.Handler; |
| import android.os.HandlerThread; |
| import android.os.IBinder; |
| import android.os.Looper; |
| import android.os.Message; |
| |
| /** |
| * An abstract {@link Service} that serializes the handling of the Intents passed upon service |
| * start and handles them on a handler thread. |
| * |
| * <p>To use this class extend it and implement {@link #onHandleIntent}. The {@link Service} will |
| * automatically be stopped when the last enqueued {@link Intent} is handled. |
| */ |
| public abstract class IntentService extends Service { |
| private volatile Looper mServiceLooper; |
| private volatile ServiceHandler mServiceHandler; |
| private String mName; |
| private boolean mRedelivery; |
| |
| private final class ServiceHandler extends Handler { |
| public ServiceHandler(Looper looper) { |
| super(looper); |
| } |
| |
| @Override |
| public void handleMessage(Message msg) { |
| onHandleIntent((Intent)msg.obj); |
| stopSelf(msg.arg1); |
| } |
| } |
| |
| public IntentService(String name) { |
| super(); |
| mName = name; |
| } |
| |
| /** |
| * Control redelivery of intents. If called with true, |
| * {@link #onStartCommand(Intent, int, int)} will return |
| * {@link Service#START_REDELIVER_INTENT} instead of |
| * {@link Service#START_NOT_STICKY}, so that if this service's process |
| * is called while it is executing the Intent in |
| * {@link #onHandleIntent(Intent)}, then when later restarted the same Intent |
| * will be re-delivered to it, to retry its execution. |
| */ |
| public void setIntentRedelivery(boolean enabled) { |
| mRedelivery = enabled; |
| } |
| |
| @Override |
| public void onCreate() { |
| super.onCreate(); |
| HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); |
| thread.start(); |
| |
| mServiceLooper = thread.getLooper(); |
| mServiceHandler = new ServiceHandler(mServiceLooper); |
| } |
| |
| @Override |
| public void onStart(Intent intent, int startId) { |
| Message msg = mServiceHandler.obtainMessage(); |
| msg.arg1 = startId; |
| msg.obj = intent; |
| mServiceHandler.sendMessage(msg); |
| } |
| |
| @Override |
| public int onStartCommand(Intent intent, int flags, int startId) { |
| onStart(intent, startId); |
| return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; |
| } |
| |
| @Override |
| public void onDestroy() { |
| mServiceLooper.quit(); |
| } |
| |
| @Override |
| public IBinder onBind(Intent intent) { |
| return null; |
| } |
| |
| /** |
| * Invoked on the Handler thread with the {@link Intent} that is passed to {@link #onStart}. |
| * Note that this will be invoked from a different thread than the one that handles the |
| * {@link #onStart} call. |
| */ |
| protected abstract void onHandleIntent(Intent intent); |
| } |