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 upgrade
pull/253/head
Alex Baker 11 years ago
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);
}
}
}

@ -2,7 +2,7 @@ package org.tasks.injection;
import android.content.Context; import android.content.Context;
import com.todoroo.astrid.backup.BackupServiceTests; import org.tasks.scheduling.BackupServiceTests;
import com.todoroo.astrid.dao.Database; import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.MetadataDaoTests; import com.todoroo.astrid.dao.MetadataDaoTests;
import com.todoroo.astrid.dao.TaskDaoTests; import com.todoroo.astrid.dao.TaskDaoTests;

@ -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());
}
}

@ -176,7 +176,7 @@
<receiver android:name="com.todoroo.astrid.reminders.Notifications" /> <receiver android:name="com.todoroo.astrid.reminders.Notifications" />
<receiver android:name="org.tasks.scheduling.RefreshBroadcastReceiver" /> <receiver android:name=".receivers.RefreshReceiver" />
<receiver android:name="com.todoroo.astrid.reminders.ShowNotificationReceiver"> <receiver android:name="com.todoroo.astrid.reminders.ShowNotificationReceiver">
<intent-filter> <intent-filter>
@ -411,7 +411,6 @@
</activity> </activity>
<!-- backup --> <!-- backup -->
<service android:name="com.todoroo.astrid.backup.BackupService" />
<activity <activity
android:name="com.todoroo.astrid.backup.BackupPreferences" android:name="com.todoroo.astrid.backup.BackupPreferences"
@ -426,13 +425,6 @@
</intent-filter> </intent-filter>
</activity> </activity>
<receiver android:name="com.todoroo.astrid.backup.BackupStartupReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- premium --> <!-- premium -->
<activity <activity
android:name="com.todoroo.astrid.files.AACRecordingActivity" android:name="com.todoroo.astrid.files.AACRecordingActivity"
@ -463,13 +455,6 @@
</intent-filter> </intent-filter>
</activity> </activity>
<receiver android:name="com.todoroo.astrid.reminders.ReminderStartupReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity <activity
android:name=".voice.VoiceCommandActivity" android:name=".voice.VoiceCommandActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"> android:theme="@android:style/Theme.Translucent.NoTitleBar">
@ -481,7 +466,47 @@
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name="com.todoroo.astrid.reminders.ReminderSchedulingService" /> <receiver android:name=".receivers.BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.FirstLaunchReceiver"/>
<receiver
android:name=".receivers.PackageReplacedReceiver"
android:enabled="@bool/at_most_honeycomb">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<receiver
android:name=".receivers.MyPackageReplacedReceiver"
android:enabled="@bool/at_least_honeycomb_mr1">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
<service
android:name=".scheduling.AlarmSchedulingIntentService"
android:exported="false" />
<service
android:name=".scheduling.ReminderSchedulerIntentService"
android:exported="false" />
<service
android:name=".scheduling.RefreshSchedulerIntentService"
android:exported="false" />
<service
android:name=".scheduling.BackupIntentService"
android:exported="false" />
<service
android:name=".scheduling.MidnightRefreshService"
android:exported="false" />
<!-- Uses Library --> <!-- Uses Library -->
<uses-library <uses-library

@ -1,4 +1,4 @@
<configuration debug='true'> <configuration debug='false'>
<appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender"> <appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender">
<encoder> <encoder>
<pattern>[%thread] %-5level - %msg%n</pattern> <pattern>[%thread] %-5level - %msg%n</pattern>

