Skip to content

Instantly share code, notes, and snippets.

@tanhauhau
Created August 20, 2015 04:24
Show Gist options
  • Save tanhauhau/0eadd4ec2bb523e200a5 to your computer and use it in GitHub Desktop.
Save tanhauhau/0eadd4ec2bb523e200a5 to your computer and use it in GitHub Desktop.
Wakeful Scheduled Service
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
/**
* Created by lhtan on 20/8/15.
* Refer from: https://randling.wordpress.com/2013/12/29/wakeful-and-repeatable-background-service-on-android/#comment-690
*/
public abstract class AlarmReceiver extends WakefulBroadcastReceiver {
public static final String EXTRA_SERVICE = "extra-service";
public static final String EXTRA_SERVICE_BUNDLE = "extra-bundle";
private final String LOG_TAG = "AlarmReceiver";
@Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
BootListener bootListener = getBootListener();
if (bootListener != null) {
bootListener.onBootCompleted(context, intent);
}
return;
}
Bundle extras = intent.getExtras();
String className = extras.getString(EXTRA_SERVICE);
Bundle intentExtras = extras.getBundle(EXTRA_SERVICE_BUNDLE);
Log.i(LOG_TAG, "intent received to execute service: " + className);
try {
Class<?> serviceClass = Class.forName(className);
Intent serviceIntent = new Intent(context, serviceClass);
serviceIntent.putExtras(intentExtras);
startWakefulService(context, serviceIntent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private abstract BootListener getBootListener();
}
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<receiver android:name=".receiver.AlarmReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.Application;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import java.util.Date;
/**
* Created by lhtan on 20/8/15.
* Refer from: https://randling.wordpress.com/2013/12/29/wakeful-and-repeatable-background-service-on-android/#comment-690
*/
public abstract class ScheduledService extends IntentService{
protected static final int REQUEST_CODE = 101;
private final String LOG_TAG = "ScheduledService";
private String serviceName;
public ScheduledService(String name) {
super(name);
serviceName = name;
}
@Override
protected void onHandleIntent(Intent intent) {
try {
Log.i(LOG_TAG, "Starting service " + serviceName);
executeBackgroundService(intent);
Log.i(LOG_TAG, serviceName + " completed.");
} catch (Exception e) {
e.printStackTrace();
}
}
abstract protected long getNextScheduleTime();
protected String getServiceName() {
return serviceName;
}
protected abstract Intent getServiceIntent(Context context);
protected abstract void executeBackgroundService(Intent intent) throws Exception;
public void scheduleService(Context context, boolean forceReshedule) {
if (isScheduled()) {
if (forceReshedule) {
cancelSchedule();
}else {
Log.i(LOG_TAG, getServiceName() + " is already scheduled.");
return;
}
}
scheduleServiceImpl(context);
}
public void scheduleService(Context context) {
scheduleService(context, false);
}
protected void scheduleServiceImpl(Context context) {
Intent intent = getServiceIntent(context);
PendingIntent pendingIntent = PendingIntent.getService(context, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
scheduleAlarm(am, pendingIntent, getNextScheduleTime());
}
@TargetApi(Build.VERSION_CODES.KITKAT)
protected void scheduleAlarm(AlarmManager am, PendingIntent pendingIntent, long time) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
}else {
am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
}
Log.i(LOG_TAG, "Scheduled " + getServiceName() + " to run at " + new Date(time));
}
protected boolean isScheduled() {
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), REQUEST_CODE,
getServiceIntent(getApplicationContext()), PendingIntent.FLAG_NO_CREATE);
return (pendingIntent != null);
}
protected void cancelSchedule() {
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), REQUEST_CODE,
getServiceIntent(getApplicationContext()), PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null) {
Log.i(LOG_TAG, "Cancelling last schedule for " + getServiceName());
AlarmManager am = (AlarmManager) getApplicationContext().getSystemService(ALARM_SERVICE);
am.cancel(pendingIntent);
}
}
}
import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import java.util.Objects;
/**
* Created by lhtan on 20/8/15.
* Refer from: https://randling.wordpress.com/2013/12/29/wakeful-and-repeatable-background-service-on-android/#comment-690
*/
public abstract class WakefulScheduledService extends ScheduledService {
private final String LOG_TAG = "ScheduledService";
public WakefulScheduledService(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
try {
super.onHandleIntent(intent);
} finally {
AlarmReceiver.completeWakefulIntent(intent);
}
}
protected void scheduleServiceImpl(Context context) {
Intent intent = getAlarmReceiverIntent(context);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
long time = getNextScheduleTime();
scheduleAlarm(am, pendingIntent, time);
}
protected Intent getAlarmReceiverIntent(Context context) {
Intent intent = new Intent(context, AlarmReceiver.class);
Intent serviceIntent = getServiceIntent(context);
intent.setData(Uri.fromParts("execService", serviceIntent.getComponent().getClassName(), null));
intent.putExtra(AlarmReceiver.EXTRA_SERVICE, serviceIntent.getComponent().getClassName());
intent.putExtra(AlarmReceiver.EXTRA_SERVICE_BUNDLE, serviceIntent.getExtras());
return intent;
}
protected boolean isScheduled() {
Intent intent = getAlarmReceiverIntent(getApplicationContext());
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE,
intent, PendingIntent.FLAG_NO_CREATE);
return (pendingIntent != null);
}
protected void cancelSchedule() {
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE,
getAlarmReceiverIntent(getApplicationContext()), PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null) {
Log.i(LOG_TAG, "Cancelling last schedule for " + getServiceName());
AlarmManager am = (AlarmManager) getApplicationContext().getSystemService(ALARM_SERVICE);
am.cancel(pendingIntent);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment