diff --git a/README.md b/README.md
index 9cb523948..4696a6b58 100644
--- a/README.md
+++ b/README.md
@@ -38,6 +38,12 @@ Getting Started With Development
9. Sign a [Contributors License Agreement](https://github.com/downloads/todoroo/astrid/Contributors%20Licensing%20Agreement.pdf) and send it to astrid AT todoroo.com
+Testing on a device - debugging
+---------------
+If you have trouble running Astrid on your device, it is recommended to:
+1. Fully uninstall Astrid from the device: adb uninstall com.timsu.astrid
+2. Restart Eclipse
+
Contributors workflow
---------------
diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml
index 7a3502b3b..6de167651 100644
--- a/astrid/AndroidManifest.xml
+++ b/astrid/AndroidManifest.xml
@@ -8,7 +8,7 @@
-
+
@@ -56,7 +56,7 @@
android:minSdkVersion="3" />
-
+
diff --git a/astrid/plugin-src/com/todoroo/astrid/core/CustomFilterAdapter.java b/astrid/plugin-src/com/todoroo/astrid/core/CustomFilterAdapter.java
index 14148baf4..07676f8fc 100644
--- a/astrid/plugin-src/com/todoroo/astrid/core/CustomFilterAdapter.java
+++ b/astrid/plugin-src/com/todoroo/astrid/core/CustomFilterAdapter.java
@@ -31,7 +31,7 @@ import com.todoroo.astrid.data.AddOn;
*
* @author Tim Su
*
- */
+ */
public class CustomFilterAdapter extends ArrayAdapter {
private final CustomFilterActivity activity;
diff --git a/astrid/src/com/todoroo/astrid/activity/EditPreferences.java b/astrid/src/com/todoroo/astrid/activity/EditPreferences.java
index 0bb80280c..cd32cbae5 100644
--- a/astrid/src/com/todoroo/astrid/activity/EditPreferences.java
+++ b/astrid/src/com/todoroo/astrid/activity/EditPreferences.java
@@ -13,8 +13,8 @@ import org.weloveastrid.rmilk.MilkUtilities;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
+import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@@ -22,9 +22,9 @@ import android.net.Uri;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
+import android.preference.Preference.OnPreferenceClickListener;
import android.widget.Toast;
import com.timsu.astrid.R;
@@ -39,6 +39,7 @@ import com.todoroo.andlib.widget.TodorooPreferences;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.data.Task;
+import com.todoroo.astrid.helper.MetadataHelper;
import com.todoroo.astrid.service.AddOnService;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.TaskService;
@@ -104,6 +105,9 @@ public class EditPreferences extends TodorooPreferences {
int length = resolveInfoList.size();
LinkedHashMap> categoryPreferences =
new LinkedHashMap>();
+
+ // Loop through a list of all packages (including plugins, addons)
+ // that have a settings action
for(int i = 0; i < length; i++) {
ResolveInfo resolveInfo = resolveInfoList.get(i);
Intent intent = new Intent(AstridApiConstants.ACTION_SETTINGS);
@@ -118,23 +122,7 @@ public class EditPreferences extends TodorooPreferences {
preference.setTitle(resolveInfo.activityInfo.loadLabel(pm));
preference.setIntent(intent);
- // category - either from metadata, or the application name
- String category = null;
- if(resolveInfo.activityInfo.metaData != null &&
- resolveInfo.activityInfo.metaData.containsKey(METADATA_CATEGORY)) {
- int resource = resolveInfo.activityInfo.metaData.getInt(METADATA_CATEGORY, -1);
- if(resource > -1) {
- try {
- category = pm.getResourcesForApplication(resolveInfo.activityInfo.applicationInfo).getString(resource);
- } catch (Exception e) {
- //
- }
- } else {
- category = resolveInfo.activityInfo.metaData.getString(METADATA_CATEGORY);
- }
- }
- if(category == null)
- category = resolveInfo.activityInfo.applicationInfo.loadLabel(pm).toString();
+ String category = MetadataHelper.resolveActivityCategoryName(resolveInfo, pm);
if(!categoryPreferences.containsKey(category))
categoryPreferences.put(category, new ArrayList());
diff --git a/astrid/src/com/todoroo/astrid/activity/TaskListActivity.java b/astrid/src/com/todoroo/astrid/activity/TaskListActivity.java
index 30d9b82d6..e2741a4c9 100644
--- a/astrid/src/com/todoroo/astrid/activity/TaskListActivity.java
+++ b/astrid/src/com/todoroo/astrid/activity/TaskListActivity.java
@@ -1,11 +1,12 @@
package com.todoroo.astrid.activity;
+import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
+import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicReference;
import android.app.AlertDialog;
@@ -29,28 +30,28 @@ import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnKeyListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.View.OnClickListener;
+import android.view.View.OnKeyListener;
import android.view.inputmethod.EditorInfo;
import android.widget.AbsListView;
-import android.widget.AbsListView.OnScrollListener;
-import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.TextView.OnEditorActionListener;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.Property;
@@ -78,6 +79,7 @@ import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.Task;
+import com.todoroo.astrid.helper.MetadataHelper;
import com.todoroo.astrid.helper.TaskListContextMenuExtensionLoader;
import com.todoroo.astrid.helper.TaskListContextMenuExtensionLoader.ContextMenuItem;
import com.todoroo.astrid.reminders.Notifications;
@@ -258,11 +260,9 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
item.setIcon(android.R.drawable.ic_menu_sort_by_size);
}
- if(syncActions.size() > 0) {
- item = menu.add(Menu.NONE, MENU_SYNC_ID, Menu.NONE,
- R.string.TLA_menu_sync);
- item.setIcon(R.drawable.ic_menu_refresh);
- }
+ item = menu.add(Menu.NONE, MENU_SYNC_ID, Menu.NONE,
+ R.string.TLA_menu_sync);
+ item.setIcon(R.drawable.ic_menu_refresh);
item = menu.add(Menu.NONE, MENU_HELP_ID, Menu.NONE,
R.string.TLA_menu_help);
@@ -348,6 +348,7 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
}
});
+
// set listener for showing quick add button if text not empty
quickAddButton = ((ImageButton)findViewById(R.id.quickAddButton));
quickAddBox.addTextChangedListener(new TextWatcher() {
@@ -841,10 +842,62 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
.show();
}
+ /**
+ * Intent object with custom label returned by toString.
+ * @author joshuagross
+ */
+ private class IntentWithLabel extends Intent {
+ private final String label;
+ public IntentWithLabel (Intent in, String labelIn) {
+ super(in);
+ label = labelIn;
+ }
+ @Override
+ public String toString () {
+ return label;
+ }
+ }
+
private void performSyncAction() {
- if(syncActions.size() == 0)
- return;
- if(syncActions.size() == 1) {
+ if (syncActions.size() == 0) {
+ String desiredCategory = getString(R.string.SyP_label);
+
+ // Get a list of all sync plugins and bring user to the prefs pane
+ // for one of them
+ Intent queryIntent = new Intent(AstridApiConstants.ACTION_SETTINGS);
+ PackageManager pm = getPackageManager();
+ List resolveInfoList = pm.queryIntentActivities(
+ queryIntent, PackageManager.GET_META_DATA);
+ int length = resolveInfoList.size();
+ ArrayList syncIntents = new ArrayList();
+
+ // Loop through a list of all packages (including plugins, addons)
+ // that have a settings action: filter to sync actions
+ for (int i = 0; i < length; i++) {
+ ResolveInfo resolveInfo = resolveInfoList.get(i);
+ Intent intent = new Intent(AstridApiConstants.ACTION_SETTINGS);
+ intent.setClassName(resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name);
+
+ String category = MetadataHelper.resolveActivityCategoryName(resolveInfo, pm);
+
+ if (category.equals(desiredCategory)) {
+ syncIntents.add(new IntentWithLabel(intent,
+ resolveInfo.activityInfo.loadLabel(pm).toString()));
+ }
+ }
+
+ final Intent[] actions = syncIntents.toArray(new Intent[syncIntents.size()]);
+ DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface click, int which) {
+ startActivity(actions[which]);
+ }
+ };
+
+ showSyncOptionMenu(actions, listener);
+ }
+ else if(syncActions.size() == 1) {
SyncAction syncAction = syncActions.iterator().next();
try {
syncAction.intent.send();
@@ -854,9 +907,9 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
//
}
} else {
+ // We have >1 sync actions, pop up a dialogue so the user can
+ // select just one of them (only sync one at a time)
final SyncAction[] actions = syncActions.toArray(new SyncAction[syncActions.size()]);
- ArrayAdapter adapter = new ArrayAdapter(this,
- android.R.layout.simple_spinner_dropdown_item, actions);
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface click, int which) {
@@ -869,16 +922,28 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
}
}
};
-
- // show a menu of available options
- new AlertDialog.Builder(this)
- .setTitle(R.string.SyP_label)
- .setAdapter(adapter, listener)
- .show().setOwnerActivity(this);
-
+ showSyncOptionMenu(actions, listener);
}
}
+ /**
+ * Show menu of sync options. This is shown when you're not logged into any services, or logged into
+ * more than one.
+ * @param
+ * @param items
+ * @param listener
+ */
+ private void showSyncOptionMenu(TYPE[] items, DialogInterface.OnClickListener listener) {
+ ArrayAdapter adapter = new ArrayAdapter(this,
+ android.R.layout.simple_spinner_dropdown_item, items);
+
+ // show a menu of available options
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.SyP_label)
+ .setAdapter(adapter, listener)
+ .show().setOwnerActivity(this);
+ }
+
@Override
public boolean onMenuItemSelected(int featureId, final MenuItem item) {
Intent intent;
@@ -904,7 +969,7 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
return true;
case MENU_HELP_ID:
intent = new Intent(Intent.ACTION_VIEW,
- Uri.parse("http://weloveastrid.com/help-user-guide-astrid-v3/active-tasks/")); //$NON-NLS-1$
+ Uri.parse("http://weloveastrid.com/help-user-guide-astrid-v3/active-tasks/"));
startActivity(intent);
return true;
case MENU_ADDON_INTENT_ID:
@@ -966,21 +1031,21 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
if(time == 0 || time == Long.MAX_VALUE)
return;
- Toast.makeText(TaskListActivity.this, "Scheduled Alarm: " + //$NON-NLS-1$
+ Toast.makeText(TaskListActivity.this, "Scheduled Alarm: " +
new Date(time), Toast.LENGTH_LONG).show();
ReminderService.getInstance().setScheduler(null);
}
});
ReminderService.getInstance().scheduleAlarm(task);
if(ReminderService.getInstance().getScheduler() != null)
- Toast.makeText(this, "No alarms", Toast.LENGTH_LONG).show(); //$NON-NLS-1$
+ Toast.makeText(this, "No alarms", Toast.LENGTH_LONG).show();
ReminderService.getInstance().setScheduler(original);
return true;
}
case CONTEXT_MENU_DEBUG + 1: {
itemId = item.getGroupId();
- new Notifications().showTaskNotification(itemId, 0, "test reminder"); //$NON-NLS-1$
+ new Notifications().showTaskNotification(itemId, 0, "test reminder");
return true;
}
diff --git a/astrid/src/com/todoroo/astrid/helper/MetadataHelper.java b/astrid/src/com/todoroo/astrid/helper/MetadataHelper.java
new file mode 100644
index 000000000..830830827
--- /dev/null
+++ b/astrid/src/com/todoroo/astrid/helper/MetadataHelper.java
@@ -0,0 +1,38 @@
+package com.todoroo.astrid.helper;
+
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+/**
+ * @author joshuagross
+ */
+public class MetadataHelper {
+ public static String resolveActivityCategoryName (ResolveInfo resolveInfo, PackageManager pm) {
+ // category - either from metadata, or the application name
+ String category = null;
+ String categoryKey = "category";
+ if (resolveInfo.activityInfo.metaData != null && resolveInfo.activityInfo.metaData.containsKey(categoryKey)) {
+ int resource = resolveInfo.activityInfo.metaData.getInt(
+ categoryKey, -1);
+ if (resource > -1) {
+ // category stored as integer in Manifest
+ try {
+ category = pm.getResourcesForApplication(
+ resolveInfo.activityInfo.applicationInfo).getString(
+ resource);
+ } catch (Exception e) {
+ //
+ }
+ } else {
+ // category stored as String in Manifest
+ category = resolveInfo.activityInfo.metaData.getString(categoryKey);
+ }
+ }
+ // If category is null at this point, we use the name of the application this activity is found in
+ if (category == null) {
+ category = resolveInfo.activityInfo.applicationInfo.loadLabel(pm).toString();
+ }
+
+ return category;
+ }
+}