diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 9b47f1067..3ac54c1b9 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -344,20 +344,6 @@ - - - - - - - - - - - - - - @@ -496,16 +482,19 @@ android:name=".scheduling.AlarmSchedulingIntentService" android:exported="false" /> + diff --git a/src/main/java/com/todoroo/astrid/gtasks/GtasksBackgroundService.java b/src/main/java/com/todoroo/astrid/gtasks/GtasksBackgroundService.java deleted file mode 100644 index e29584351..000000000 --- a/src/main/java/com/todoroo/astrid/gtasks/GtasksBackgroundService.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2012 Todoroo Inc - * - * See the file "LICENSE" for the full license governing this code. - */ -package com.todoroo.astrid.gtasks; - -import android.content.Intent; -import android.os.IBinder; - -import com.todoroo.andlib.service.ContextManager; -import com.todoroo.astrid.gtasks.sync.GtasksSyncV2Provider; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.tasks.Broadcaster; -import org.tasks.injection.InjectingService; -import org.tasks.sync.RecordSyncStatusCallback; - -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.inject.Inject; - -public class GtasksBackgroundService extends InjectingService { - - private static final Logger log = LoggerFactory.getLogger(GtasksBackgroundService.class); - - @Inject GtasksPreferenceService gtasksPreferenceService; - @Inject GtasksSyncV2Provider gtasksSyncV2Provider; - @Inject Broadcaster broadcaster; - - private final AtomicBoolean started = new AtomicBoolean(false); - - /** Receive the alarm - start the synchronize service! */ - @Override - public void onStart(Intent intent, int startId) { - try { - if(intent != null && !started.getAndSet(true)) { - ContextManager.setContext(this); - - if(gtasksPreferenceService.isLoggedIn() && gtasksSyncV2Provider.isActive()) { - gtasksSyncV2Provider.synchronizeActiveTasks(new RecordSyncStatusCallback(gtasksPreferenceService, broadcaster)); - } - } - } catch (Exception e) { - log.error(e.getMessage(), e); - } - } - - @Override - public IBinder onBind(Intent intent) { - return null; - } -} diff --git a/src/main/java/com/todoroo/astrid/gtasks/GtasksPreferences.java b/src/main/java/com/todoroo/astrid/gtasks/GtasksPreferences.java index 5dadc5c12..5ba4a0596 100644 --- a/src/main/java/com/todoroo/astrid/gtasks/GtasksPreferences.java +++ b/src/main/java/com/todoroo/astrid/gtasks/GtasksPreferences.java @@ -24,6 +24,7 @@ import com.todoroo.astrid.gtasks.sync.GtasksSyncV2Provider; import org.tasks.R; import org.tasks.injection.InjectingSyncProviderPreferences; +import org.tasks.scheduling.BackgroundScheduler; import java.util.HashMap; import java.util.Set; @@ -43,7 +44,7 @@ public class GtasksPreferences extends InjectingSyncProviderPreferences { @Inject GtasksPreferenceService gtasksPreferenceService; @Inject GtasksSyncV2Provider gtasksSyncV2Provider; - @Inject GtasksScheduler gtasksScheduler; + @Inject BackgroundScheduler backgroundScheduler; @Override public int getPreferenceResource() { @@ -88,7 +89,7 @@ public class GtasksPreferences extends InjectingSyncProviderPreferences { @Override protected void onPause() { super.onPause(); - gtasksScheduler.scheduleService(); + backgroundScheduler.scheduleGtaskSync(); } public static final int RESULT_CODE_SYNCHRONIZE = 2; diff --git a/src/main/java/com/todoroo/astrid/gtasks/GtasksScheduler.java b/src/main/java/com/todoroo/astrid/gtasks/GtasksScheduler.java deleted file mode 100644 index a405baadd..000000000 --- a/src/main/java/com/todoroo/astrid/gtasks/GtasksScheduler.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.todoroo.astrid.gtasks; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; - -import com.todoroo.andlib.utility.DateUtilities; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.tasks.injection.ForApplication; -import org.tasks.preferences.Preferences; - -import javax.inject.Inject; -import javax.inject.Singleton; - -@Singleton -public class GtasksScheduler { - - private static final Logger log = LoggerFactory.getLogger(GtasksScheduler.class); - - /** Minimum time before an auto-sync */ - private static final long AUTO_SYNC_MIN_OFFSET = 5*60*1000L; - - private final GtasksPreferenceService gtasksPreferenceService; - private Context context; - private Preferences preferences; - - @Inject - public GtasksScheduler(GtasksPreferenceService gtasksPreferenceService, @ForApplication Context context, Preferences preferences) { - this.gtasksPreferenceService = gtasksPreferenceService; - this.context = context; - this.preferences = preferences; - } - - /** - * Schedules repeating alarm for auto-synchronization - */ - public void scheduleService() { - int syncFrequencySeconds = 0; - try { - syncFrequencySeconds = preferences.getIntegerFromString( - gtasksPreferenceService.getSyncIntervalKey(), -1); - } catch(ClassCastException e) { - log.error(e.getMessage(), e); - preferences.setStringFromInteger(gtasksPreferenceService.getSyncIntervalKey(), 0); - } - if(syncFrequencySeconds <= 0) { - unscheduleService(context); - return; - } - - // figure out synchronization frequency - long interval = 1000L * syncFrequencySeconds; - long offset = computeNextSyncOffset(interval); - - // give a little padding - offset = Math.max(offset, AUTO_SYNC_MIN_OFFSET); - - AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - PendingIntent pendingIntent = PendingIntent.getService(context, gtasksPreferenceService.getSyncIntervalKey(), - createAlarmIntent(context), PendingIntent.FLAG_UPDATE_CURRENT); - - log.info("Autosync set for {} seconds repeating every {}", offset / 1000, syncFrequencySeconds); //$NON-NLS-1$ - - // cancel all existing - am.cancel(pendingIntent); - - // schedule new - am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + offset, - interval, pendingIntent); - } - - - /** - * Removes repeating alarm for auto-synchronization - */ - private void unscheduleService(Context context) { - AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); - PendingIntent pendingIntent = PendingIntent.getService(context, gtasksPreferenceService.getSyncIntervalKey(), - createAlarmIntent(context), PendingIntent.FLAG_UPDATE_CURRENT); - am.cancel(pendingIntent); - } - - /** Create the alarm intent */ - private Intent createAlarmIntent(Context context) { - return new Intent(context, GtasksBackgroundService.class); - } - - // --- utility methods - - private long computeNextSyncOffset(long interval) { - // figure out last synchronize time - long lastSyncDate = gtasksPreferenceService.getLastSyncDate(); - - // if user never synchronized, give them a full offset period before bg sync - if(lastSyncDate != 0) { - return Math.max(0, lastSyncDate + interval - DateUtilities.now()); - } else { - return interval; - } - } -} diff --git a/src/main/java/com/todoroo/astrid/gtasks/GtasksStartupReceiver.java b/src/main/java/com/todoroo/astrid/gtasks/GtasksStartupReceiver.java deleted file mode 100644 index ee159436e..000000000 --- a/src/main/java/com/todoroo/astrid/gtasks/GtasksStartupReceiver.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2012 Todoroo Inc - * - * See the file "LICENSE" for the full license governing this code. - */ -package com.todoroo.astrid.gtasks; - -import android.content.Context; -import android.content.Intent; - -import com.todoroo.andlib.service.ContextManager; - -import org.tasks.injection.InjectingBroadcastReceiver; - -import javax.inject.Inject; - -public class GtasksStartupReceiver extends InjectingBroadcastReceiver { - - @Inject GtasksScheduler scheduler; - - @Override - public void onReceive(final Context context, Intent intent) { - super.onReceive(context, intent); - ContextManager.setContext(context); - scheduler.scheduleService(); - } -} diff --git a/src/main/java/org/tasks/injection/BroadcastModule.java b/src/main/java/org/tasks/injection/BroadcastModule.java index 6963ed5d6..48dc4f2dd 100644 --- a/src/main/java/org/tasks/injection/BroadcastModule.java +++ b/src/main/java/org/tasks/injection/BroadcastModule.java @@ -9,7 +9,6 @@ import com.todoroo.astrid.gcal.CalendarStartupReceiver; import com.todoroo.astrid.gcal.GCalTaskCompleteListener; import com.todoroo.astrid.gtasks.GtasksCustomFilterCriteriaExposer; import com.todoroo.astrid.gtasks.GtasksFilterExposer; -import com.todoroo.astrid.gtasks.GtasksStartupReceiver; import com.todoroo.astrid.reminders.Notifications; import com.todoroo.astrid.reminders.ShowNotificationReceiver; import com.todoroo.astrid.repeats.RepeatTaskCompleteListener; @@ -37,7 +36,6 @@ import dagger.Module; TimerTaskCompleteListener.class, RepeatTaskCompleteListener.class, AlarmTaskRepeatListener.class, - GtasksStartupReceiver.class, PhoneStateChangedReceiver.class, ShowNotificationReceiver.class, CoreFilterExposer.class, diff --git a/src/main/java/org/tasks/injection/IntentServiceModule.java b/src/main/java/org/tasks/injection/IntentServiceModule.java index 2d9ca11d8..baa4f91be 100644 --- a/src/main/java/org/tasks/injection/IntentServiceModule.java +++ b/src/main/java/org/tasks/injection/IntentServiceModule.java @@ -8,6 +8,7 @@ import dagger.Module; injects = { AlarmSchedulingIntentService.class, BackupIntentService.class, + GtasksBackgroundService.class, MidnightRefreshService.class, RefreshSchedulerIntentService.class, ReminderSchedulerIntentService.class diff --git a/src/main/java/org/tasks/injection/ServiceModule.java b/src/main/java/org/tasks/injection/ServiceModule.java index a80601e2d..8ec721b14 100644 --- a/src/main/java/org/tasks/injection/ServiceModule.java +++ b/src/main/java/org/tasks/injection/ServiceModule.java @@ -1,6 +1,5 @@ package org.tasks.injection; -import com.todoroo.astrid.gtasks.GtasksBackgroundService; import com.todoroo.astrid.widget.WidgetUpdateService; import org.tasks.widget.ScrollableWidgetUpdateService; @@ -9,7 +8,6 @@ import dagger.Module; @Module(addsTo = TasksModule.class, injects = { - GtasksBackgroundService.class, ScrollableWidgetUpdateService.class, WidgetUpdateService.class }) diff --git a/src/main/java/org/tasks/preferences/Preferences.java b/src/main/java/org/tasks/preferences/Preferences.java index d7d62d530..3469252ed 100644 --- a/src/main/java/org/tasks/preferences/Preferences.java +++ b/src/main/java/org/tasks/preferences/Preferences.java @@ -98,6 +98,10 @@ public class Preferences { } } + public void setString(int key, String newValue) { + setString(context.getString(key), newValue); + } + public void setString(String key, String newValue) { Editor editor = prefs.edit(); editor.putString(key, newValue); diff --git a/src/main/java/org/tasks/scheduling/BackgroundScheduler.java b/src/main/java/org/tasks/scheduling/BackgroundScheduler.java index 1fb7d88c0..625d5e805 100644 --- a/src/main/java/org/tasks/scheduling/BackgroundScheduler.java +++ b/src/main/java/org/tasks/scheduling/BackgroundScheduler.java @@ -21,6 +21,7 @@ public class BackgroundScheduler { context.startService(new Intent(context, ReminderSchedulerIntentService.class)); scheduleBackupService(); scheduleMidnightRefresh(); + scheduleGtaskSync(); } public void scheduleBackupService() { @@ -30,4 +31,8 @@ public class BackgroundScheduler { public void scheduleMidnightRefresh() { context.startService(new Intent(context, MidnightRefreshService.class)); } + + public void scheduleGtaskSync() { + context.startService(new Intent(context, GtasksBackgroundService.class)); + } } diff --git a/src/main/java/org/tasks/scheduling/GtasksBackgroundService.java b/src/main/java/org/tasks/scheduling/GtasksBackgroundService.java new file mode 100644 index 000000000..a2a0a9d19 --- /dev/null +++ b/src/main/java/org/tasks/scheduling/GtasksBackgroundService.java @@ -0,0 +1,59 @@ +package org.tasks.scheduling; + +import com.todoroo.astrid.gtasks.GtasksPreferenceService; +import com.todoroo.astrid.gtasks.sync.GtasksSyncV2Provider; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.tasks.Broadcaster; +import org.tasks.R; +import org.tasks.preferences.Preferences; +import org.tasks.sync.RecordSyncStatusCallback; + +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; + +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; + +public class GtasksBackgroundService extends RecurringIntervalIntentService { + + private static final Logger log = LoggerFactory.getLogger(GtasksBackgroundService.class); + + @Inject Preferences preferences; + @Inject GtasksPreferenceService gtasksPreferenceService; + @Inject GtasksSyncV2Provider gtasksSyncV2Provider; + @Inject Broadcaster broadcaster; + + public GtasksBackgroundService() { + super(GtasksBackgroundService.class.getSimpleName()); + } + + @Override + void run() { + if (gtasksPreferenceService.isOngoing()) { + log.debug("aborting: sync ongoing"); + return; + } + if(gtasksPreferenceService.isLoggedIn() && gtasksSyncV2Provider.isActive()) { + gtasksSyncV2Provider.synchronizeActiveTasks(new RecordSyncStatusCallback(gtasksPreferenceService, broadcaster)); + } + } + + @Override + long intervalMillis() { + try { + return SECONDS.toMillis(preferences.getIntegerFromString(R.string.gtasks_GPr_interval_key, 0)); + } catch(Exception e) { + log.error(e.getMessage(), e); + preferences.setString(R.string.gtasks_GPr_interval_key, "0"); + return 0; + } + } + + @Override + String getLastRunPreference() { + return "gtasks_last_sync"; + } +} diff --git a/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java b/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java new file mode 100644 index 000000000..8fb6206da --- /dev/null +++ b/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java @@ -0,0 +1,65 @@ +package org.tasks.scheduling; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.tasks.injection.InjectingIntentService; +import org.tasks.preferences.Preferences; + +import javax.inject.Inject; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.tasks.date.DateTimeUtils.currentTimeMillis; +import static org.tasks.date.DateTimeUtils.newDateTime; + +public abstract class RecurringIntervalIntentService extends InjectingIntentService { + + private static final Logger log = LoggerFactory.getLogger(RecurringIntervalIntentService.class); + + private static final long PADDING = SECONDS.toMillis(1); + + @Inject Preferences preferences; + + public RecurringIntervalIntentService(String name) { + super(name); + } + + @Override + protected void onHandleIntent(Intent intent) { + super.onHandleIntent(intent); + + long interval = intervalMillis(); + + if (interval <= 0) { + log.debug("service disabled"); + return; + } + + long lastRun = preferences.getLong(getLastRunPreference(), 0); + long now = currentTimeMillis(); + long nextRun = lastRun + interval; + + if (nextRun < now + PADDING) { + nextRun = now + interval; + log.debug("running now [nextRun={}]", newDateTime(nextRun)); + preferences.setLong(getLastRunPreference(), now); + run(); + } else { + log.debug("will run at {} [lastRun={}]", newDateTime(nextRun), newDateTime(lastRun)); + } + + AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + PendingIntent pendingIntent = PendingIntent.getService(this, 0, new Intent(this, this.getClass()), PendingIntent.FLAG_UPDATE_CURRENT); + alarmManager.set(AlarmManager.RTC, nextRun, pendingIntent); + } + + abstract void run(); + + abstract long intervalMillis(); + + abstract String getLastRunPreference(); +}