diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml
index 583884b4f..3b1405d94 100644
--- a/astrid/AndroidManifest.xml
+++ b/astrid/AndroidManifest.xml
@@ -201,6 +201,19 @@
FilterListFilter
allows users to display tasks that have
* something in common.
@@ -36,6 +38,7 @@ public final class Filter extends FilterListItem {
*
* e.g "Tasks With Notes"
*/
+ @CheckForNull
public String title;
/**
@@ -53,6 +56,7 @@ public final class Filter extends FilterListItem {
* metadata.value = 'b' GROUP BY tasks.id ORDER BY tasks.title"
*
*/
+ @CheckForNull
public String sqlQuery;
/**
@@ -61,6 +65,7 @@ public final class Filter extends FilterListItem {
* tasks they create should also be tagged 'ABC'. If set to null, no
* additional values will be stored for a task.
*/
+ @CheckForNull
public ContentValues valuesForNewTasks = null;
/**
diff --git a/astrid/api-src/com/todoroo/astrid/api/FilterCategory.java b/astrid/api-src/com/todoroo/astrid/api/FilterCategory.java
index 3fe51d269..4b00695ad 100644
--- a/astrid/api-src/com/todoroo/astrid/api/FilterCategory.java
+++ b/astrid/api-src/com/todoroo/astrid/api/FilterCategory.java
@@ -5,6 +5,7 @@ package com.todoroo.astrid.api;
import android.os.Parcel;
import android.os.Parcelable;
+import edu.umd.cs.findbugs.annotations.CheckForNull;
/**
* A FilterCategory
groups common {@link Filter}s and allows
@@ -18,6 +19,7 @@ public class FilterCategory extends FilterListItem {
/**
* {@link Filter}s contained by this category
*/
+ @CheckForNull
public Filter[] children;
/**
diff --git a/astrid/api-src/com/todoroo/astrid/api/FilterListItem.java b/astrid/api-src/com/todoroo/astrid/api/FilterListItem.java
index 747a22cf3..d23f9e4e9 100644
--- a/astrid/api-src/com/todoroo/astrid/api/FilterListItem.java
+++ b/astrid/api-src/com/todoroo/astrid/api/FilterListItem.java
@@ -7,6 +7,7 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Parcel;
import android.os.Parcelable;
+import edu.umd.cs.findbugs.annotations.CheckForNull;
/**
* Represents an item displayed by Astrid's FilterListActivity
@@ -19,17 +20,20 @@ abstract public class FilterListItem implements Parcelable {
/**
* Title of this item displayed on the Filters page
*/
+ @CheckForNull
public String listingTitle = null;
/**
* Bitmap for icon used on listing page. null
=> no icon
*/
+ @CheckForNull
public Bitmap listingIcon = null;
/**
* Context Menu labels. The context menu will be displayed when users
* long-press on this filter list item.
*/
+ @CheckForNull
public String contextMenuLabels[] = new String[0];
/**
@@ -37,6 +41,7 @@ abstract public class FilterListItem implements Parcelable {
* content menu label is invoked. This array must be the same size as
* the contextMenuLabels array.
*/
+ @CheckForNull
public Intent contextMenuIntents[] = new Intent[0];
// --- parcelable helpers
diff --git a/astrid/api-src/com/todoroo/astrid/api/TaskDecoration.java b/astrid/api-src/com/todoroo/astrid/api/TaskDecoration.java
index e1cf4115c..3d12aab10 100644
--- a/astrid/api-src/com/todoroo/astrid/api/TaskDecoration.java
+++ b/astrid/api-src/com/todoroo/astrid/api/TaskDecoration.java
@@ -7,6 +7,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.widget.RemoteViews;
import android.widget.RemoteViews.RemoteView;
+import edu.umd.cs.findbugs.annotations.CheckForNull;
/**
* Represents a line of text displayed in the Task List
@@ -29,6 +30,7 @@ public final class TaskDecoration implements Parcelable {
/**
* {@link RemoteView} decoration
*/
+ @CheckForNull
public RemoteViews decoration = null;
/**
diff --git a/astrid/plugin-src/com/todoroo/astrid/backup/BackupPreferences.java b/astrid/plugin-src/com/todoroo/astrid/backup/BackupPreferences.java
new file mode 100644
index 000000000..1ca13d244
--- /dev/null
+++ b/astrid/plugin-src/com/todoroo/astrid/backup/BackupPreferences.java
@@ -0,0 +1,125 @@
+package com.todoroo.astrid.backup;
+
+import java.util.Date;
+
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.view.View;
+import android.view.ViewGroup.OnHierarchyChangeListener;
+
+import com.timsu.astrid.R;
+import com.todoroo.andlib.service.Autowired;
+import com.todoroo.andlib.utility.DateUtilities;
+import com.todoroo.andlib.utility.DialogUtilities;
+import com.todoroo.andlib.widget.TodorooPreferences;
+import com.todoroo.astrid.utility.Preferences;
+
+/**
+ * Displays synchronization preferences and an action panel so users can
+ * initiate actions from the menu.
+ *
+ * @author timsu
+ *
+ */
+public class BackupPreferences extends TodorooPreferences {
+
+ static final String PREF_BACKUP_LAST_DATE = "backupDate"; //$NON-NLS-1$
+
+ static final String PREF_BACKUP_LAST_ERROR = "backupError"; //$NON-NLS-1$
+
+ @Autowired
+ private DialogUtilities dialogUtilities;
+
+ private int statusColor = Color.BLACK;
+
+ @Override
+ public int getPreferenceResource() {
+ return R.xml.preferences_backup;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getListView().setOnHierarchyChangeListener(new OnHierarchyChangeListener() {
+
+ @Override
+ public void onChildViewRemoved(View parent, View child) {
+ //
+ }
+
+ @Override
+ public void onChildViewAdded(View parent, View child) {
+ View view = findViewById(R.id.status);
+ if(view != null)
+ view.setBackgroundColor(statusColor);
+ }
+ });
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ BackupService.scheduleService(this);
+ }
+
+ /**
+ *
+ * @param resource
+ * if null, updates all resources
+ */
+ @Override
+ public void updatePreferences(Preference preference, Object value) {
+ final Resources r = getResources();
+
+ // auto
+ 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 subtitle = ""; //$NON-NLS-1$
+
+ // last backup was error
+ final long last = Preferences.getLong(PREF_BACKUP_LAST_DATE, 0);
+ final String error = Preferences.getStringValue(PREF_BACKUP_LAST_ERROR);
+ if(error != null) {
+ status = r.getString(R.string.backup_status_failed);
+ subtitle = r.getString(R.string.backup_status_failed_subtitle);
+ statusColor = Color.rgb(100, 0, 0);
+ preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference p) {
+ dialogUtilities.okDialog(BackupPreferences.this, error, null);
+ return true;
+ }
+ });
+ } else if(last > 0) {
+ status = r.getString(R.string.backup_status_success,
+ DateUtilities.getDateWithTimeFormat(BackupPreferences.this).
+ format(new Date(last)));
+ statusColor = Color.rgb(0, 100, 0);
+ preference.setOnPreferenceClickListener(null);
+ } else {
+ status = r.getString(R.string.backup_status_never);
+ statusColor = Color.rgb(0, 0, 100);
+ preference.setOnPreferenceClickListener(null);
+ }
+ preference.setTitle(status);
+ preference.setSummary(subtitle);
+
+ View view = findViewById(R.id.status);
+ if(view != null)
+ view.setBackgroundColor(statusColor);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/astrid/plugin-src/com/todoroo/astrid/backup/BackupService.java b/astrid/plugin-src/com/todoroo/astrid/backup/BackupService.java
index e62a6bd4d..29cbad18c 100644
--- a/astrid/plugin-src/com/todoroo/astrid/backup/BackupService.java
+++ b/astrid/plugin-src/com/todoroo/astrid/backup/BackupService.java
@@ -13,11 +13,16 @@ import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
+import com.timsu.astrid.R;
+import com.todoroo.astrid.utility.Preferences;
+
/**
* Inspired heavily by SynchronizationService
*/
public class BackupService extends Service {
+ // --- constants for backup
+
/**
* when after phone starts to start first back up
*/
@@ -27,13 +32,10 @@ public class BackupService extends Service {
* how often to back up
*/
private static final long BACKUP_INTERVAL = AlarmManager.INTERVAL_DAY;
- public static final String BACKUP_ACTION = "backup";
- public static final String BACKUP_FILE_NAME_REGEX = "auto\\.[-\\d]+\\.xml";
+ public static final String BACKUP_ACTION = "backup"; //$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;
- static final String PREF_BACKUP_LAST_ERROR = "backupError";
- static final String PREF_BACKUP_LAST_DATE = "backupDate";
-
@Override
public IBinder onBind(Intent intent) {
return null;
@@ -48,66 +50,56 @@ public class BackupService extends Service {
/**
* Test hook for backup
- * @param ctx
+ * @param context
*/
- public void testBackup(Context ctx) {
- startBackup(ctx);
+ public void testBackup(Context context) {
+ startBackup(context);
}
- private void startBackup(Context ctx) {
- /*if (ctx == null || ctx.getResources() == null) {
+ private void startBackup(Context context) {
+ if (context == null || context.getResources() == null) {
return;
}
try {
- if (!Preferences.isBackupEnabled(ctx)) {
+ if (!Preferences.getBoolean(R.string.backup_BPr_auto_key, true)) {
return;
}
try {
deleteOldBackups();
} catch (Exception e) {
- Log.e("error-deleting", "Error deleting old backups: " + e);
+ Log.e("error-deleting", "Error deleting old backups", e); //$NON-NLS-1$ //$NON-NLS-2$
}
- TasksXmlExporter exporter = new TasksXmlExporter(true);
- exporter.setContext(ctx);
- exporter.exportTasks(backupDirectorySetting.getBackupDirectory());
- Preferences.setBackupSummary(ctx,
- ctx.getString(R.string.BPr_backup_desc_success,
- BackupDateUtilities.getFormattedDate(ctx, new Date())));
+
+ TasksXmlExporter.exportTasks(context, true, null);
+
} catch (Exception e) {
- // unable to backup.
- if (e == null || e.getMessage() == null) {
- Preferences.setBackupSummary(ctx,
- ctx.getString(R.string.BPr_backup_desc_failure_null));
- } else {
- Preferences.setBackupSummary(ctx,
- ctx.getString(R.string.BPr_backup_desc_failure,
- e.toString()));
- }
- }*/
+ Log.e("error-backup", "Error starting backups", e); //$NON-NLS-1$ //$NON-NLS-2$
+ Preferences.setString(BackupPreferences.PREF_BACKUP_LAST_ERROR, e.toString());
+ }
}
- public static void scheduleService(Context ctx) {
- /*AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
- PendingIntent pendingIntent = PendingIntent.getService(ctx, 0,
- createAlarmIntent(ctx), PendingIntent.FLAG_UPDATE_CURRENT);
+ public static void scheduleService(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.isBackupEnabled(ctx)) {
+ if (!Preferences.getBoolean(R.string.backup_BPr_auto_key, true)) {
return;
}
am.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis() + BACKUP_OFFSET,
- BACKUP_INTERVAL, pendingIntent);*/
+ BACKUP_INTERVAL, pendingIntent);
}
- public static void unscheduleService(Context ctx) {
- AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
- PendingIntent pendingIntent = PendingIntent.getService(ctx, 0,
- createAlarmIntent(ctx), PendingIntent.FLAG_UPDATE_CURRENT);
+ public static void unscheduleService(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);
}
- private static Intent createAlarmIntent(Context ctx) {
- Intent intent = new Intent(ctx, BackupService.class);
+ private static Intent createAlarmIntent(Context context) {
+ Intent intent = new Intent(context, BackupService.class);
intent.setAction(BACKUP_ACTION);
return intent;
}
diff --git a/astrid/plugin-src/com/todoroo/astrid/backup/BackupStartupReceiver.java b/astrid/plugin-src/com/todoroo/astrid/backup/BackupStartupReceiver.java
new file mode 100644
index 000000000..d19286a9d
--- /dev/null
+++ b/astrid/plugin-src/com/todoroo/astrid/backup/BackupStartupReceiver.java
@@ -0,0 +1,26 @@
+/**
+ * See the file "LICENSE" for the full license governing this code.
+ */
+package com.todoroo.astrid.backup;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.todoroo.andlib.service.ContextManager;
+import com.todoroo.astrid.service.AstridDependencyInjector;
+
+public class BackupStartupReceiver extends BroadcastReceiver {
+
+ static {
+ AstridDependencyInjector.initialize();
+ }
+
+ @Override
+ /** Called when device is restarted */
+ public void onReceive(final Context context, Intent intent) {
+ ContextManager.setContext(context);
+ BackupService.scheduleService(context);
+ }
+
+}
diff --git a/astrid/plugin-src/com/todoroo/astrid/backup/TasksXmlExporter.java b/astrid/plugin-src/com/todoroo/astrid/backup/TasksXmlExporter.java
index aac2f93fc..53ef05261 100644
--- a/astrid/plugin-src/com/todoroo/astrid/backup/TasksXmlExporter.java
+++ b/astrid/plugin-src/com/todoroo/astrid/backup/TasksXmlExporter.java
@@ -91,8 +91,9 @@ public class TasksXmlExporter {
String output = setupFile(BackupConstants.getExportDirectory(),
isService);
doTasksExport(output);
- Preferences.setLong(BackupService.PREF_BACKUP_LAST_DATE,
+ Preferences.setLong(BackupPreferences.PREF_BACKUP_LAST_DATE,
DateUtilities.now());
+ Preferences.setString(BackupPreferences.PREF_BACKUP_LAST_ERROR, null);
if (!isService)
displayToast(output);
@@ -102,7 +103,7 @@ public class TasksXmlExporter {
context.getString(R.string.backup_TXI_error), e);
else {
exceptionService.reportError("background-backup", e); //$NON-NLS-1$
- Preferences.setString(BackupService.PREF_BACKUP_LAST_ERROR, e.toString());
+ Preferences.setString(BackupPreferences.PREF_BACKUP_LAST_ERROR, e.toString());
}
} finally {
if(runAfterExport != null)
diff --git a/astrid/plugin-src/com/todoroo/astrid/locale/LocaleEditAlerts.java b/astrid/plugin-src/com/todoroo/astrid/locale/LocaleEditAlerts.java
index 8bcc9744a..220628589 100644
--- a/astrid/plugin-src/com/todoroo/astrid/locale/LocaleEditAlerts.java
+++ b/astrid/plugin-src/com/todoroo/astrid/locale/LocaleEditAlerts.java
@@ -154,6 +154,8 @@ public final class LocaleEditAlerts extends ExpandableListActivity {
adapter.setSelection(item);
} else if(item instanceof FilterCategory) {
Filter[] filters = ((FilterCategory)item).children;
+ if(filters == null)
+ return;
for(Filter filter : filters)
if(finalSelection.equals(filter.sqlQuery)) {
adapter.setSelection(filter);
@@ -243,7 +245,7 @@ public final class LocaleEditAlerts extends ExpandableListActivity {
/*
* This is the blurb concisely describing what your setting's state is. This is simply used for display in the UI.
*/
- if (filterItem.title.length() > com.twofortyfouram.Intent.MAXIMUM_BLURB_LENGTH)
+ if (filterItem.title != null && filterItem.title.length() > com.twofortyfouram.Intent.MAXIMUM_BLURB_LENGTH)
returnIntent.putExtra(com.twofortyfouram.Intent.EXTRA_STRING_BLURB, filterItem.title.substring(0, com.twofortyfouram.Intent.MAXIMUM_BLURB_LENGTH));
else
returnIntent.putExtra(com.twofortyfouram.Intent.EXTRA_STRING_BLURB, filterItem.title);
diff --git a/astrid/res/layout/rmilk_status_preference.xml b/astrid/res/layout/status_preference.xml
similarity index 100%
rename from astrid/res/layout/rmilk_status_preference.xml
rename to astrid/res/layout/status_preference.xml
diff --git a/astrid/res/values/strings-backup.xml b/astrid/res/values/strings-backup.xml
index 2fd48d9dc..fd6008da0 100644
--- a/astrid/res/values/strings-backup.xml
+++ b/astrid/res/values/strings-backup.xml
@@ -20,6 +20,37 @@