-
-
Save klobusnikpeter/d62bb459d15f7022360f326b69e93d70 to your computer and use it in GitHub Desktop.
WakefulBlockingIntentService combining the ease of BlockingIntentService with a partial WakeLock.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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