Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service with priority queue in Android

I'd like to implement an IntentService (source code) that handles intents based on a simple numeric priority. Intents with higher priority should be processed first by the service than intents with lower priority.

Is there anything on Android that does this already? If not, any pointers on how to implement it?

like image 639
hpique Avatar asked Dec 16 '10 15:12

hpique


2 Answers

A first attempt at an implementation of a intent service with priorities, based on CommonsWare's answer and Android's IntentService source code. Will test extensively and edit accordingly.

public abstract class PriorityIntentService extends Service {

    private final class QueueItem implements Comparable<QueueItem> {
        Intent intent;
        int priority;
        int startId;

        @Override
        public int compareTo(QueueItem another) {
            if (this.priority < another.priority) {
                return -1;
            } else if (this.priority > another.priority) {
                return 1;
            } else {
                return (this.startId < another.startId) ? -1 : 1;
            }
        }
    }
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            try {
                final QueueItem item = mQueue.take();
                onHandleIntent(item.intent);
                if (mQueue.isEmpty()) {
                    PriorityIntentService.this.stopSelf();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static final String EXTRA_PRIORITY = "priority";
    private String mName;
    private PriorityBlockingQueue<QueueItem> mQueue;
    private boolean mRedelivery;
    private volatile ServiceHandler mServiceHandler;
    private volatile Looper mServiceLooper;

    public PriorityIntentService(String name) {
        super();
        mName = name;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("PriorityIntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
        mQueue = new PriorityBlockingQueue<QueueItem>();
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    protected abstract void onHandleIntent(Intent intent);

    @Override
    public void onStart(Intent intent, int startId) {
        final QueueItem item = new QueueItem();
        item.intent = intent;
        item.startId = startId;
        final int priority = intent.getIntExtra(EXTRA_PRIORITY, 0);
        item.priority = priority;
        mQueue.add(item);
        mServiceHandler.sendEmptyMessage(0);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }
}
like image 156
hpique Avatar answered Oct 13 '22 06:10

hpique


Not really. There isn't much to IntentService, though. Cooking up a PriorityIntentService backed by a PriorityBlockingQueue, rather than a Handler+Looper, shouldn't be much longer.

like image 29
CommonsWare Avatar answered Oct 13 '22 06:10

CommonsWare