mirror of https://github.com/tasks/tasks
Working on background services
* Backup intent service runs at midnight - closes #109 * Broadcast refresh at midnight - closes #100 * Task list listens for refreshes - see #189 * Reschedule everything on app upgradepull/253/head
parent
24a9ac5d9c
commit
972b19fae0
@ -1,188 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.backup;
|
|
||||||
|
|
||||||
import com.todoroo.andlib.utility.AndroidUtilities;
|
|
||||||
import com.todoroo.astrid.backup.BackupService.BackupDirectorySetting;
|
|
||||||
import com.todoroo.astrid.dao.TaskDao;
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import com.todoroo.astrid.test.DatabaseTestCase;
|
|
||||||
|
|
||||||
import org.tasks.R;
|
|
||||||
import org.tasks.preferences.Preferences;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import static org.tasks.date.DateTimeUtils.newDate;
|
|
||||||
|
|
||||||
public class BackupServiceTests extends DatabaseTestCase {
|
|
||||||
|
|
||||||
private static final long BACKUP_WAIT_TIME = 500L;
|
|
||||||
|
|
||||||
File temporaryDirectory = null;
|
|
||||||
|
|
||||||
@Inject TasksXmlExporter xmlExporter;
|
|
||||||
@Inject TaskDao taskDao;
|
|
||||||
@Inject Preferences preferences;
|
|
||||||
|
|
||||||
BackupDirectorySetting setting = new BackupDirectorySetting() {
|
|
||||||
public File getBackupDirectory() {
|
|
||||||
return temporaryDirectory;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() {
|
|
||||||
super.setUp();
|
|
||||||
|
|
||||||
try {
|
|
||||||
temporaryDirectory = File.createTempFile("backup", Long.toString(System.nanoTime()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(temporaryDirectory.delete()))
|
|
||||||
throw new RuntimeException("Could not delete temp file: " + temporaryDirectory.getAbsolutePath());
|
|
||||||
if (!(temporaryDirectory.mkdir()))
|
|
||||||
throw new RuntimeException("Could not create temp directory: " + temporaryDirectory.getAbsolutePath());
|
|
||||||
|
|
||||||
// make a temporary task
|
|
||||||
Task task = new Task();
|
|
||||||
task.setTitle("helicopter");
|
|
||||||
taskDao.createNew(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() {
|
|
||||||
super.tearDown();
|
|
||||||
|
|
||||||
if (temporaryDirectory != null) {
|
|
||||||
for (File file : temporaryDirectory.listFiles())
|
|
||||||
file.delete();
|
|
||||||
temporaryDirectory.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean getBackupSetting() {
|
|
||||||
return preferences.getBoolean(R.string.backup_BPr_auto_key, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setBackupSetting(boolean setting) {
|
|
||||||
preferences.setBoolean(R.string.backup_BPr_auto_key, setting);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disabled_testBackup() {
|
|
||||||
assertEquals(0, temporaryDirectory.list().length);
|
|
||||||
|
|
||||||
boolean backupSetting = getBackupSetting();
|
|
||||||
try {
|
|
||||||
setBackupSetting(true);
|
|
||||||
preferences.setLong(BackupPreferences.PREF_BACKUP_LAST_DATE, 0);
|
|
||||||
|
|
||||||
// create a backup
|
|
||||||
BackupService service = new BackupService();
|
|
||||||
service.setBackupDirectorySetting(setting);
|
|
||||||
service.testBackup(xmlExporter, preferences, getContext());
|
|
||||||
|
|
||||||
AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME);
|
|
||||||
|
|
||||||
// assert file created
|
|
||||||
File[] files = temporaryDirectory.listFiles();
|
|
||||||
assertEquals(1, files.length);
|
|
||||||
assertTrue(files[0].getName().matches(BackupService.BACKUP_FILE_NAME_REGEX));
|
|
||||||
|
|
||||||
// assert summary updated
|
|
||||||
assertTrue(preferences.getLong(BackupPreferences.PREF_BACKUP_LAST_DATE, 0) > 0);
|
|
||||||
assertNull(preferences.getStringValue(BackupPreferences.PREF_BACKUP_LAST_ERROR));
|
|
||||||
} finally {
|
|
||||||
setBackupSetting(backupSetting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disabled_testNoBackup() {
|
|
||||||
assertEquals(0, temporaryDirectory.list().length);
|
|
||||||
System.err.println("test no backup");
|
|
||||||
boolean backupSetting = getBackupSetting();
|
|
||||||
try {
|
|
||||||
setBackupSetting(false);
|
|
||||||
preferences.setLong(BackupPreferences.PREF_BACKUP_LAST_DATE, 0);
|
|
||||||
|
|
||||||
// create a backup
|
|
||||||
BackupService service = new BackupService();
|
|
||||||
service.setBackupDirectorySetting(new BackupDirectorySetting() {
|
|
||||||
public File getBackupDirectory() {
|
|
||||||
fail("Why was this method called?");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
service.testBackup(xmlExporter, preferences, getContext());
|
|
||||||
|
|
||||||
AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME);
|
|
||||||
|
|
||||||
// assert no file created
|
|
||||||
File[] files = temporaryDirectory.listFiles();
|
|
||||||
assertEquals(0, files.length);
|
|
||||||
|
|
||||||
// assert summary not updated
|
|
||||||
assertEquals(0, preferences.getLong(BackupPreferences.PREF_BACKUP_LAST_DATE, 0));
|
|
||||||
} finally {
|
|
||||||
setBackupSetting(backupSetting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDeletion() throws IOException {
|
|
||||||
// create a bunch of backups
|
|
||||||
assertEquals(0, temporaryDirectory.list().length);
|
|
||||||
|
|
||||||
boolean backupSetting = getBackupSetting();
|
|
||||||
try {
|
|
||||||
setBackupSetting(true);
|
|
||||||
|
|
||||||
// create some user files
|
|
||||||
File myFile = new File(temporaryDirectory, "beans");
|
|
||||||
myFile.createNewFile();
|
|
||||||
|
|
||||||
// create some backup files
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
DateFormat df = new SimpleDateFormat("MMdd-HHmm");
|
|
||||||
String name = String.format("auto.%02d%s.xml", i, df.format(newDate()));
|
|
||||||
File tempFile = new File(temporaryDirectory, name);
|
|
||||||
tempFile.createNewFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
// make one really old
|
|
||||||
File[] files = temporaryDirectory.listFiles();
|
|
||||||
files[4].setLastModified(System.currentTimeMillis() - 20000);
|
|
||||||
|
|
||||||
// assert files created
|
|
||||||
assertEquals(11, files.length);
|
|
||||||
|
|
||||||
// backup
|
|
||||||
BackupService service = new BackupService();
|
|
||||||
service.setBackupDirectorySetting(setting);
|
|
||||||
service.testBackup(xmlExporter, preferences, getContext());
|
|
||||||
|
|
||||||
AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME);
|
|
||||||
|
|
||||||
// assert the oldest file was deleted
|
|
||||||
assertTrue(temporaryDirectory.listFiles().length < 11);
|
|
||||||
assertFalse(files[4].exists());
|
|
||||||
|
|
||||||
// assert user file still exists
|
|
||||||
service.testBackup(xmlExporter, preferences, getContext());
|
|
||||||
assertTrue(myFile.exists());
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
setBackupSetting(backupSetting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,133 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2012 Todoroo Inc
|
||||||
|
*
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package org.tasks.scheduling;
|
||||||
|
|
||||||
|
import com.todoroo.andlib.utility.AndroidUtilities;
|
||||||
|
import com.todoroo.astrid.backup.BackupPreferences;
|
||||||
|
import com.todoroo.astrid.backup.TasksXmlExporter;
|
||||||
|
import com.todoroo.astrid.dao.TaskDao;
|
||||||
|
import com.todoroo.astrid.data.Task;
|
||||||
|
import com.todoroo.astrid.test.DatabaseTestCase;
|
||||||
|
|
||||||
|
import org.tasks.preferences.Preferences;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.tasks.date.DateTimeUtils.newDate;
|
||||||
|
|
||||||
|
public class BackupServiceTests extends DatabaseTestCase {
|
||||||
|
|
||||||
|
private static final long BACKUP_WAIT_TIME = 500L;
|
||||||
|
|
||||||
|
File temporaryDirectory = null;
|
||||||
|
|
||||||
|
@Inject TasksXmlExporter xmlExporter;
|
||||||
|
@Inject TaskDao taskDao;
|
||||||
|
@Inject Preferences preferences;
|
||||||
|
|
||||||
|
BackupIntentService.BackupDirectorySetting setting = new BackupIntentService.BackupDirectorySetting() {
|
||||||
|
public File getBackupDirectory() {
|
||||||
|
return temporaryDirectory;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
try {
|
||||||
|
temporaryDirectory = File.createTempFile("backup", Long.toString(System.nanoTime()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(temporaryDirectory.delete()))
|
||||||
|
throw new RuntimeException("Could not delete temp file: " + temporaryDirectory.getAbsolutePath());
|
||||||
|
if (!(temporaryDirectory.mkdir()))
|
||||||
|
throw new RuntimeException("Could not create temp directory: " + temporaryDirectory.getAbsolutePath());
|
||||||
|
|
||||||
|
// make a temporary task
|
||||||
|
Task task = new Task();
|
||||||
|
task.setTitle("helicopter");
|
||||||
|
taskDao.createNew(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() {
|
||||||
|
super.tearDown();
|
||||||
|
|
||||||
|
if (temporaryDirectory != null) {
|
||||||
|
for (File file : temporaryDirectory.listFiles())
|
||||||
|
file.delete();
|
||||||
|
temporaryDirectory.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disabled_testBackup() {
|
||||||
|
assertEquals(0, temporaryDirectory.list().length);
|
||||||
|
|
||||||
|
preferences.setLong(BackupPreferences.PREF_BACKUP_LAST_DATE, 0);
|
||||||
|
|
||||||
|
// create a backup
|
||||||
|
BackupIntentService service = new BackupIntentService();
|
||||||
|
service.setBackupDirectorySetting(setting);
|
||||||
|
service.testBackup(xmlExporter, preferences, getContext());
|
||||||
|
|
||||||
|
AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME);
|
||||||
|
|
||||||
|
// assert file created
|
||||||
|
File[] files = temporaryDirectory.listFiles();
|
||||||
|
assertEquals(1, files.length);
|
||||||
|
assertTrue(files[0].getName().matches(BackupIntentService.BACKUP_FILE_NAME_REGEX));
|
||||||
|
|
||||||
|
// assert summary updated
|
||||||
|
assertTrue(preferences.getLong(BackupPreferences.PREF_BACKUP_LAST_DATE, 0) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeletion() throws IOException {
|
||||||
|
// create a bunch of backups
|
||||||
|
assertEquals(0, temporaryDirectory.list().length);
|
||||||
|
|
||||||
|
// create some user files
|
||||||
|
File myFile = new File(temporaryDirectory, "beans");
|
||||||
|
myFile.createNewFile();
|
||||||
|
|
||||||
|
// create some backup files
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
DateFormat df = new SimpleDateFormat("MMdd-HHmm");
|
||||||
|
String name = String.format("auto.%02d%s.xml", i, df.format(newDate()));
|
||||||
|
File tempFile = new File(temporaryDirectory, name);
|
||||||
|
tempFile.createNewFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
// make one really old
|
||||||
|
File[] files = temporaryDirectory.listFiles();
|
||||||
|
files[4].setLastModified(System.currentTimeMillis() - 20000);
|
||||||
|
|
||||||
|
// assert files created
|
||||||
|
assertEquals(11, files.length);
|
||||||
|
|
||||||
|
// backup
|
||||||
|
BackupIntentService service = new BackupIntentService();
|
||||||
|
service.setBackupDirectorySetting(setting);
|
||||||
|
service.testBackup(xmlExporter, preferences, getContext());
|
||||||
|
|
||||||
|
AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME);
|
||||||
|
|
||||||
|
// assert the oldest file was deleted
|
||||||
|
assertTrue(temporaryDirectory.listFiles().length < 11);
|
||||||
|
assertFalse(files[4].exists());
|
||||||
|
|
||||||
|
// assert user file still exists
|
||||||
|
service.testBackup(xmlExporter, preferences, getContext());
|
||||||
|
assertTrue(myFile.exists());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,30 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.backup;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
import com.todoroo.andlib.service.ContextManager;
|
|
||||||
|
|
||||||
import org.tasks.injection.InjectingBroadcastReceiver;
|
|
||||||
import org.tasks.preferences.Preferences;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public class BackupStartupReceiver extends InjectingBroadcastReceiver {
|
|
||||||
|
|
||||||
@Inject Preferences preferences;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
/** Called when device is restarted */
|
|
||||||
public void onReceive(final Context context, Intent intent) {
|
|
||||||
super.onReceive(context, intent);
|
|
||||||
|
|
||||||
ContextManager.setContext(context);
|
|
||||||
BackupService.scheduleService(preferences, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.reminders;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.IBinder;
|
|
||||||
|
|
||||||
import com.todoroo.andlib.service.ContextManager;
|
|
||||||
import com.todoroo.andlib.utility.AndroidUtilities;
|
|
||||||
import com.todoroo.astrid.alarms.AlarmService;
|
|
||||||
import com.todoroo.astrid.dao.TaskDao;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.tasks.injection.InjectingService;
|
|
||||||
import org.tasks.scheduling.RefreshScheduler;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules reminders in the background to prevent ANR's
|
|
||||||
*
|
|
||||||
* @author Tim Su
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ReminderSchedulingService extends InjectingService {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ReminderSchedulingService.class);
|
|
||||||
|
|
||||||
@Inject RefreshScheduler refreshScheduler;
|
|
||||||
@Inject AlarmService alarmService;
|
|
||||||
@Inject ReminderService reminderService;
|
|
||||||
@Inject TaskDao taskDao;
|
|
||||||
|
|
||||||
/** Receive the alarm - start the synchronize service! */
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
ContextManager.setContext(ReminderSchedulingService.this);
|
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
delaySchedulingToPreventANRs();
|
|
||||||
scheduleReminders();
|
|
||||||
stopSelf();
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
return START_NOT_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleReminders() {
|
|
||||||
try {
|
|
||||||
reminderService.scheduleAllAlarms(taskDao);
|
|
||||||
alarmService.scheduleAllAlarms();
|
|
||||||
refreshScheduler.scheduleAllAlarms();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void delaySchedulingToPreventANRs() {
|
|
||||||
AndroidUtilities.sleepDeep(5000L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.reminders;
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
import com.todoroo.andlib.service.ContextManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service which handles jobs that need to be run when phone boots
|
|
||||||
*
|
|
||||||
* @author Tim Su <tim@todoroo.com>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ReminderStartupReceiver extends BroadcastReceiver {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
/** Called when the system is started up */
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
ContextManager.setContext(context);
|
|
||||||
startReminderSchedulingService(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startReminderSchedulingService(Context context) {
|
|
||||||
context.startService(new Intent(context, ReminderSchedulingService.class));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package org.tasks.injection;
|
||||||
|
|
||||||
|
import android.app.IntentService;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
public class InjectingIntentService extends IntentService {
|
||||||
|
|
||||||
|
public InjectingIntentService(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHandleIntent(Intent intent) {
|
||||||
|
((Injector) getApplication())
|
||||||
|
.getObjectGraph()
|
||||||
|
.plus(new IntentServiceModule())
|
||||||
|
.inject(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package org.tasks.injection;
|
||||||
|
|
||||||
|
import org.tasks.scheduling.*;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
|
||||||
|
@Module(addsTo = TasksModule.class,
|
||||||
|
injects = {
|
||||||
|
AlarmSchedulingIntentService.class,
|
||||||
|
BackupIntentService.class,
|
||||||
|
MidnightRefreshService.class,
|
||||||
|
RefreshSchedulerIntentService.class,
|
||||||
|
ReminderSchedulerIntentService.class
|
||||||
|
})
|
||||||
|
public class IntentServiceModule {
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package org.tasks.receivers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.tasks.injection.InjectingBroadcastReceiver;
|
||||||
|
import org.tasks.scheduling.BackgroundScheduler;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class BootCompletedReceiver extends InjectingBroadcastReceiver {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BootCompletedReceiver.class);
|
||||||
|
|
||||||
|
@Inject BackgroundScheduler backgroundScheduler;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
super.onReceive(context, intent);
|
||||||
|
|
||||||
|
log.debug("onReceive(context, {})", intent);
|
||||||
|
|
||||||
|
backgroundScheduler.scheduleEverything();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package org.tasks.receivers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.tasks.injection.InjectingBroadcastReceiver;
|
||||||
|
import org.tasks.scheduling.BackgroundScheduler;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class FirstLaunchReceiver extends InjectingBroadcastReceiver {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(FirstLaunchReceiver.class);
|
||||||
|
|
||||||
|
@Inject BackgroundScheduler backgroundScheduler;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
super.onReceive(context, intent);
|
||||||
|
|
||||||
|
log.debug("onReceive(context, {})", intent);
|
||||||
|
|
||||||
|
backgroundScheduler.scheduleBackupService();
|
||||||
|
backgroundScheduler.scheduleMidnightRefresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package org.tasks.receivers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.tasks.injection.InjectingBroadcastReceiver;
|
||||||
|
import org.tasks.scheduling.BackgroundScheduler;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class MyPackageReplacedReceiver extends InjectingBroadcastReceiver {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(MyPackageReplacedReceiver.class);
|
||||||
|
|
||||||
|
@Inject BackgroundScheduler backgroundScheduler;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
super.onReceive(context, intent);
|
||||||
|
|
||||||
|
log.debug("onReceive(context, {})", intent);
|
||||||
|
|
||||||
|
backgroundScheduler.scheduleEverything();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package org.tasks.receivers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.tasks.injection.InjectingBroadcastReceiver;
|
||||||
|
import org.tasks.scheduling.BackgroundScheduler;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class PackageReplacedReceiver extends InjectingBroadcastReceiver {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PackageReplacedReceiver.class);
|
||||||
|
|
||||||
|
@Inject BackgroundScheduler backgroundScheduler;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
super.onReceive(context, intent);
|
||||||
|
|
||||||
|
if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED) && context.getPackageName().equals(intent.getData().getSchemeSpecificPart())) {
|
||||||
|
log.debug("onReceive(context, {})", intent);
|
||||||
|
backgroundScheduler.scheduleEverything();
|
||||||
|
} else {
|
||||||
|
log.debug("ignoring {}", intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package org.tasks.scheduling;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import com.todoroo.astrid.alarms.AlarmService;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.tasks.injection.InjectingIntentService;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class AlarmSchedulingIntentService extends InjectingIntentService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AlarmSchedulingIntentService.class);
|
||||||
|
|
||||||
|
@Inject AlarmService alarmService;
|
||||||
|
|
||||||
|
public AlarmSchedulingIntentService() {
|
||||||
|
super(AlarmSchedulingIntentService.class.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHandleIntent(Intent intent) {
|
||||||
|
super.onHandleIntent(intent);
|
||||||
|
|
||||||
|
log.debug("onHandleIntent({})", intent);
|
||||||
|
|
||||||
|
alarmService.scheduleAllAlarms();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package org.tasks.scheduling;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import org.tasks.injection.ForApplication;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class BackgroundScheduler {
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public BackgroundScheduler(@ForApplication Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleEverything() {
|
||||||
|
context.startService(new Intent(context, RefreshSchedulerIntentService.class));
|
||||||
|
context.startService(new Intent(context, AlarmSchedulingIntentService.class));
|
||||||
|
context.startService(new Intent(context, ReminderSchedulerIntentService.class));
|
||||||
|
scheduleBackupService();
|
||||||
|
scheduleMidnightRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleBackupService() {
|
||||||
|
context.startService(new Intent(context, BackupIntentService.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleMidnightRefresh() {
|
||||||
|
context.startService(new Intent(context, MidnightRefreshService.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
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 MidnightIntentService extends InjectingIntentService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(MidnightIntentService.class);
|
||||||
|
|
||||||
|
private static final long PADDING = SECONDS.toMillis(1);
|
||||||
|
|
||||||
|
@Inject Preferences preferences;
|
||||||
|
|
||||||
|
public MidnightIntentService(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHandleIntent(Intent intent) {
|
||||||
|
super.onHandleIntent(intent);
|
||||||
|
|
||||||
|
long lastRun = preferences.getLong(getLastRunPreference(), 0);
|
||||||
|
long nextRun = nextMidnight(lastRun);
|
||||||
|
long now = currentTimeMillis();
|
||||||
|
|
||||||
|
if (nextRun <= now) {
|
||||||
|
nextRun = nextMidnight(now);
|
||||||
|
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 + PADDING, pendingIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long nextMidnight(long timestamp) {
|
||||||
|
return newDateTime(timestamp).withMillisOfDay(0).plusDays(1).getMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void run();
|
||||||
|
|
||||||
|
abstract String getLastRunPreference();
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package org.tasks.scheduling;
|
||||||
|
|
||||||
|
import org.tasks.Broadcaster;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class MidnightRefreshService extends MidnightIntentService {
|
||||||
|
|
||||||
|
@Inject Broadcaster broadcaster;
|
||||||
|
|
||||||
|
public MidnightRefreshService() {
|
||||||
|
super(MidnightRefreshService.class.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void run() {
|
||||||
|
broadcaster.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getLastRunPreference() {
|
||||||
|
return "midnightRefreshDate";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package org.tasks.scheduling;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.tasks.injection.InjectingIntentService;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class RefreshSchedulerIntentService extends InjectingIntentService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(RefreshSchedulerIntentService.class);
|
||||||
|
|
||||||
|
@Inject RefreshScheduler refreshScheduler;
|
||||||
|
|
||||||
|
public RefreshSchedulerIntentService() {
|
||||||
|
super(RefreshSchedulerIntentService.class.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHandleIntent(Intent intent) {
|
||||||
|
super.onHandleIntent(intent);
|
||||||
|
|
||||||
|
log.debug("onHandleIntent({})", intent);
|
||||||
|
|
||||||
|
refreshScheduler.scheduleApplicationRefreshes();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package org.tasks.scheduling;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import com.todoroo.astrid.dao.TaskDao;
|
||||||
|
import com.todoroo.astrid.reminders.ReminderService;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.tasks.injection.InjectingIntentService;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class ReminderSchedulerIntentService extends InjectingIntentService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ReminderSchedulerIntentService.class);
|
||||||
|
|
||||||
|
@Inject ReminderService reminderService;
|
||||||
|
@Inject TaskDao taskDao;
|
||||||
|
|
||||||
|
public ReminderSchedulerIntentService() {
|
||||||
|
super(ReminderSchedulerIntentService.class.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHandleIntent(Intent intent) {
|
||||||
|
super.onHandleIntent(intent);
|
||||||
|
|
||||||
|
log.debug("onHandleIntent({})", intent);
|
||||||
|
|
||||||
|
reminderService.scheduleAllAlarms(taskDao);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<bool name="at_most_honeycomb">false</bool>
|
||||||
|
<bool name="at_least_honeycomb_mr1">true</bool>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<bool name="at_most_honeycomb">true</bool>
|
||||||
|
<bool name="at_least_honeycomb_mr1">false</bool>
|
||||||
|
</resources>
|
||||||
Loading…
Reference in New Issue