@ -7,7 +7,10 @@ package com.todoroo.astrid.activity;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.view.MenuItemCompat; import android.support.v4.view.MenuItemCompat;
@ -72,6 +75,13 @@ public class TaskListActivity extends AstridActivity implements OnPageChangeList
public static final String OPEN_TASK = "openTask"; //$NON-NLS-1$ public static final String OPEN_TASK = "openTask"; //$NON-NLS-1$
private final BroadcastReceiver refreshReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
refreshTaskList();
}
};
/** /**
* @see android.app.Activity#onCreate(Bundle) * @see android.app.Activity#onCreate(Bundle)
*/ */
@ -129,9 +139,18 @@ public class TaskListActivity extends AstridActivity implements OnPageChangeList
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
registerReceiver(refreshReceiver, new IntentFilter(AstridApiConstants.BROADCAST_EVENT_REFRESH));
getTaskListFragment().setSyncOngoing(gtasksPreferenceService.isOngoing()); getTaskListFragment().setSyncOngoing(gtasksPreferenceService.isOngoing());
} }
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(refreshReceiver);
}
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
if (isDrawerOpen()) { if (isDrawerOpen()) {

@ -490,8 +490,7 @@ public class TaskListFragment extends InjectingListFragment implements OnSortSel
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
getActivity().registerReceiver(refreshReceiver, getActivity().registerReceiver(refreshReceiver, new IntentFilter(AstridApiConstants.BROADCAST_EVENT_REFRESH));
new IntentFilter(AstridApiConstants.BROADCAST_EVENT_REFRESH));
if (Flags.checkAndClear(Flags.REFRESH)) { if (Flags.checkAndClear(Flags.REFRESH)) {
refresh(); refresh();
@ -565,8 +564,7 @@ public class TaskListFragment extends InjectingListFragment implements OnSortSel
protected class RefreshReceiver extends BroadcastReceiver { protected class RefreshReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (intent == null if (intent == null || !AstridApiConstants.BROADCAST_EVENT_REFRESH.equals(intent.getAction())) {
|| !AstridApiConstants.BROADCAST_EVENT_REFRESH.equals(intent.getAction())) {
return; return;
} }

@ -258,7 +258,7 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
* Call this method from your activity's onResume() method * Call this method from your activity's onResume() method
*/ */
public void registerRecevier() { public void registerRecevier() {
activity.registerReceiver(filterListUpdateReceiver, new IntentFilter(AstridApiConstants.BROADCAST_EVENT_FILTER_LIST_UPDATED)); activity.registerReceiver(filterListUpdateReceiver, new IntentFilter(AstridApiConstants.BROADCAST_EVENT_REFRESH));
getLists(); getLists();
refreshFilterCount(); refreshFilterCount();

@ -99,15 +99,6 @@ public class AstridApiConstants {
*/ */
public static final String BROADCAST_EVENT_REFRESH = API_PACKAGE + ".REFRESH"; public static final String BROADCAST_EVENT_REFRESH = API_PACKAGE + ".REFRESH";
/**
* Action name for broadcast intent notifying that task was created or
* title was changed
* <li> EXTRAS_TASK_ID id of the task
*/
public static final String BROADCAST_EVENT_TASK_LIST_UPDATED = API_PACKAGE + ".TASK_LIST_UPDATED";
public static final String BROADCAST_EVENT_FILTER_LIST_UPDATED = API_PACKAGE + ".FILTER_LIST_UPDATED";
/** /**
* Action name for broadcast intent notifying that task was completed * Action name for broadcast intent notifying that task was completed
* <li> EXTRAS_TASK_ID id of the task * <li> EXTRAS_TASK_ID id of the task

@ -34,9 +34,9 @@ import static org.tasks.date.DateTimeUtils.newDate;
*/ */
public class BackupPreferences extends TodorooPreferenceActivity { public class BackupPreferences extends TodorooPreferenceActivity {
static final String PREF_BACKUP_LAST_DATE = "backupDate"; //$NON-NLS-1$ public static final String PREF_BACKUP_LAST_DATE = "backupDate"; //$NON-NLS-1$
static final String PREF_BACKUP_LAST_ERROR = "backupError"; //$NON-NLS-1$ public static final String PREF_BACKUP_LAST_ERROR = "backupError"; //$NON-NLS-1$
private int statusColor = Color.BLACK; private int statusColor = Color.BLACK;
@ -85,28 +85,11 @@ public class BackupPreferences extends TodorooPreferenceActivity {
}); });
} }
@Override
protected void onPause() {
super.onPause();
BackupService.scheduleService(preferences, this);
}
@Override @Override
public void updatePreferences(Preference preference, Object value) { public void updatePreferences(Preference preference, Object value) {
final Resources r = getResources(); final Resources r = getResources();
// auto if (r.getString(R.string.backup_BPr_status_key).equals(preference.getKey())) {
if (r.getString(R.string.backup_BPr_auto_key).equals(
preference.getKey())) {
if (value != null && !(Boolean)value) {
preference.setSummary(R.string.backup_BPr_auto_disabled);
} else {
preference.setSummary(R.string.backup_BPr_auto_enabled);
}
}
// status
else if (r.getString(R.string.backup_BPr_status_key).equals(preference.getKey())) {
String status; String status;
String subtitle = ""; //$NON-NLS-1$ String subtitle = ""; //$NON-NLS-1$

@ -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);
}
}

@ -74,8 +74,14 @@ public class TasksXmlExporter {
private File backupDirectory; private File backupDirectory;
private String latestSetVersionName; private String latestSetVersionName;
private void post(Runnable runnable) {
if (handler != null) {
handler.post(runnable);
}
}
private void setProgress(final int taskNumber, final int total) { private void setProgress(final int taskNumber, final int total) {
handler.post(new Runnable() { post(new Runnable() {
@Override @Override
public void run() { public void run() {
progressDialog.setMax(total); progressDialog.setMax(total);
@ -99,7 +105,7 @@ public class TasksXmlExporter {
BackupConstants.defaultExportDirectory() : backupDirectoryOverride; BackupConstants.defaultExportDirectory() : backupDirectoryOverride;
this.latestSetVersionName = null; this.latestSetVersionName = null;
handler = new Handler(); handler = exportType == ExportType.EXPORT_TYPE_MANUAL ? new Handler() : null;
progressDialog = new ProgressDialog(context); progressDialog = new ProgressDialog(context);
if(exportType == ExportType.EXPORT_TYPE_MANUAL) { if(exportType == ExportType.EXPORT_TYPE_MANUAL) {
progressDialog.setIcon(android.R.drawable.ic_dialog_info); progressDialog.setIcon(android.R.drawable.ic_dialog_info);
@ -135,7 +141,7 @@ public class TasksXmlExporter {
} catch (IOException e) { } catch (IOException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} finally { } finally {
handler.post(new Runnable() { post(new Runnable() {
@Override @Override
public void run() { public void run() {
if(progressDialog.isShowing() && context instanceof Activity) { if(progressDialog.isShowing() && context instanceof Activity) {
@ -291,7 +297,7 @@ public class TasksXmlExporter {
xml.attribute(null, property.name, value); xml.attribute(null, property.name, value);
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
// didn't read this value, do nothing // didn't read this value, do nothing
log.debug(e.getMessage(), e); log.trace(e.getMessage(), e);
} catch (IllegalArgumentException | IOException | IllegalStateException e) { } catch (IllegalArgumentException | IOException | IllegalStateException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -300,7 +306,7 @@ public class TasksXmlExporter {
} }
private void onFinishExport(final String outputFile) { private void onFinishExport(final String outputFile) {
handler.post(new Runnable() { post(new Runnable() {
@Override @Override
public void run() { public void run() {
if(exportCount == 0) { if(exportCount == 0) {

@ -358,7 +358,7 @@ public class TaskDao extends RemoteModelDao<Task> {
* Send broadcast when task list changes. Widgets should update. * Send broadcast when task list changes. Widgets should update.
*/ */
private void broadcastTaskChanged() { private void broadcastTaskChanged() {
broadcaster.taskListUpdated(); broadcaster.refresh();
} }
/** /**

@ -45,9 +45,7 @@ public class SyncActionHelper {
syncResultCallback = new IndeterminateProgressBarSyncResultCallback(gtasksPreferenceService, activity, new Runnable() { syncResultCallback = new IndeterminateProgressBarSyncResultCallback(gtasksPreferenceService, activity, new Runnable() {
@Override @Override
public void run() { public void run() {
activity.sendBroadcast( activity.sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH));
new Intent(
AstridApiConstants.BROADCAST_EVENT_REFRESH));
} }
}); });
} }

@ -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));
}
}

@ -27,7 +27,6 @@ import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DialogUtilities; import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.backup.BackupConstants; import com.todoroo.astrid.backup.BackupConstants;
import com.todoroo.astrid.backup.BackupService;
import com.todoroo.astrid.backup.TasksXmlImporter; import com.todoroo.astrid.backup.TasksXmlImporter;
import com.todoroo.astrid.dao.Database; import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.MetadataDao; import com.todoroo.astrid.dao.MetadataDao;
@ -41,12 +40,12 @@ import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService; import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import com.todoroo.astrid.provider.Astrid2TaskProvider; import com.todoroo.astrid.provider.Astrid2TaskProvider;
import com.todoroo.astrid.provider.Astrid3ContentProvider; import com.todoroo.astrid.provider.Astrid3ContentProvider;
import com.todoroo.astrid.reminders.ReminderStartupReceiver;
import com.todoroo.astrid.tags.TaskToTagMetadata; import com.todoroo.astrid.tags.TaskToTagMetadata;
import com.todoroo.astrid.utility.Constants; import com.todoroo.astrid.utility.Constants;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.tasks.Broadcaster;
import org.tasks.R; import org.tasks.R;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
@ -80,6 +79,7 @@ public class StartupService {
private final TasksXmlImporter xmlImporter; private final TasksXmlImporter xmlImporter;
private final CalendarAlarmScheduler calendarAlarmScheduler; private final CalendarAlarmScheduler calendarAlarmScheduler;
private final TaskDeleter taskDeleter; private final TaskDeleter taskDeleter;
private Broadcaster broadcaster;
@Inject @Inject
public StartupService(UpgradeService upgradeService, TaskService taskService, public StartupService(UpgradeService upgradeService, TaskService taskService,
@ -87,7 +87,8 @@ public class StartupService {
GtasksPreferenceService gtasksPreferenceService, GtasksPreferenceService gtasksPreferenceService,
GtasksSyncService gtasksSyncService, MetadataDao metadataDao, GtasksSyncService gtasksSyncService, MetadataDao metadataDao,
Preferences preferences, TasksXmlImporter xmlImporter, Preferences preferences, TasksXmlImporter xmlImporter,
CalendarAlarmScheduler calendarAlarmScheduler, TaskDeleter taskDeleter) { CalendarAlarmScheduler calendarAlarmScheduler, TaskDeleter taskDeleter,
Broadcaster broadcaster) {
this.upgradeService = upgradeService; this.upgradeService = upgradeService;
this.taskService = taskService; this.taskService = taskService;
this.tagDataDao = tagDataDao; this.tagDataDao = tagDataDao;
@ -99,6 +100,7 @@ public class StartupService {
this.xmlImporter = xmlImporter; this.xmlImporter = xmlImporter;
this.calendarAlarmScheduler = calendarAlarmScheduler; this.calendarAlarmScheduler = calendarAlarmScheduler;
this.taskDeleter = taskDeleter; this.taskDeleter = taskDeleter;
this.broadcaster = broadcaster;
} }
/** /**
@ -186,10 +188,6 @@ public class StartupService {
// if sync ongoing flag was set, clear it // if sync ongoing flag was set, clear it
gtasksPreferenceService.stopOngoing(); gtasksPreferenceService.stopOngoing();
// perform initialization
ReminderStartupReceiver.startReminderSchedulingService(activity);
BackupService.scheduleService(preferences, activity);
gtasksSyncService.initialize(); gtasksSyncService.initialize();
// get and display update messages // get and display update messages
@ -201,6 +199,10 @@ public class StartupService {
preferences.setDefaults(); preferences.setDefaults();
if (latestSetVersion == 0) {
broadcaster.firstLaunch();
}
calendarAlarmScheduler.scheduleCalendarAlarms(activity, false); // This needs to be after set preference defaults for the purposes of ab testing calendarAlarmScheduler.scheduleCalendarAlarms(activity, false); // This needs to be after set preference defaults for the purposes of ab testing
showTaskKillerHelp(activity); showTaskKillerHelp(activity);

@ -229,7 +229,7 @@ public class TaskService {
filterCounter.refreshFilterCounts(new Runnable() { filterCounter.refreshFilterCounts(new Runnable() {
@Override @Override
public void run() { public void run() {
broadcaster.filterListUpdated(); broadcaster.refresh();
} }
}); });
} }

@ -30,7 +30,7 @@ import org.tasks.widget.WidgetHelper;
import javax.inject.Inject; import javax.inject.Inject;
import static com.todoroo.andlib.utility.AndroidUtilities.preIceCreamSandwich; import static com.todoroo.andlib.utility.AndroidUtilities.preIceCreamSandwich;
import static com.todoroo.astrid.api.AstridApiConstants.BROADCAST_EVENT_TASK_LIST_UPDATED; import static com.todoroo.astrid.api.AstridApiConstants.BROADCAST_EVENT_REFRESH;
public class TasksWidget extends InjectingAppWidgetProvider { public class TasksWidget extends InjectingAppWidgetProvider {
@ -65,7 +65,7 @@ public class TasksWidget extends InjectingAppWidgetProvider {
context.startActivity(intent); context.startActivity(intent);
break; break;
case BROADCAST_EVENT_TASK_LIST_UPDATED: case BROADCAST_EVENT_REFRESH:
updateWidgets(context); updateWidgets(context);
break; break;
} }

@ -9,6 +9,7 @@ import com.todoroo.astrid.reminders.Notifications;
import com.todoroo.astrid.utility.Constants; import com.todoroo.astrid.utility.Constants;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.receivers.FirstLaunchReceiver;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -44,15 +45,7 @@ public class Broadcaster {
}}); }});
} }
public void taskListUpdated() { public void refresh() {
sendOrderedBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_LIST_UPDATED));
}
public void filterListUpdated() {
sendOrderedBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_FILTER_LIST_UPDATED));
}
public void eventRefresh() {
context.sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH)); context.sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH));
} }
@ -63,4 +56,8 @@ public class Broadcaster {
void sendOrderedBroadcast(Intent intent, String permissions) { void sendOrderedBroadcast(Intent intent, String permissions) {
context.sendOrderedBroadcast(intent, permissions); context.sendOrderedBroadcast(intent, permissions);
} }
public void firstLaunch() {
context.sendBroadcast(new Intent(context, FirstLaunchReceiver.class));
}
} }

@ -1,5 +1,7 @@
package org.tasks.date; package org.tasks.date;
import org.joda.time.DateTime;
import java.util.Date; import java.util.Date;
public class DateTimeUtils { public class DateTimeUtils {
@ -24,4 +26,7 @@ public class DateTimeUtils {
return newDate(Date.UTC(year - 1900, month - 1, day, hour, minute, second)); return newDate(Date.UTC(year - 1900, month - 1, day, hour, minute, second));
} }
public static DateTime newDateTime(long timestamp) {
return new DateTime(timestamp);
}
} }

@ -1,7 +1,6 @@
package org.tasks.injection; package org.tasks.injection;
import com.todoroo.astrid.alarms.AlarmTaskRepeatListener; import com.todoroo.astrid.alarms.AlarmTaskRepeatListener;
import com.todoroo.astrid.backup.BackupStartupReceiver;
import com.todoroo.astrid.calls.PhoneStateChangedReceiver; import com.todoroo.astrid.calls.PhoneStateChangedReceiver;
import com.todoroo.astrid.core.CoreFilterExposer; import com.todoroo.astrid.core.CoreFilterExposer;
import com.todoroo.astrid.core.CustomFilterExposer; import com.todoroo.astrid.core.CustomFilterExposer;
@ -20,32 +19,39 @@ import com.todoroo.astrid.timers.TimerFilterExposer;
import com.todoroo.astrid.timers.TimerTaskCompleteListener; import com.todoroo.astrid.timers.TimerTaskCompleteListener;
import com.todoroo.astrid.widget.TasksWidget; import com.todoroo.astrid.widget.TasksWidget;
import org.tasks.scheduling.RefreshBroadcastReceiver; import org.tasks.receivers.BootCompletedReceiver;
import org.tasks.receivers.FirstLaunchReceiver;
import org.tasks.receivers.MyPackageReplacedReceiver;
import org.tasks.receivers.PackageReplacedReceiver;
import org.tasks.receivers.RefreshReceiver;
import dagger.Module; import dagger.Module;
@Module(addsTo = TasksModule.class, @Module(addsTo = TasksModule.class,
injects = { injects = {
RefreshBroadcastReceiver.class, TasksWidget.class,
TasksWidget.class, Notifications.class,
Notifications.class, GtasksCustomFilterCriteriaExposer.class,
GtasksCustomFilterCriteriaExposer.class, TagCustomFilterCriteriaExposer.class,
TagCustomFilterCriteriaExposer.class, GCalTaskCompleteListener.class,
GCalTaskCompleteListener.class, TimerTaskCompleteListener.class,
TimerTaskCompleteListener.class, RepeatTaskCompleteListener.class,
RepeatTaskCompleteListener.class, AlarmTaskRepeatListener.class,
AlarmTaskRepeatListener.class, GtasksStartupReceiver.class,
GtasksStartupReceiver.class, PhoneStateChangedReceiver.class,
PhoneStateChangedReceiver.class, ShowNotificationReceiver.class,
ShowNotificationReceiver.class, CoreFilterExposer.class,
CoreFilterExposer.class, TimerFilterExposer.class,
TimerFilterExposer.class, CustomFilterExposer.class,
CustomFilterExposer.class, GtasksFilterExposer.class,
GtasksFilterExposer.class, TagFilterExposer.class,
TagFilterExposer.class, CalendarAlarmReceiver.class,
BackupStartupReceiver.class, CalendarStartupReceiver.class,
CalendarAlarmReceiver.class, BootCompletedReceiver.class,
CalendarStartupReceiver.class FirstLaunchReceiver.class,
}) MyPackageReplacedReceiver.class,
PackageReplacedReceiver.class,
RefreshReceiver.class
})
public class BroadcastModule { public class BroadcastModule {
} }

@ -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 {
}

@ -1,8 +1,6 @@
package org.tasks.injection; package org.tasks.injection;
import com.todoroo.astrid.backup.BackupService;
import com.todoroo.astrid.gtasks.GtasksBackgroundService; import com.todoroo.astrid.gtasks.GtasksBackgroundService;
import com.todoroo.astrid.reminders.ReminderSchedulingService;
import com.todoroo.astrid.widget.WidgetUpdateService; import com.todoroo.astrid.widget.WidgetUpdateService;
import org.tasks.widget.ScrollableWidgetUpdateService; import org.tasks.widget.ScrollableWidgetUpdateService;
@ -12,10 +10,8 @@ import dagger.Module;
@Module(addsTo = TasksModule.class, @Module(addsTo = TasksModule.class,
injects = { injects = {
GtasksBackgroundService.class, GtasksBackgroundService.class,
ReminderSchedulingService.class,
ScrollableWidgetUpdateService.class, ScrollableWidgetUpdateService.class,
WidgetUpdateService.class, WidgetUpdateService.class
BackupService.class
}) })
public class ServiceModule { public class ServiceModule {
} }

@ -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);
}
}
}

@ -1,14 +1,18 @@
package org.tasks.scheduling; package org.tasks.receivers;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tasks.Broadcaster; import org.tasks.Broadcaster;
import org.tasks.injection.InjectingBroadcastReceiver; import org.tasks.injection.InjectingBroadcastReceiver;
import javax.inject.Inject; import javax.inject.Inject;
public class RefreshBroadcastReceiver extends InjectingBroadcastReceiver { public class RefreshReceiver extends InjectingBroadcastReceiver {
private static final Logger log = LoggerFactory.getLogger(RefreshReceiver.class);
@Inject Broadcaster broadcaster; @Inject Broadcaster broadcaster;
@ -16,7 +20,8 @@ public class RefreshBroadcastReceiver extends InjectingBroadcastReceiver {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent); super.onReceive(context, intent);
broadcaster.taskListUpdated(); log.debug("onReceive(context, {})", intent);
broadcaster.filterListUpdated();
broadcaster.refresh();
} }
} }

@ -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));
}
}

@ -1,23 +1,13 @@
/** package org.tasks.scheduling;
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.backup;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import com.todoroo.andlib.service.ContextManager; import com.todoroo.astrid.backup.BackupConstants;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.backup.BackupPreferences;
import com.todoroo.astrid.backup.TasksXmlExporter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.tasks.R;
import org.tasks.injection.InjectingService;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import java.io.File; import java.io.File;
@ -27,44 +17,28 @@ import java.util.Comparator;
import javax.inject.Inject; import javax.inject.Inject;
/** public class BackupIntentService extends MidnightIntentService {
* Inspired heavily by SynchronizationService
*/
public class BackupService extends InjectingService {
private static final Logger log = LoggerFactory.getLogger(BackupService.class);
// --- constants for backup private static final Logger log = LoggerFactory.getLogger(BackupIntentService.class);
/**
* when after phone starts to start first back up
*/
private static final long BACKUP_OFFSET = 5 * 60 * 1000L;
/**
* how often to back up
*/
private static final long BACKUP_INTERVAL = AlarmManager.INTERVAL_DAY;
public static final String BACKUP_ACTION = "backup"; //$NON-NLS-1$
public static final String BACKUP_FILE_NAME_REGEX = "auto\\.[-\\d]+\\.xml"; //$NON-NLS-1$ public static final String BACKUP_FILE_NAME_REGEX = "auto\\.[-\\d]+\\.xml"; //$NON-NLS-1$
private static final int DAYS_TO_KEEP_BACKUP = 7; private static final int DAYS_TO_KEEP_BACKUP = 7;
@Inject TasksXmlExporter xmlExporter; @Inject TasksXmlExporter xmlExporter;
@Inject Preferences preferences; @Inject Preferences preferences;
public BackupIntentService() {
super(BackupIntentService.class.getSimpleName());
}
@Override @Override
public IBinder onBind(Intent intent) { void run() {
return null; startBackup(this);
} }
@Override @Override
public void onStart(Intent intent, int startId) { String getLastRunPreference() {
try { return BackupPreferences.PREF_BACKUP_LAST_DATE;
ContextManager.setContext(this);
startBackup(this);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
} }
/** /**
@ -81,43 +55,20 @@ public class BackupService extends InjectingService {
return; return;
} }
try { try {
if (!preferences.getBoolean(R.string.backup_BPr_auto_key, true)) { deleteOldBackups();
return; } catch (Exception e) {
} log.error(e.getMessage(), e);
}
try {
deleteOldBackups();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
try {
xmlExporter.exportTasks(context, TasksXmlExporter.ExportType.EXPORT_TYPE_SERVICE, xmlExporter.exportTasks(context, TasksXmlExporter.ExportType.EXPORT_TYPE_SERVICE,
backupDirectorySetting.getBackupDirectory()); backupDirectorySetting.getBackupDirectory());
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
preferences.setString(BackupPreferences.PREF_BACKUP_LAST_ERROR, e.toString()); preferences.setString(BackupPreferences.PREF_BACKUP_LAST_ERROR, e.toString());
} }
} }
public static void scheduleService(Preferences preferences, Context context) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(context, 0,
createAlarmIntent(context), PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pendingIntent);
if (!preferences.getBoolean(R.string.backup_BPr_auto_key, true)) {
return;
}
am.setInexactRepeating(AlarmManager.RTC, DateUtilities.now() + BACKUP_OFFSET,
BACKUP_INTERVAL, pendingIntent);
}
private static Intent createAlarmIntent(Context context) {
Intent intent = new Intent(context, BackupService.class);
intent.setAction(BACKUP_ACTION);
return intent;
}
private void deleteOldBackups() { private void deleteOldBackups() {
FileFilter backupFileFilter = new FileFilter() { FileFilter backupFileFilter = new FileFilter() {
@Override @Override

@ -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";
}
}

@ -13,6 +13,7 @@ import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.receivers.RefreshReceiver;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -38,7 +39,7 @@ public class RefreshScheduler {
this.context = context; this.context = context;
} }
public void scheduleAllAlarms() { public void scheduleApplicationRefreshes() {
TodorooCursor<Task> cursor = getTasks(); TodorooCursor<Task> cursor = getTasks();
try { try {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
@ -68,7 +69,7 @@ public class RefreshScheduler {
} }
dueDate += 1000; // this is ghetto dueDate += 1000; // this is ghetto
Intent intent = new Intent(context, RefreshBroadcastReceiver.class); Intent intent = new Intent(context, RefreshReceiver.class);
intent.setAction(Long.toString(dueDate)); intent.setAction(Long.toString(dueDate));
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, FLAG_UPDATE_CURRENT); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, FLAG_UPDATE_CURRENT);

@ -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);
}
}

@ -28,7 +28,7 @@ public class RecordSyncStatusCallback implements SyncResultCallback {
public void finished() { public void finished() {
gtasksPreferenceService.stopOngoing(); gtasksPreferenceService.stopOngoing();
if (broadcaster != null) { if (broadcaster != null) {
broadcaster.eventRefresh(); broadcaster.refresh();
} }
} }
} }

@ -18,6 +18,7 @@
android:id="@+id/completeBox" android:id="@+id/completeBox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingRight="@dimen/task_edit_drawable_padding" android:paddingRight="@dimen/task_edit_drawable_padding"
android:paddingEnd="@dimen/task_edit_drawable_padding" android:paddingEnd="@dimen/task_edit_drawable_padding"
android:scaleType="center" android:scaleType="center"

@ -7,7 +7,6 @@
<resources> <resources>
<string name="TVA_add_comment">إضافة تعليق ...</string> <string name="TVA_add_comment">إضافة تعليق ...</string>
<string name="backup_BPr_group_status">الحالة</string> <string name="backup_BPr_group_status">الحالة</string>
<string name="backup_BPr_group_options">الخيارات</string>
<string name="DLG_cancel">الغي</string> <string name="DLG_cancel">الغي</string>
<string name="WID_dateButtonUnset">اضغط لتعيين</string> <string name="WID_dateButtonUnset">اضغط لتعيين</string>
<string name="TLA_no_items">لا يوجد لديك مهام! \n هل تريد أن تضيف شيئا؟</string> <string name="TLA_no_items">لا يوجد لديك مهام! \n هل تريد أن تضيف شيئا؟</string>

@ -19,10 +19,6 @@
<string name="backup_status_success">Последно резервно копие:\n%s</string> <string name="backup_status_success">Последно резервно копие:\n%s</string>
<string name="backup_status_failed">Последното резервно копиране се провали</string> <string name="backup_status_failed">Последното резервно копиране се провали</string>
<string name="backup_status_never">Никога не е правено резевно копиране!</string> <string name="backup_status_never">Никога не е правено резевно копиране!</string>
<string name="backup_BPr_group_options">Опции</string>
<string name="backup_BPr_auto_title">Автоматично резервно копиране</string>
<string name="backup_BPr_auto_disabled">Автоматичното резервно копиране е изключено</string>
<string name="backup_BPr_auto_enabled">Резервно копиране ще се случва всеки ден</string>
<string name="backup_BAc_import">Импортиране на задачи</string> <string name="backup_BAc_import">Импортиране на задачи</string>
<string name="backup_BAc_export">Експортиране на задачи</string> <string name="backup_BAc_export">Експортиране на задачи</string>
<string name="export_toast_no_tasks">Няма задачи за експортиране</string> <string name="export_toast_no_tasks">Няма задачи за експортиране</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">Còpia de seguretat Fallida</string> <string name="backup_status_failed">Còpia de seguretat Fallida</string>
<string name="backup_status_failed_subtitle">Feu clic per veure l\'error</string> <string name="backup_status_failed_subtitle">Feu clic per veure l\'error</string>
<string name="backup_status_never">Encara sense Còpies!</string> <string name="backup_status_never">Encara sense Còpies!</string>
<string name="backup_BPr_group_options">Opcions</string>
<string name="backup_BPr_auto_title">Còpies de seguretat automàtiques</string>
<string name="backup_BPr_auto_disabled">Còpies de seguretat automàtiques desactivades</string>
<string name="backup_BPr_auto_enabled">Còpies de seguretat diàries</string>
<string name="backup_BAc_import">Importa tasques</string> <string name="backup_BAc_import">Importa tasques</string>
<string name="backup_BAc_export">Exporta tasques</string> <string name="backup_BAc_export">Exporta tasques</string>
<string name="export_toast_no_tasks">Sense tasques que exportar</string> <string name="export_toast_no_tasks">Sense tasques que exportar</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">Předchozí zálohování selhalo</string> <string name="backup_status_failed">Předchozí zálohování selhalo</string>
<string name="backup_status_failed_subtitle">klikněte pro zobrazení chyby</string> <string name="backup_status_failed_subtitle">klikněte pro zobrazení chyby</string>
<string name="backup_status_never">Nikdy nezálohováno!</string> <string name="backup_status_never">Nikdy nezálohováno!</string>
<string name="backup_BPr_group_options">Nastavení</string>
<string name="backup_BPr_auto_title">Automatické zálohování</string>
<string name="backup_BPr_auto_disabled">Automatické zálohování je zakázáno</string>
<string name="backup_BPr_auto_enabled">Zálohování se bude provádět denně</string>
<string name="backup_BAc_import">Importovat úkoly</string> <string name="backup_BAc_import">Importovat úkoly</string>
<string name="backup_BAc_export">Exportovat úkoly</string> <string name="backup_BAc_export">Exportovat úkoly</string>
<string name="export_toast">Zálohovány %1$s do %2$s.</string> <string name="export_toast">Zálohovány %1$s do %2$s.</string>

@ -18,10 +18,6 @@
<string name="backup_status_failed">Seneste backup fejlede</string> <string name="backup_status_failed">Seneste backup fejlede</string>
<string name="backup_status_failed_subtitle">(tryk for at vise fejl)</string> <string name="backup_status_failed_subtitle">(tryk for at vise fejl)</string>
<string name="backup_status_never">Har aldrig taget backup!</string> <string name="backup_status_never">Har aldrig taget backup!</string>
<string name="backup_BPr_group_options">Indstillinger</string>
<string name="backup_BPr_auto_title">Automatisk backup</string>
<string name="backup_BPr_auto_disabled">Automatisk backup deaktiveret</string>
<string name="backup_BPr_auto_enabled">Backup vil ske dagligt</string>
<string name="backup_BAc_import">Importér opgaver</string> <string name="backup_BAc_import">Importér opgaver</string>
<string name="backup_BAc_export">Eksportér opgaver</string> <string name="backup_BAc_export">Eksportér opgaver</string>
<string name="export_toast">Sikkerhedskopierede %1$s til %2$s.</string> <string name="export_toast">Sikkerhedskopierede %1$s til %2$s.</string>

@ -18,10 +18,6 @@
<string name="backup_status_failed">Letzte Datensicherung gescheitert</string> <string name="backup_status_failed">Letzte Datensicherung gescheitert</string>
<string name="backup_status_failed_subtitle">(Anklicken, um Fehler anzuzeigen)</string> <string name="backup_status_failed_subtitle">(Anklicken, um Fehler anzuzeigen)</string>
<string name="backup_status_never">Bisher keine Datensicherung erstellt!</string> <string name="backup_status_never">Bisher keine Datensicherung erstellt!</string>
<string name="backup_BPr_group_options">Optionen</string>
<string name="backup_BPr_auto_title">Automatische Backups</string>
<string name="backup_BPr_auto_disabled">Automatische Backups deaktiviert</string>
<string name="backup_BPr_auto_enabled">Backup täglich durchführen</string>
<string name="backup_BAc_import">Aufgaben importieren</string> <string name="backup_BAc_import">Aufgaben importieren</string>
<string name="backup_BAc_export">Aufgaben exportieren</string> <string name="backup_BAc_export">Aufgaben exportieren</string>
<string name="export_toast">Gesichert von %1$s bis %2$s.</string> <string name="export_toast">Gesichert von %1$s bis %2$s.</string>

@ -18,10 +18,6 @@
<string name="backup_status_failed">Το τελευταίο αντίγραφο ασφαλείας απέτυχε</string> <string name="backup_status_failed">Το τελευταίο αντίγραφο ασφαλείας απέτυχε</string>
<string name="backup_status_failed_subtitle">(πατήστε για να δείξετε σφάλμα)</string> <string name="backup_status_failed_subtitle">(πατήστε για να δείξετε σφάλμα)</string>
<string name="backup_status_never">Δεν έγινε ποτέ αντίγραφο ασφαλείας!</string> <string name="backup_status_never">Δεν έγινε ποτέ αντίγραφο ασφαλείας!</string>
<string name="backup_BPr_group_options">Ρυθμίσεις</string>
<string name="backup_BPr_auto_title">Αυτόματα αντίγραφα ασφαλείας</string>
<string name="backup_BPr_auto_disabled">Αυτόματα αντίγραφα ασφαλείας απενεργοποιήθηκαν</string>
<string name="backup_BPr_auto_enabled">Aντίγραφα ασφαλείας θα παίρνονται καθημερινά</string>
<string name="backup_BAc_import">Εισαγωγή καθηκόντων</string> <string name="backup_BAc_import">Εισαγωγή καθηκόντων</string>
<string name="backup_BAc_export">Εξαγωγή καθηκόντων</string> <string name="backup_BAc_export">Εξαγωγή καθηκόντων</string>
<string name="export_toast">Αποθηκεύση ασφαλείας %1$s στο %2$s.</string> <string name="export_toast">Αποθηκεύση ασφαλείας %1$s στο %2$s.</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">La última copia de seguridad falló</string> <string name="backup_status_failed">La última copia de seguridad falló</string>
<string name="backup_status_failed_subtitle">(toque para visualizar los errores)</string> <string name="backup_status_failed_subtitle">(toque para visualizar los errores)</string>
<string name="backup_status_never">Nunca se hizo copia de seguridad!</string> <string name="backup_status_never">Nunca se hizo copia de seguridad!</string>
<string name="backup_BPr_group_options">Opciones</string>
<string name="backup_BPr_auto_title">Copias de seguridad automáticas</string>
<string name="backup_BPr_auto_disabled">Copias de seguridad automáticas desactivadas</string>
<string name="backup_BPr_auto_enabled">La copia de seguridad se hará diariamente</string>
<string name="backup_BAc_import">Importar tareas</string> <string name="backup_BAc_import">Importar tareas</string>
<string name="backup_BAc_export">Exportar tareas</string> <string name="backup_BAc_export">Exportar tareas</string>
<string name="export_toast">Respaldadas %1$s de %2$s.</string> <string name="export_toast">Respaldadas %1$s de %2$s.</string>

@ -23,9 +23,6 @@
<string name="backup_status_failed">La dernière sauvegarde a échoué</string> <string name="backup_status_failed">La dernière sauvegarde a échoué</string>
<string name="backup_status_failed_subtitle">(appuyer pour afficher l\'erreur)</string> <string name="backup_status_failed_subtitle">(appuyer pour afficher l\'erreur)</string>
<string name="backup_status_never">Aucune sauvegarde !</string> <string name="backup_status_never">Aucune sauvegarde !</string>
<string name="backup_BPr_auto_title">Sauvegardes automatiques</string>
<string name="backup_BPr_auto_disabled">Sauvegardes automatiques désactivées</string>
<string name="backup_BPr_auto_enabled">Une sauvegarde sera effectuée quotidiennement.</string>
<string name="backup_BAc_import">Importer des tâches</string> <string name="backup_BAc_import">Importer des tâches</string>
<string name="backup_BAc_export">Exporter des tâches</string> <string name="backup_BAc_export">Exporter des tâches</string>
<string name="export_toast">Sauvegardé %1$s dans %2$s.</string> <string name="export_toast">Sauvegardé %1$s dans %2$s.</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">Ultimo Backup Fallito</string> <string name="backup_status_failed">Ultimo Backup Fallito</string>
<string name="backup_status_failed_subtitle">(clicca per visualizzare l\'errore)</string> <string name="backup_status_failed_subtitle">(clicca per visualizzare l\'errore)</string>
<string name="backup_status_never">Mai eseguito!</string> <string name="backup_status_never">Mai eseguito!</string>
<string name="backup_BPr_group_options">Preferenze</string>
<string name="backup_BPr_auto_title">Backup automatici</string>
<string name="backup_BPr_auto_disabled">Backup Automatico Disabilitato</string>
<string name="backup_BPr_auto_enabled">I Backup verranno eseguiti giornalmente</string>
<string name="backup_BAc_import">Importa compiti</string> <string name="backup_BAc_import">Importa compiti</string>
<string name="backup_BAc_export">Esporta compiti</string> <string name="backup_BAc_export">Esporta compiti</string>
<string name="export_toast">Backup di %1$s su %2$s eseguito.</string> <string name="export_toast">Backup di %1$s su %2$s eseguito.</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">הגיבוי האחרון נכשל</string> <string name="backup_status_failed">הגיבוי האחרון נכשל</string>
<string name="backup_status_failed_subtitle">\"(טפח כדי להציג את השגיאה)\"</string> <string name="backup_status_failed_subtitle">\"(טפח כדי להציג את השגיאה)\"</string>
<string name="backup_status_never">לא נעשו גיבויים מעולם!</string> <string name="backup_status_never">לא נעשו גיבויים מעולם!</string>
<string name="backup_BPr_group_options">אפשרויות</string>
<string name="backup_BPr_auto_title">גיבויים אוטומטיים</string>
<string name="backup_BPr_auto_disabled">הגיבויים האוטומטיים הופסקו</string>
<string name="backup_BPr_auto_enabled">הגיבוי יתבצע מדי יום</string>
<string name="backup_BAc_import">ייבוא משימות</string> <string name="backup_BAc_import">ייבוא משימות</string>
<string name="backup_BAc_export">ייצוא משימות</string> <string name="backup_BAc_export">ייצוא משימות</string>
<string name="export_toast">בוצע גיבוי של %1$s אל %2$s.</string> <string name="export_toast">בוצע גיבוי של %1$s אל %2$s.</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">前回のバックアップが失敗しました</string> <string name="backup_status_failed">前回のバックアップが失敗しました</string>
<string name="backup_status_failed_subtitle">(タップでエラーを表示)</string> <string name="backup_status_failed_subtitle">(タップでエラーを表示)</string>
<string name="backup_status_never">一度もバックアップされていません!</string> <string name="backup_status_never">一度もバックアップされていません!</string>
<string name="backup_BPr_group_options">オプション</string>
<string name="backup_BPr_auto_title">自動的なバックアップ</string>
<string name="backup_BPr_auto_disabled">自動的なバックアップは無効です</string>
<string name="backup_BPr_auto_enabled">バックアップは毎日行われます</string>
<string name="backup_BAc_import">タスクのインポート</string> <string name="backup_BAc_import">タスクのインポート</string>
<string name="backup_BAc_export">タスクのエクスポート</string> <string name="backup_BAc_export">タスクのエクスポート</string>
<string name="export_toast">%1$s を %2$s にバックアップしました。</string> <string name="export_toast">%1$s を %2$s にバックアップしました。</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">마지막 백업 실패함</string> <string name="backup_status_failed">마지막 백업 실패함</string>
<string name="backup_status_failed_subtitle">(오류 내용을 보려면 누르세요)</string> <string name="backup_status_failed_subtitle">(오류 내용을 보려면 누르세요)</string>
<string name="backup_status_never">백업한 적이 없습니다!</string> <string name="backup_status_never">백업한 적이 없습니다!</string>
<string name="backup_BPr_group_options">설정</string>
<string name="backup_BPr_auto_title">자동 백업</string>
<string name="backup_BPr_auto_disabled">자동으로 백업하지 않습니다</string>
<string name="backup_BPr_auto_enabled">매일 백업합니다</string>
<string name="backup_BAc_import">일정 가져오기</string> <string name="backup_BAc_import">일정 가져오기</string>
<string name="backup_BAc_export">일정 내보내기</string> <string name="backup_BAc_export">일정 내보내기</string>
<string name="export_toast">%1$s 를 %2$s 로 백업함.</string> <string name="export_toast">%1$s 를 %2$s 로 백업함.</string>

@ -12,10 +12,6 @@
<string name="backup_status_failed">Siste sikkerhetskopiering mislyktes</string> <string name="backup_status_failed">Siste sikkerhetskopiering mislyktes</string>
<string name="backup_status_failed_subtitle">(klikk for å vise feil)</string> <string name="backup_status_failed_subtitle">(klikk for å vise feil)</string>
<string name="backup_status_never">Sikkerhetskopi aldri utført!</string> <string name="backup_status_never">Sikkerhetskopi aldri utført!</string>
<string name="backup_BPr_group_options">Alternativer</string>
<string name="backup_BPr_auto_title">Automatisk sikkerhetskopiering</string>
<string name="backup_BPr_auto_disabled">Automatisk sikkerhetskopiering deaktivert</string>
<string name="backup_BPr_auto_enabled">Sikkerhetskopiering vil skje daglig</string>
<string name="backup_BAc_import">Importer oppgaver</string> <string name="backup_BAc_import">Importer oppgaver</string>
<string name="backup_BAc_export">Eksporter oppgaver</string> <string name="backup_BAc_export">Eksporter oppgaver</string>
<string name="export_toast">Backup ferdig %1$s av %2$s.</string> <string name="export_toast">Backup ferdig %1$s av %2$s.</string>

@ -22,10 +22,6 @@
<string name="backup_status_failed">Laatste back-up mislukt</string> <string name="backup_status_failed">Laatste back-up mislukt</string>
<string name="backup_status_failed_subtitle">(tik om foutmelding te zien)</string> <string name="backup_status_failed_subtitle">(tik om foutmelding te zien)</string>
<string name="backup_status_never">Nooit eerder back-up van gemaakt!</string> <string name="backup_status_never">Nooit eerder back-up van gemaakt!</string>
<string name="backup_BPr_group_options">Opties</string>
<string name="backup_BPr_auto_title">Automatische back-ups</string>
<string name="backup_BPr_auto_disabled">Automatische back-ups uitgeschakeld</string>
<string name="backup_BPr_auto_enabled">Back-up dagelijks uitvoeren</string>
<string name="backup_BAc_import">Taken importeren</string> <string name="backup_BAc_import">Taken importeren</string>
<string name="backup_BAc_export">Taken exporteren</string> <string name="backup_BAc_export">Taken exporteren</string>
<string name="export_toast">Back-up gemaakt van %1$s naar %2$s.</string> <string name="export_toast">Back-up gemaakt van %1$s naar %2$s.</string>

@ -20,10 +20,6 @@
<string name="backup_status_failed">Błąd zapisu ostatniej kopii</string> <string name="backup_status_failed">Błąd zapisu ostatniej kopii</string>
<string name="backup_status_failed_subtitle">(puknij, aby zobaczyć błąd)</string> <string name="backup_status_failed_subtitle">(puknij, aby zobaczyć błąd)</string>
<string name="backup_status_never">Kopia zapasowa nigdy nie wykonana!</string> <string name="backup_status_never">Kopia zapasowa nigdy nie wykonana!</string>
<string name="backup_BPr_group_options">Opcje</string>
<string name="backup_BPr_auto_title">Automatyczne kopie zapasowe</string>
<string name="backup_BPr_auto_disabled">Automatyczne kopie zapasowe wyłączone</string>
<string name="backup_BPr_auto_enabled">Kopia zapasowa będzie wykonywana codziennie</string>
<string name="backup_BAc_import">Importuj zadania</string> <string name="backup_BAc_import">Importuj zadania</string>
<string name="backup_BAc_export">Eksportuj zadania</string> <string name="backup_BAc_export">Eksportuj zadania</string>
<string name="export_toast">Zapisano %1$s do %2$s.</string> <string name="export_toast">Zapisano %1$s do %2$s.</string>

@ -22,10 +22,6 @@
<string name="backup_status_failed">O último backup falhou</string> <string name="backup_status_failed">O último backup falhou</string>
<string name="backup_status_failed_subtitle">(toque para exibir o erro)</string> <string name="backup_status_failed_subtitle">(toque para exibir o erro)</string>
<string name="backup_status_never">O Backup nunca foi executado!</string> <string name="backup_status_never">O Backup nunca foi executado!</string>
<string name="backup_BPr_group_options">Opções</string>
<string name="backup_BPr_auto_title">Backups automáticos</string>
<string name="backup_BPr_auto_disabled">Backups automáticos desativados</string>
<string name="backup_BPr_auto_enabled">O Backup ocorrerá diariamente</string>
<string name="backup_BAc_import">Importar tarefas</string> <string name="backup_BAc_import">Importar tarefas</string>
<string name="backup_BAc_export">Exportar tarefas</string> <string name="backup_BAc_export">Exportar tarefas</string>
<string name="export_toast">Backups feitos: de %1$s para %2$s.</string> <string name="export_toast">Backups feitos: de %1$s para %2$s.</string>

@ -22,10 +22,6 @@
<string name="backup_status_failed">Último backup falhou</string> <string name="backup_status_failed">Último backup falhou</string>
<string name="backup_status_failed_subtitle">(clique para ver o erro)</string> <string name="backup_status_failed_subtitle">(clique para ver o erro)</string>
<string name="backup_status_never">Nunca fez um backup!</string> <string name="backup_status_never">Nunca fez um backup!</string>
<string name="backup_BPr_group_options">Opções</string>
<string name="backup_BPr_auto_title">Backups automáticos</string>
<string name="backup_BPr_auto_disabled">Backups automáticos desativados</string>
<string name="backup_BPr_auto_enabled">Backups diários</string>
<string name="backup_BAc_import">Importar tarefas</string> <string name="backup_BAc_import">Importar tarefas</string>
<string name="backup_BAc_export">Exportar tarefas</string> <string name="backup_BAc_export">Exportar tarefas</string>
<string name="export_toast">Backup de %1$s para %2$s.</string> <string name="export_toast">Backup de %1$s para %2$s.</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">Резервирование не удалось</string> <string name="backup_status_failed">Резервирование не удалось</string>
<string name="backup_status_failed_subtitle">(нажмите для просмотра ошибки)</string> <string name="backup_status_failed_subtitle">(нажмите для просмотра ошибки)</string>
<string name="backup_status_never">Резервное копирование ещё не совершалось!</string> <string name="backup_status_never">Резервное копирование ещё не совершалось!</string>
<string name="backup_BPr_group_options">Параметры</string>
<string name="backup_BPr_auto_title">Резервное копирование: автоматическое</string>
<string name="backup_BPr_auto_disabled">Резервное копирование: отключено</string>
<string name="backup_BPr_auto_enabled">Резервное копирование будет производиться ежедневно</string>
<string name="backup_BAc_import">Импортировать задачи</string> <string name="backup_BAc_import">Импортировать задачи</string>
<string name="backup_BAc_export">Экспортировать задачи</string> <string name="backup_BAc_export">Экспортировать задачи</string>
<string name="export_toast">Восстановлено %1$s в %2$s.</string> <string name="export_toast">Восстановлено %1$s в %2$s.</string>

@ -22,10 +22,6 @@
<string name="backup_status_failed">Najnovejša varnostna kopija neuspešna</string> <string name="backup_status_failed">Najnovejša varnostna kopija neuspešna</string>
<string name="backup_status_failed_subtitle">(hitri dotik pokaže napako)</string> <string name="backup_status_failed_subtitle">(hitri dotik pokaže napako)</string>
<string name="backup_status_never">Varnostna kopija še NIkoli SHRANJENA!</string> <string name="backup_status_never">Varnostna kopija še NIkoli SHRANJENA!</string>
<string name="backup_BPr_group_options">Možnosti</string>
<string name="backup_BPr_auto_title">Samodejne varnostne kopije</string>
<string name="backup_BPr_auto_disabled">Samodejne varnostne kopije onemogočene</string>
<string name="backup_BPr_auto_enabled">Varnostna kopija bo shranjena vsak dan</string>
<string name="backup_BAc_import">Uvozi opravke</string> <string name="backup_BAc_import">Uvozi opravke</string>
<string name="backup_BAc_export">Izvozi opravke</string> <string name="backup_BAc_export">Izvozi opravke</string>
<string name="export_toast">Varnostna kopija za %1$s shranjena v %2$s.</string> <string name="export_toast">Varnostna kopija za %1$s shranjena v %2$s.</string>

@ -19,10 +19,6 @@
<string name="backup_status_failed">Senaste säkerhetskopieringen misslyckades</string> <string name="backup_status_failed">Senaste säkerhetskopieringen misslyckades</string>
<string name="backup_status_failed_subtitle">(klicka för att se felet)</string> <string name="backup_status_failed_subtitle">(klicka för att se felet)</string>
<string name="backup_status_never">Aldrig säkerhetskopierat!</string> <string name="backup_status_never">Aldrig säkerhetskopierat!</string>
<string name="backup_BPr_group_options">Alternativ</string>
<string name="backup_BPr_auto_title">Automatisk säkerhetskopiering</string>
<string name="backup_BPr_auto_disabled">Automatisk säkerhetskopiering avaktiverad</string>
<string name="backup_BPr_auto_enabled">Säkerhetskopiering kommer att ske dagligen</string>
<string name="backup_BAc_import">Importera uppgifter</string> <string name="backup_BAc_import">Importera uppgifter</string>
<string name="backup_BAc_export">Exportera uppgifter</string> <string name="backup_BAc_export">Exportera uppgifter</string>
<string name="export_toast">Säkerhetskopierade %1$s till %2$s.</string> <string name="export_toast">Säkerhetskopierade %1$s till %2$s.</string>

@ -14,8 +14,6 @@
<string name="backup_BPr_header">สำรองข้อมูล</string> <string name="backup_BPr_header">สำรองข้อมูล</string>
<string name="backup_BPr_group_status">สถานะ</string> <string name="backup_BPr_group_status">สถานะ</string>
<string name="backup_status_failed_subtitle">(แตะเพื่อแสดงข้อผิดพลาด)</string> <string name="backup_status_failed_subtitle">(แตะเพื่อแสดงข้อผิดพลาด)</string>
<string name="backup_BPr_group_options">ตัวเลือก</string>
<string name="backup_BPr_auto_enabled">จะทำการสำรองข้อมูลทุกวัน</string>
<string name="export_progress_title">กำลังส่งออก...</string> <string name="export_progress_title">กำลังส่งออก...</string>
<string name="import_progress_title">กำลังนำเข้า...</string> <string name="import_progress_title">กำลังนำเข้า...</string>
<string name="import_progress_read">กำลังอ่านแผนงาน %d...</string> <string name="import_progress_read">กำลังอ่านแผนงาน %d...</string>

@ -20,10 +20,6 @@
<string name="backup_status_failed">Son Yedekleme Başarısız</string> <string name="backup_status_failed">Son Yedekleme Başarısız</string>
<string name="backup_status_failed_subtitle">(hatayı görmek için dokunun)</string> <string name="backup_status_failed_subtitle">(hatayı görmek için dokunun)</string>
<string name="backup_status_never">Hiç Yedeklenmemiş!</string> <string name="backup_status_never">Hiç Yedeklenmemiş!</string>
<string name="backup_BPr_group_options">Seçenekler</string>
<string name="backup_BPr_auto_title">Kendiliğinden Yedeklemeler</string>
<string name="backup_BPr_auto_disabled">Kendiliğinden Yedekleme Etkisiz</string>
<string name="backup_BPr_auto_enabled">Günlük yedekleme yapılacak</string>
<string name="backup_BAc_import">Görevleri İçe Aktar</string> <string name="backup_BAc_import">Görevleri İçe Aktar</string>
<string name="backup_BAc_export">Görevleri Dışa Aktar</string> <string name="backup_BAc_export">Görevleri Dışa Aktar</string>
<string name="export_toast">%1$s şuraya yedeklendi: %2$s.</string> <string name="export_toast">%1$s şuraya yedeklendi: %2$s.</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">Створення останньої резервної копії не вдалось</string> <string name="backup_status_failed">Створення останньої резервної копії не вдалось</string>
<string name="backup_status_failed_subtitle">(торкніться щоб подивитись помилку)</string> <string name="backup_status_failed_subtitle">(торкніться щоб подивитись помилку)</string>
<string name="backup_status_never">Резервна копія не створена!</string> <string name="backup_status_never">Резервна копія не створена!</string>
<string name="backup_BPr_group_options">Налаштування</string>
<string name="backup_BPr_auto_title">Автоматичне резервне копіювання</string>
<string name="backup_BPr_auto_disabled">Автоматичне резервне копіювання заборонене</string>
<string name="backup_BPr_auto_enabled">Резервне копіювання буде здійснюватись щоденно</string>
<string name="backup_BAc_import">Імпортувати завдання</string> <string name="backup_BAc_import">Імпортувати завдання</string>
<string name="backup_BAc_export">Експорт завдань</string> <string name="backup_BAc_export">Експорт завдань</string>
<string name="export_toast">Резервні копії %1$s для %2$s.</string> <string name="export_toast">Резервні копії %1$s для %2$s.</string>

@ -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>

@ -23,10 +23,6 @@
<string name="backup_status_failed">上次备份失败</string> <string name="backup_status_failed">上次备份失败</string>
<string name="backup_status_failed_subtitle">(点击查看错误)</string> <string name="backup_status_failed_subtitle">(点击查看错误)</string>
<string name="backup_status_never">从未备份!</string> <string name="backup_status_never">从未备份!</string>
<string name="backup_BPr_group_options">选项</string>
<string name="backup_BPr_auto_title">自动备份</string>
<string name="backup_BPr_auto_disabled">自动备份已停用</string>
<string name="backup_BPr_auto_enabled">备份每天执行</string>
<string name="backup_BAc_import">导入任务</string> <string name="backup_BAc_import">导入任务</string>
<string name="backup_BAc_export">导出任务</string> <string name="backup_BAc_export">导出任务</string>
<string name="export_toast">已将 %1$s 备份至 %2$s。</string> <string name="export_toast">已将 %1$s 备份至 %2$s。</string>

@ -23,10 +23,6 @@
<string name="backup_status_failed">上次備份失敗</string> <string name="backup_status_failed">上次備份失敗</string>
<string name="backup_status_failed_subtitle">(點選查看錯誤)</string> <string name="backup_status_failed_subtitle">(點選查看錯誤)</string>
<string name="backup_status_never">從未備份</string> <string name="backup_status_never">從未備份</string>
<string name="backup_BPr_group_options">選項</string>
<string name="backup_BPr_auto_title">自動備份</string>
<string name="backup_BPr_auto_disabled">停用自動備份</string>
<string name="backup_BPr_auto_enabled">備份將每天執行</string>
<string name="backup_BAc_import">匯入工作</string> <string name="backup_BAc_import">匯入工作</string>
<string name="backup_BAc_export">匯出工作</string> <string name="backup_BAc_export">匯出工作</string>
<string name="export_toast">備份 %1$s 至 %2$s.</string> <string name="export_toast">備份 %1$s 至 %2$s.</string>

@ -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>

@ -228,8 +228,6 @@
<!-- Preference Key (do not translate) --> <!-- Preference Key (do not translate) -->
<string name="backup_BPr_status_key">backup_status</string> <string name="backup_BPr_status_key">backup_status</string>
<!-- Preference Key (do not translate) -->
<string name="backup_BPr_auto_key">backup</string>
<!-- Default Calendar Preference Key (do not translate) --> <!-- Default Calendar Preference Key (do not translate) -->
<string name="gcal_p_default">default_calendar_id</string> <string name="gcal_p_default">default_calendar_id</string>

@ -20,16 +20,6 @@
<!-- slide 48a: Backup Status: never backed up --> <!-- slide 48a: Backup Status: never backed up -->
<string name="backup_status_never">Never backed up!</string> <string name="backup_status_never">Never backed up!</string>
<!-- slide 48f/ 50e: Backup Options Group Label -->
<string name="backup_BPr_group_options">Options</string>
<!-- slide 48b: Preference: Automatic Backup Title -->
<string name="backup_BPr_auto_title">Automatic backups</string>
<!-- Preference: Automatic Backup Description (when disabled) -->
<string name="backup_BPr_auto_disabled">Automatic backups disabled</string>
<!-- slide 48g: Preference: Automatic Backup Description (when enabled) -->
<string name="backup_BPr_auto_enabled">Backup will occur daily</string>
<!-- backup activity import button --> <!-- backup activity import button -->
<string name="backup_BAc_import">Import tasks</string> <string name="backup_BAc_import">Import tasks</string>

@ -18,16 +18,6 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory
android:title="@string/backup_BPr_group_options">
<com.todoroo.astrid.ui.MultilineCheckboxPreference
android:key="@string/backup_BPr_auto_key"
android:title="@string/backup_BPr_auto_title"
android:defaultValue="true" />
</PreferenceCategory>
<Preference <Preference
android:key="@string/backup_BAc_import" android:key="@string/backup_BAc_import"
android:title="@string/backup_BAc_import"/> android:title="@string/backup_BAc_import"/>

Loading…
Cancel
Save