Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save klobusnikpeter/d62bb459d15f7022360f326b69e93d70 to your computer and use it in GitHub Desktop.

Select an option

Save klobusnikpeter/d62bb459d15f7022360f326b69e93d70 to your computer and use it in GitHub Desktop.
WakefulBlockingIntentService combining the ease of BlockingIntentService with a partial WakeLock.
package com.nomanprojects.mycartracks.service;
import java.util.LinkedList;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.util.Log;
/**
* WakefulBlockingIntentService combining the ease of BlockingIntentService with a partial WakeLock. An extension of the IntentService class that will block an
* Intent from entering the queue if the same Intent is already in the queue to be run by the Service. A duplicate Intent is defined by the filterEqual()
* method. Blocking, for the purpose of this class, means the duplicate Intent still resides in IntentService's message queue, but onHandleIntent will return
* quickly after identifying the Intent as duplicate.
*
*
* Note: when using this class, make sure to override onHandleBlockingIntent instead of onHandleIntent as you would with IntentService.
*
* @author Sean
* @author Peter Klobusnik
*
*/
public abstract class WakefulBlockingIntentService extends IntentService {
private static final String TAG = WakefulBlockingIntentService.class.getSimpleName();
// Intent Action specifying to do nothing when this Action is encountered in onHandleIntent().
private final static String NO_ACTION = "no_action";
// FIFO queue that mimics what is contained in IntentService's message queue
private LinkedList<Intent> queue;
private static PowerManager.WakeLock lockStatic = null;
synchronized private static PowerManager.WakeLock getLock(Context context) {
if (lockStatic == null) {
PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
lockStatic.setReferenceCounted(true);
}
return (lockStatic);
}
public static void sendWakefulWork(Context ctxt, Intent i) {
getLock(ctxt).acquire();
ctxt.startService(i);
}
public static void sendWakefulWork(Context ctxt, Class clsService) {
sendWakefulWork(ctxt, new Intent(ctxt, clsService));
}
public WakefulBlockingIntentService(String name) {
super(name);
setIntentRedelivery(true);
}
@Override
public void onCreate() {
super.onCreate();
queue = new LinkedList<Intent>();
}
@Override
public void onStart(Intent intent, int startId) {
if (!getLock(this).isHeld()) { // fail-safe for crash restart
getLock(this).acquire();
}
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!getLock(this).isHeld()) { // fail-safe for crash restart
getLock(this).acquire();
}
for (Intent i : queue) {
if (intentEquals(intent, i)) {
intent.setAction(NO_ACTION);
// remove not necessary data
if (intent.getExtras() != null) {
intent.getExtras().clear();
}
break;
}
}
queue.push(intent);
super.onStart(intent, startId);
return (START_REDELIVER_INTENT);
}
@Override
protected void onHandleIntent(Intent intent) {
try {
if (!intent.getAction().equals(NO_ACTION)) {
onHandleBlockingIntent(intent);
} else {
throw new DuplicateIntentException();
}
} catch (DuplicateIntentException e) {
Log.w(TAG, "Already in queue. Skip!");
} catch (Exception e) {
Log.e(TAG, "Error while handling intent!", e);
} finally {
queue.pop();
if (getLock(this).isHeld()) { // fail-safe for crash restart
getLock(this).release();
}
}
}
protected abstract void onHandleBlockingIntent(Intent intent);
protected boolean intentEquals(Intent intent, Intent other) {
return intent.filterEquals(other);
}
@SuppressWarnings("serial")
public class DuplicateIntentException extends Exception {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment