Fixed the Blade-filterlist bug.

I implemented the workaround as Tim suggested by introducing the new interface
AstridFilterExposer and used it in the FilterAdapter-class. Additionally, I
had to introduce a fallback resultReceiver that is called after the last
filterexposer finished and checks if the filterlist-screen is empty. In this
case it uses a pre-fetched lists of Astrids registered receivers for filters
and uses the new interface on them to get the FilterListItem-instances.
pull/14/head
Arne Jans 14 years ago
parent b078d7dcc8
commit 6d763da7eb

@ -0,0 +1,13 @@
/**
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.api;
/**
* Common interface for Astrids filter-exposers to provide their {@link FilterListitem}-instances.
*
* @author Arne Jans
*/
public interface AstridFilterExposer {
public FilterListItem[] getFilters();
}

@ -16,6 +16,7 @@ import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.astrid.activity.FilterListActivity;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.AstridFilterExposer;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
@ -30,13 +31,20 @@ import com.todoroo.astrid.tags.TagService;
* @author Tim Su <tim@todoroo.com>
*
*/
public final class CoreFilterExposer extends BroadcastReceiver {
public final class CoreFilterExposer extends BroadcastReceiver implements AstridFilterExposer {
@Override
public void onReceive(Context context, Intent intent) {
Resources r = context.getResources();
ContextManager.setContext(context);
FilterListItem[] list = prepareFilters(r);
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private FilterListItem[] prepareFilters(Resources r) {
// core filters
Filter inbox = buildInboxFilter(r);
@ -44,9 +52,7 @@ public final class CoreFilterExposer extends BroadcastReceiver {
// transmit filter list
FilterListItem[] list = new FilterListItem[1];
list[0] = inbox;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
return list;
}
/**
@ -65,4 +71,13 @@ public final class CoreFilterExposer extends BroadcastReceiver {
return inbox;
}
@Override
public FilterListItem[] getFilters() {
if (ContextManager.getContext() == null || ContextManager.getContext().getResources() == null)
return null;
Resources r = ContextManager.getContext().getResources();
return prepareFilters(r);
}
}

@ -16,6 +16,7 @@ import android.os.Bundle;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Order;
@ -25,6 +26,7 @@ import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.activity.FilterListActivity;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.AstridFilterExposer;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategoryWithNewButton;
import com.todoroo.astrid.api.FilterListItem;
@ -40,13 +42,22 @@ import com.todoroo.astrid.data.Task;
* @author Tim Su <tim@todoroo.com>
*
*/
public final class CustomFilterExposer extends BroadcastReceiver {
public final class CustomFilterExposer extends BroadcastReceiver implements AstridFilterExposer {
private static final String TOKEN_FILTER_ID = "id"; //$NON-NLS-1$
private static final String TOKEN_FILTER_NAME = "name"; //$NON-NLS-1$
@Override
public void onReceive(Context context, Intent intent) {
FilterListItem[] list = prepareFilters(context);
// transmit filter list
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private FilterListItem[] prepareFilters(Context context) {
Resources r = context.getResources();
PendingIntent customFilterIntent = PendingIntent.getActivity(context, 0,
@ -61,11 +72,7 @@ public final class CustomFilterExposer extends BroadcastReceiver {
FilterListItem[] list = new FilterListItem[1];
list[0] = heading;
// transmit filter list
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
return list;
}
private Filter[] buildSavedFilters(Context context, Resources r) {
@ -158,4 +165,12 @@ public final class CustomFilterExposer extends BroadcastReceiver {
}
}
@Override
public FilterListItem[] getFilters() {
if (ContextManager.getContext() == null)
return null;
return prepareFilters(ContextManager.getContext());
}
}

@ -22,6 +22,7 @@ import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.AstridFilterExposer;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategoryWithNewButton;
import com.todoroo.astrid.api.FilterListItem;
@ -40,7 +41,7 @@ import com.todoroo.astrid.service.AstridDependencyInjector;
* @author Tim Su <tim@todoroo.com>
*
*/
public class GtasksFilterExposer extends BroadcastReceiver {
public class GtasksFilterExposer extends BroadcastReceiver implements AstridFilterExposer {
@Autowired private GtasksListService gtasksListService;
@Autowired private GtasksPreferenceService gtasksPreferenceService;
@ -75,17 +76,25 @@ public class GtasksFilterExposer extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ContextManager.setContext(context);
FilterListItem[] list = prepareFilters(context);
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, GtasksPreferenceService.IDENTIFIER);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private FilterListItem[] prepareFilters(Context context) {
DependencyInjectionService.getInstance().inject(this);
// if we aren't logged in, don't expose features
if(!gtasksPreferenceService.isLoggedIn())
return;
return null;
lists = gtasksListService.getLists();
// If user does not have any lists, don't show this section at all
if(noListsToShow())
return;
return null;
Filter[] listFilters = new Filter[lists.length];
for(int i = 0; i < lists.length; i++)
@ -99,14 +108,19 @@ public class GtasksFilterExposer extends BroadcastReceiver {
// transmit filter list
FilterListItem[] list = new FilterListItem[1];
list[0] = listsCategory;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, GtasksPreferenceService.IDENTIFIER);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
return list;
}
private boolean noListsToShow() {
return lists.length == 0;
}
@Override
public FilterListItem[] getFilters() {
if (ContextManager.getContext() == null)
return null;
return prepareFilters(ContextManager.getContext());
}
}

@ -16,6 +16,7 @@ import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.AstridFilterExposer;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategory;
import com.todoroo.astrid.api.FilterListHeader;
@ -35,7 +36,7 @@ import com.todoroo.astrid.producteev.sync.ProducteevUser;
* @author Arne Jans <arne.jans@gmail.com>
*
*/
public class ProducteevFilterExposer extends BroadcastReceiver {
public class ProducteevFilterExposer extends BroadcastReceiver implements AstridFilterExposer {
/**
* @param context
@ -113,15 +114,24 @@ public class ProducteevFilterExposer extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ContextManager.setContext(context);
FilterListItem[] list = prepareFilters(context);
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, ProducteevUtilities.IDENTIFIER);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private FilterListItem[] prepareFilters(Context context) {
// if we aren't logged in, don't expose features
if(!ProducteevUtilities.INSTANCE.isLoggedIn())
return;
return null;
StoreObject[] dashboards = ProducteevDataService.getInstance().getDashboards();
// If user does not have any dashboards, don't show this section at all
if(dashboards.length == 0)
return;
return null;
FilterListHeader producteevHeader = new FilterListHeader(context.getString(R.string.producteev_FEx_header));
@ -157,10 +167,7 @@ public class ProducteevFilterExposer extends BroadcastReceiver {
list[1] = producteevDashboards;
list[2] = producteevUsersByMeCategory;
list[3] = producteevUsersByOthersCategory;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, ProducteevUtilities.IDENTIFIER);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
return list;
}
/**
@ -177,4 +184,12 @@ public class ProducteevFilterExposer extends BroadcastReceiver {
return users;
}
@Override
public FilterListItem[] getFilters() {
if (ContextManager.getContext() == null)
return null;
return prepareFilters(ContextManager.getContext());
}
}

@ -30,6 +30,7 @@ import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.actfm.TagViewActivity;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.AstridFilterExposer;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategory;
import com.todoroo.astrid.api.FilterCategoryWithNewButton;
@ -51,7 +52,7 @@ import com.todoroo.astrid.tags.TagService.Tag;
* @author Tim Su <tim@todoroo.com>
*
*/
public class TagFilterExposer extends BroadcastReceiver {
public class TagFilterExposer extends BroadcastReceiver implements AstridFilterExposer {
private static final String TAG = "tag"; //$NON-NLS-1$
@ -115,6 +116,15 @@ public class TagFilterExposer extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
FilterListItem[] listAsArray = prepareFilters(context);
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, listAsArray);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, TagsPlugin.IDENTIFIER);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private FilterListItem[] prepareFilters(Context context) {
DependencyInjectionService.getInstance().inject(this);
ContextManager.setContext(context);
tagService = TagService.getInstance();
@ -126,10 +136,7 @@ public class TagFilterExposer extends BroadcastReceiver {
// transmit filter list
FilterListItem[] listAsArray = list.toArray(new FilterListItem[list.size()]);
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, listAsArray);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, TagsPlugin.IDENTIFIER);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
return listAsArray;
}
private void addTags(ArrayList<FilterListItem> list) {
@ -292,4 +299,12 @@ public class TagFilterExposer extends BroadcastReceiver {
}
}
@Override
public FilterListItem[] getFilters() {
if (ContextManager.getContext() == null)
return null;
return prepareFilters(ContextManager.getContext());
}
}

@ -16,6 +16,7 @@ import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.astrid.activity.FilterListActivity;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.AstridFilterExposer;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.core.PluginServices;
@ -27,23 +28,29 @@ import com.todoroo.astrid.data.Task;
* @author Tim Su <tim@todoroo.com>
*
*/
public final class TimerFilterExposer extends BroadcastReceiver {
public final class TimerFilterExposer extends BroadcastReceiver implements AstridFilterExposer {
@Override
public void onReceive(Context context, Intent intent) {
ContextManager.setContext(context);
FilterListItem[] list = prepareFilters(context);
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private FilterListItem[] prepareFilters(Context context) {
if(PluginServices.getTaskService().count(Query.select(Task.ID).
where(Task.TIMER_START.gt(0))) == 0)
return;
return null;
Filter workingOn = createFilter(context);
// transmit filter list
FilterListItem[] list = new FilterListItem[1];
list[0] = workingOn;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
return list;
}
public static Filter createFilter(Context context) {
@ -58,4 +65,12 @@ public final class TimerFilterExposer extends BroadcastReceiver {
return workingOn;
}
@Override
public FilterListItem[] getFilters() {
if (ContextManager.getContext() == null)
return null;
return prepareFilters(ContextManager.getContext());
}
}

@ -6,6 +6,7 @@ package com.todoroo.astrid.adapter;
import greendroid.widget.AsyncImageView;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@ -17,9 +18,12 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.BadParcelableException;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextUtils;
@ -38,10 +42,12 @@ import android.widget.TextView;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.activity.FilterListActivity;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.AstridFilterExposer;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategory;
import com.todoroo.astrid.api.FilterCategoryWithNewButton;
@ -49,9 +55,20 @@ import com.todoroo.astrid.api.FilterListHeader;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.api.FilterWithUpdate;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.utility.Constants;
public class FilterAdapter extends BaseExpandableListAdapter {
private static List<ResolveInfo> filterExposerList;
static {
// query astrids AndroidManifest.xml for all registered default-receivers to expose filters
PackageManager pm = ContextManager.getContext().getPackageManager();
filterExposerList = pm.queryBroadcastReceivers(
new Intent(AstridApiConstants.BROADCAST_REQUEST_FILTERS),
PackageManager.MATCH_DEFAULT_ONLY);
}
// --- style constants
public int filterStyle = R.style.TextAppearance_FLA_Filter;
@ -76,6 +93,7 @@ public class FilterAdapter extends BaseExpandableListAdapter {
/** receiver for new filters */
private final FilterReceiver filterReceiver = new FilterReceiver();
private final BladeFilterReceiver bladeFilterReceiver = new BladeFilterReceiver();
/** row layout to inflate */
private final int layout;
@ -309,10 +327,38 @@ public class FilterAdapter extends BaseExpandableListAdapter {
public class FilterReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Constants.DEBUG_BLADE) {
// emulate the bug in the zte blade to not load the parcelable-array due to classloader-problems
try {
// normally caused by (with another message of course):
// final Parcelable[] filters = extras.getParcelableArray(AstridApiConstants.EXTRAS_RESPONSE);
throw new BadParcelableException(new ClassNotFoundException("ZTE Blade debug test!"));
} catch (Exception e) {
Log.e("receive-filter-" + //$NON-NLS-1$
intent.getStringExtra(AstridApiConstants.EXTRAS_ADDON),
e.toString(), e);
}
// setResultCode(Activity.RESULT_OK);
return;
}
try {
Bundle extras = intent.getExtras();
extras.setClassLoader(FilterListHeader.class.getClassLoader());
final Parcelable[] filters = extras.getParcelableArray(AstridApiConstants.EXTRAS_RESPONSE);
populateFiltersToAdapter(filters);
} catch (Exception e) {
Log.e("receive-filter-" + //$NON-NLS-1$
intent.getStringExtra(AstridApiConstants.EXTRAS_ADDON),
e.toString(), e);
}
}
protected void populateFiltersToAdapter(final Parcelable[] filters) {
if (filters == null)
return;
for (Parcelable item : filters) {
FilterListItem filter = (FilterListItem) item;
if(skipIntentFilters && !(filter instanceof Filter ||
@ -331,13 +377,41 @@ public class FilterAdapter extends BaseExpandableListAdapter {
expandList(filters);
}
});
}
}
/**
* Receiver which gets called after the FilterReceiver
* and checks if the filters are populated.
* If they aren't (e.g. due to the bug in the ZTE Blade's Parcelable-system throwing a
* ClassNotFoundExeption), the filters are fetched manually.
*
* @author Arne Jans <arne@astrid.com>
*
*/
public class BladeFilterReceiver extends FilterReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (getGroupCount() == 0 && filterExposerList != null && filterExposerList.size()>0) {
try {
for (ResolveInfo filterExposerInfo : filterExposerList) {
Log.d("BladeFilterReceiver", filterExposerInfo.toString());
String className = filterExposerInfo.activityInfo.name;
AstridFilterExposer filterExposer = null;
filterExposer = (AstridFilterExposer) Class.forName(className, true, FilterAdapter.class.getClassLoader()).newInstance();
if (filterExposer != null) {
populateFiltersToAdapter(filterExposer.getFilters());
}
}
} catch (Exception e) {
Log.e("receive-filter-" + //$NON-NLS-1$
Log.e("receive-bladefilter-" + //$NON-NLS-1$
intent.getStringExtra(AstridApiConstants.EXTRAS_ADDON),
e.toString(), e);
}
}
}
}
/**
* Expand the category filters in this group according to preference
@ -377,7 +451,15 @@ public class FilterAdapter extends BaseExpandableListAdapter {
*/
public void getLists() {
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_REQUEST_FILTERS);
activity.sendOrderedBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
// activity.sendOrderedBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
// the bladeFilterReceiver will be called after the usual FilterReceiver has finished (to handle the empty list)
activity.sendOrderedBroadcast(broadcastIntent,
AstridApiConstants.PERMISSION_READ,
bladeFilterReceiver,
null,
Activity.RESULT_OK,
null,
null);
}
/**
@ -386,6 +468,8 @@ public class FilterAdapter extends BaseExpandableListAdapter {
public void registerRecevier() {
activity.registerReceiver(filterReceiver,
new IntentFilter(AstridApiConstants.BROADCAST_SEND_FILTERS));
activity.registerReceiver(bladeFilterReceiver,
new IntentFilter(AstridApiConstants.BROADCAST_SEND_FILTERS));
if(getGroupCount() == 0)
getLists();
}
@ -395,6 +479,7 @@ public class FilterAdapter extends BaseExpandableListAdapter {
*/
public void unregisterRecevier() {
activity.unregisterReceiver(filterReceiver);
activity.unregisterReceiver(bladeFilterReceiver);
}
/**

@ -36,6 +36,12 @@ public final class Constants {
*/
public static final boolean DEBUG = false;
/**
* Whether to turn on debugging for an emulated zte blade error (in the FilterReceiver)
* Only for testing purposes. Remember to set this to false for a standard release!
*/
public static final boolean DEBUG_BLADE = false;
/**
* Astrid Help URL
*/

Loading…
Cancel
Save