From f9e00f72a0dfeea3e5b9db8a522f7251e158dc7d Mon Sep 17 00:00:00 2001 From: daniel oeh Date: Sun, 24 Feb 2013 12:30:23 +0100 Subject: [PATCH] limited access to feed items, feeds, playback history and download log --- .../activity/DownloadLogActivity.java | 2 +- .../antennapod/activity/MainActivity.java | 2 +- .../activity/PreferenceActivity.java | 2 +- .../adapter/AbstractFeedItemlistAdapter.java | 48 +++++++------ .../adapter/DownloadLogAdapter.java | 36 +++++++--- .../adapter/FeedItemlistAdapter.java | 16 +++-- .../antennapod/adapter/FeedlistAdapter.java | 32 +++++++-- .../asynctask/OpmlExportWorker.java | 3 +- src/de/danoeh/antennapod/feed/Feed.java | 67 +++++++++++++------ .../danoeh/antennapod/feed/FeedManager.java | 45 +++++++++++-- .../antennapod/fragment/FeedlistFragment.java | 13 ++-- .../antennapod/fragment/ItemlistFragment.java | 44 +++++++----- .../fragment/PlaybackHistoryFragment.java | 16 ++++- .../preferences/UserPreferences.java | 31 +++++---- .../service/download/DownloadService.java | 2 +- .../antennapod/storage/PodDBAdapter.java | 4 +- .../syndication/handler/HandlerState.java | 36 ++++++---- .../syndication/handler/SyndHandler.java | 6 ++ .../syndication/namespace/NSRSS20.java | 2 +- .../syndication/namespace/atom/NSAtom.java | 2 +- .../util/menuhandler/FeedMenuHandler.java | 2 +- .../antennapod/test/FeedHandlerTest.java | 6 +- 22 files changed, 276 insertions(+), 141 deletions(-) diff --git a/src/de/danoeh/antennapod/activity/DownloadLogActivity.java b/src/de/danoeh/antennapod/activity/DownloadLogActivity.java index 535f585db..e8a75e9cd 100644 --- a/src/de/danoeh/antennapod/activity/DownloadLogActivity.java +++ b/src/de/danoeh/antennapod/activity/DownloadLogActivity.java @@ -30,7 +30,7 @@ public class DownloadLogActivity extends SherlockListActivity { super.onCreate(savedInstanceState); manager = FeedManager.getInstance(); - dla = new DownloadLogAdapter(this, 0, manager.getDownloadLog()); + dla = new DownloadLogAdapter(this); getSupportActionBar().setDisplayHomeAsUpEnabled(true); setListAdapter(dla); } diff --git a/src/de/danoeh/antennapod/activity/MainActivity.java b/src/de/danoeh/antennapod/activity/MainActivity.java index abdd53fd7..a8032e2a5 100644 --- a/src/de/danoeh/antennapod/activity/MainActivity.java +++ b/src/de/danoeh/antennapod/activity/MainActivity.java @@ -151,7 +151,7 @@ public class MainActivity extends SherlockFragmentActivity { refreshAll.setVisible(true); } - boolean hasFeeds = !manager.getFeeds().isEmpty(); + boolean hasFeeds = manager.getFeedsSize() > 0; menu.findItem(R.id.all_feed_refresh).setVisible(hasFeeds); return true; } diff --git a/src/de/danoeh/antennapod/activity/PreferenceActivity.java b/src/de/danoeh/antennapod/activity/PreferenceActivity.java index 10888209a..360ff610d 100644 --- a/src/de/danoeh/antennapod/activity/PreferenceActivity.java +++ b/src/de/danoeh/antennapod/activity/PreferenceActivity.java @@ -82,7 +82,7 @@ public class PreferenceActivity extends SherlockPreferenceActivity { @Override public boolean onPreferenceClick(Preference preference) { - if (!FeedManager.getInstance().getFeeds().isEmpty()) { + if (FeedManager.getInstance().getFeedsSize() > 0) { new OpmlExportWorker(PreferenceActivity.this) .executeAsync(); } diff --git a/src/de/danoeh/antennapod/adapter/AbstractFeedItemlistAdapter.java b/src/de/danoeh/antennapod/adapter/AbstractFeedItemlistAdapter.java index 74b54c105..6f4cf7c29 100644 --- a/src/de/danoeh/antennapod/adapter/AbstractFeedItemlistAdapter.java +++ b/src/de/danoeh/antennapod/adapter/AbstractFeedItemlistAdapter.java @@ -1,41 +1,39 @@ package de.danoeh.antennapod.adapter; -import java.util.List; - -import android.content.Context; -import android.widget.ArrayAdapter; -import de.danoeh.antennapod.PodcastApp; +import android.widget.BaseAdapter; import de.danoeh.antennapod.feed.FeedItem; -import de.danoeh.antennapod.preferences.UserPreferences; -import de.danoeh.antennapod.util.EpisodeFilter; -public abstract class AbstractFeedItemlistAdapter extends - ArrayAdapter { +public abstract class AbstractFeedItemlistAdapter extends BaseAdapter { - private List objects; + ItemAccess itemAccess; - public AbstractFeedItemlistAdapter(Context context, int textViewResourceId, - List objects) { - super(context, textViewResourceId, objects); - this.objects = objects; + public AbstractFeedItemlistAdapter(ItemAccess itemAccess) { + super(); + if (itemAccess == null) { + throw new IllegalArgumentException("itemAccess must not be null"); + } + this.itemAccess = itemAccess; } @Override public int getCount() { - if (UserPreferences.isDisplayOnlyEpisodes()) { - return EpisodeFilter.countItemsWithEpisodes(objects); - } else { - return super.getCount(); - } - + return itemAccess.getCount(); + + } + + @Override + public long getItemId(int position) { + return position; } @Override public FeedItem getItem(int position) { - if (UserPreferences.isDisplayOnlyEpisodes()) { - return EpisodeFilter.accessEpisodeByIndex(objects, position); - } else { - return super.getItem(position); - } + return itemAccess.getItem(position); + } + + public static interface ItemAccess { + int getCount(); + + FeedItem getItem(int position); } } diff --git a/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java index ce339be88..c0ccdc7fe 100644 --- a/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java +++ b/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java @@ -1,39 +1,40 @@ package de.danoeh.antennapod.adapter; import java.text.DateFormat; -import java.util.List; import android.content.Context; import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; +import android.widget.BaseAdapter; import android.widget.TextView; import de.danoeh.antennapod.R; import de.danoeh.antennapod.asynctask.DownloadStatus; import de.danoeh.antennapod.feed.Feed; -import de.danoeh.antennapod.feed.FeedFile; import de.danoeh.antennapod.feed.FeedImage; +import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.feed.FeedMedia; import de.danoeh.antennapod.util.DownloadError; /** Displays a list of DownloadStatus entries. */ -public class DownloadLogAdapter extends ArrayAdapter { +public class DownloadLogAdapter extends BaseAdapter { - public DownloadLogAdapter(Context context, int textViewResourceId, - List objects) { - super(context, textViewResourceId, objects); + private Context context; + private FeedManager manager = FeedManager.getInstance(); + + public DownloadLogAdapter(Context context) { + super(); + this.context = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { Holder holder; DownloadStatus status = getItem(position); - FeedFile feedfile = status.getFeedFile(); if (convertView == null) { holder = new Holder(); - LayoutInflater inflater = (LayoutInflater) getContext() + LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.downloadlog_item, null); holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); @@ -71,7 +72,7 @@ public class DownloadLogAdapter extends ArrayAdapter { holder.successful.setTextColor(convertView.getResources().getColor( R.color.download_failed_red)); holder.successful.setText(R.string.download_failed); - String reasonText = DownloadError.getErrorString(getContext(), + String reasonText = DownloadError.getErrorString(context, status.getReason()); if (status.getReasonDetailed() != null) { reasonText += ": " + status.getReasonDetailed(); @@ -91,4 +92,19 @@ public class DownloadLogAdapter extends ArrayAdapter { TextView reason; } + @Override + public int getCount() { + return manager.getDownloadLogSize(); + } + + @Override + public DownloadStatus getItem(int position) { + return manager.getDownloadStatusFromLogAtIndex(position); + } + + @Override + public long getItemId(int position) { + return position; + } + } diff --git a/src/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/src/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java index b03dd0c1f..3b5fed7b5 100644 --- a/src/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java +++ b/src/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java @@ -23,16 +23,20 @@ import de.danoeh.antennapod.util.Converter; import de.danoeh.antennapod.util.ThemeUtils; public class FeedItemlistAdapter extends AbstractFeedItemlistAdapter { + + private Context context; + private ActionButtonCallback callback; private boolean showFeedtitle; private int selectedItemIndex; public static final int SELECTION_NONE = -1; - public FeedItemlistAdapter(Context context, int textViewResourceId, - List objects, ActionButtonCallback callback, - boolean showFeedtitle) { - super(context, textViewResourceId, objects); + public FeedItemlistAdapter(Context context, + AbstractFeedItemlistAdapter.ItemAccess itemAccess, + ActionButtonCallback callback, boolean showFeedtitle) { + super(itemAccess); + this.context = context; this.callback = callback; this.showFeedtitle = showFeedtitle; this.selectedItemIndex = SELECTION_NONE; @@ -45,7 +49,7 @@ public class FeedItemlistAdapter extends AbstractFeedItemlistAdapter { if (convertView == null) { holder = new Holder(); - LayoutInflater inflater = (LayoutInflater) getContext() + LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.feeditemlist_item, null); holder.title = (TextView) convertView @@ -160,7 +164,7 @@ public class FeedItemlistAdapter extends AbstractFeedItemlistAdapter { holder.downloading.setVisibility(View.GONE); } - TypedArray typeDrawables = getContext().obtainStyledAttributes( + TypedArray typeDrawables = context.obtainStyledAttributes( new int[] { R.attr.type_audio, R.attr.type_video }); MediaType mediaType = item.getMedia().getMediaType(); if (mediaType == MediaType.AUDIO) { diff --git a/src/de/danoeh/antennapod/adapter/FeedlistAdapter.java b/src/de/danoeh/antennapod/adapter/FeedlistAdapter.java index f89f2854a..09284ab49 100644 --- a/src/de/danoeh/antennapod/adapter/FeedlistAdapter.java +++ b/src/de/danoeh/antennapod/adapter/FeedlistAdapter.java @@ -9,24 +9,29 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; +import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import de.danoeh.antennapod.R; import de.danoeh.antennapod.asynctask.FeedImageLoader; import de.danoeh.antennapod.feed.Feed; +import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.storage.DownloadRequester; import de.danoeh.antennapod.util.ThemeUtils; -public class FeedlistAdapter extends ArrayAdapter { +public class FeedlistAdapter extends BaseAdapter { private static final String TAG = "FeedlistAdapter"; + private Context context; + private FeedManager manager = FeedManager.getInstance(); + private int selectedItemIndex; private FeedImageLoader imageLoader; public static final int SELECTION_NONE = -1; - public FeedlistAdapter(Context context, int textViewResourceId, - List objects) { - super(context, textViewResourceId, objects); + public FeedlistAdapter(Context context) { + super(); + this.context = context; selectedItemIndex = SELECTION_NONE; imageLoader = FeedImageLoader.getInstance(); } @@ -39,7 +44,7 @@ public class FeedlistAdapter extends ArrayAdapter { // Inflate Layout if (convertView == null) { holder = new Holder(); - LayoutInflater inflater = (LayoutInflater) getContext() + LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.feedlist_item, null); @@ -83,7 +88,7 @@ public class FeedlistAdapter extends ArrayAdapter { .getTime(), System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.SHORT)); } - holder.numberOfEpisodes.setText(feed.getNumOfItems() + holder.numberOfEpisodes.setText(feed.getNumOfItems(true) + convertView.getResources() .getString(R.string.episodes_suffix)); @@ -136,4 +141,19 @@ public class FeedlistAdapter extends ArrayAdapter { notifyDataSetChanged(); } + @Override + public int getCount() { + return manager.getFeedsSize(); + } + + @Override + public Feed getItem(int position) { + return manager.getFeedAtIndex(position); + } + + @Override + public long getItemId(int position) { + return position; + } + } diff --git a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java index 5f26e900e..978f53ac6 100644 --- a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java +++ b/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.asynctask; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.Arrays; import android.annotation.SuppressLint; import android.app.AlertDialog; @@ -50,7 +51,7 @@ public class OpmlExportWorker extends AsyncTask { } try { FileWriter writer = new FileWriter(output); - opmlWriter.writeDocument(FeedManager.getInstance().getFeeds(), + opmlWriter.writeDocument(Arrays.asList(FeedManager.getInstance().getFeedsArray()), writer); writer.close(); } catch (IOException e) { diff --git a/src/de/danoeh/antennapod/feed/Feed.java b/src/de/danoeh/antennapod/feed/Feed.java index ed5d49dbd..64e6fc4d8 100644 --- a/src/de/danoeh/antennapod/feed/Feed.java +++ b/src/de/danoeh/antennapod/feed/Feed.java @@ -1,13 +1,16 @@ package de.danoeh.antennapod.feed; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import android.content.SyncResult; import android.preference.PreferenceManager; import de.danoeh.antennapod.PodcastApp; import de.danoeh.antennapod.preferences.UserPreferences; +import de.danoeh.antennapod.util.EpisodeFilter; /** * Data Object for a whole feed @@ -40,7 +43,7 @@ public class Feed extends FeedFile { public Feed(Date lastUpdate) { super(); - items = new CopyOnWriteArrayList(); + items = Collections.synchronizedList(new ArrayList()); this.lastUpdate = lastUpdate; } @@ -71,7 +74,8 @@ public class Feed extends FeedFile { int count = 0; for (FeedItem item : items) { if (item.getState() == FeedItem.State.NEW) { - if (!UserPreferences.isDisplayOnlyEpisodes() || item.getMedia() != null) { + if (!UserPreferences.isDisplayOnlyEpisodes() + || item.getMedia() != null) { count++; } } @@ -97,14 +101,18 @@ public class Feed extends FeedFile { } /** - * Returns true if at least one item in the itemlist is unread.If the - * 'display only episodes' - preference is set to true, this method will - * only count items with episodes. + * Returns true if at least one item in the itemlist is unread. + * + * @param enableEpisodeFilter + * true if this method should only count items with episodes if + * the 'display only episodes' - preference is set to true by the + * user. */ - public boolean hasNewItems() { + public boolean hasNewItems(boolean enableEpisodeFilter) { for (FeedItem item : items) { if (item.getState() == FeedItem.State.NEW) { - if (!UserPreferences.isDisplayOnlyEpisodes() || item.getMedia() != null) { + if (!(enableEpisodeFilter && UserPreferences + .isDisplayOnlyEpisodes()) || item.getMedia() != null) { return true; } } @@ -113,18 +121,34 @@ public class Feed extends FeedFile { } /** - * Returns the number of FeedItems. If the 'display only episodes' - - * preference is set to true, this method will only count items with - * episodes. + * Returns the number of FeedItems. + * + * @param enableEpisodeFilter + * true if this method should only count items with episodes if + * the 'display only episodes' - preference is set to true by the + * user. * */ - public int getNumOfItems() { - int count = 0; - for (FeedItem item : items) { - if (!UserPreferences.isDisplayOnlyEpisodes() || item.getMedia() != null) { - count++; - } + public int getNumOfItems(boolean enableEpisodeFilter) { + if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) { + return EpisodeFilter.countItemsWithEpisodes(items); + } else { + return items.size(); + } + } + + /** + * Returns the item at the specified index. + * + * @param enableEpisodeFilter + * true if this method should ignore items without episdodes if + * the episodes filter has been enabled by the user. + */ + public FeedItem getItemAtIndex(boolean enableEpisodeFilter, int position) { + if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) { + return EpisodeFilter.accessEpisodeByIndex(items, position); + } else { + return items.get(position); } - return count; } /** @@ -264,12 +288,17 @@ public class Feed extends FeedFile { this.image = image; } - public List getItems() { + List getItems() { return items; } public void setItems(ArrayList items) { - this.items = items; + this.items = Collections.synchronizedList(items); + } + + /** Returns an array that contains all the feeditems of this feed. */ + public FeedItem[] getItemsArray() { + return items.toArray(new FeedItem[items.size()]); } public Date getLastUpdate() { diff --git a/src/de/danoeh/antennapod/feed/FeedManager.java b/src/de/danoeh/antennapod/feed/FeedManager.java index 6a8ed9b6e..890a7cbb6 100644 --- a/src/de/danoeh/antennapod/feed/FeedManager.java +++ b/src/de/danoeh/antennapod/feed/FeedManager.java @@ -19,7 +19,6 @@ import android.os.Handler; import android.preference.PreferenceManager; import android.util.Log; import de.danoeh.antennapod.AppConfig; -import de.danoeh.antennapod.PodcastApp; import de.danoeh.antennapod.asynctask.DownloadStatus; import de.danoeh.antennapod.preferences.UserPreferences; import de.danoeh.antennapod.service.PlaybackService; @@ -1472,7 +1471,22 @@ public class FeedManager { }); } - public List getFeeds() { + /** Returns the number of feeds that are currently in the feeds list. */ + public int getFeedsSize() { + return feeds.size(); + } + + /** Returns the feed at the specified index of the feeds list. */ + public Feed getFeedAtIndex(int index) { + return feeds.get(index); + } + + /** Returns an array that contains all feeds of the feed manager. */ + public Feed[] getFeedsArray() { + return feeds.toArray(new Feed[feeds.size()]); + } + + List getFeeds() { return feeds; } @@ -1542,12 +1556,31 @@ public class FeedManager { } } - public ArrayList getDownloadLog() { - return downloadLog; + /** + * Returns the number of items in the playback history. + * */ + public int getPlaybackHistorySize() { + return playbackHistory.size(); } - public List getPlaybackHistory() { - return playbackHistory; + /** + * Returns the FeedItem at the specified index of the playback history. + * + * @throws IndexOutOfBoundsException + * if index is out of range + * */ + public FeedItem getPlaybackHistoryItemIndex(int index) { + return playbackHistory.get(index); + } + + /** Returns the number of items in the download log */ + public int getDownloadLogSize() { + return downloadLog.size(); + } + + /** Returns the download status at the specified index of the download log. */ + public DownloadStatus getDownloadStatusFromLogAtIndex(int index) { + return downloadLog.get(index); } /** Is called by a FeedManagerTask after completion. */ diff --git a/src/de/danoeh/antennapod/fragment/FeedlistFragment.java b/src/de/danoeh/antennapod/fragment/FeedlistFragment.java index caf6c6a7f..f9b1b7474 100644 --- a/src/de/danoeh/antennapod/fragment/FeedlistFragment.java +++ b/src/de/danoeh/antennapod/fragment/FeedlistFragment.java @@ -45,7 +45,6 @@ public class FeedlistFragment extends SherlockFragment implements private FeedManager manager; private FeedlistAdapter fla; - private SherlockFragmentActivity pActivity; private Feed selectedFeed; private ActionMode mActionMode; @@ -57,13 +56,11 @@ public class FeedlistFragment extends SherlockFragment implements @Override public void onAttach(Activity activity) { super.onAttach(activity); - pActivity = (SherlockFragmentActivity) activity; } @Override public void onDetach() { super.onDetach(); - pActivity = null; } @Override @@ -72,7 +69,7 @@ public class FeedlistFragment extends SherlockFragment implements if (AppConfig.DEBUG) Log.d(TAG, "Creating"); manager = FeedManager.getInstance(); - fla = new FeedlistAdapter(pActivity, 0, manager.getFeeds()); + fla = new FeedlistAdapter(getActivity()); } @@ -118,14 +115,14 @@ public class FeedlistFragment extends SherlockFragment implements filter.addAction(FeedManager.ACTION_UNREAD_ITEMS_UPDATE); filter.addAction(FeedManager.ACTION_FEED_LIST_UPDATE); filter.addAction(DownloadService.ACTION_DOWNLOAD_HANDLED); - pActivity.registerReceiver(contentUpdate, filter); + getActivity().registerReceiver(contentUpdate, filter); fla.notifyDataSetChanged(); } @Override public void onPause() { super.onPause(); - pActivity.unregisterReceiver(contentUpdate); + getActivity().unregisterReceiver(contentUpdate); if (mActionMode != null) { mActionMode.finish(); } @@ -211,10 +208,10 @@ public class FeedlistFragment extends SherlockFragment implements public void onItemClick(AdapterView arg0, View arg1, int position, long id) { Feed selection = fla.getItem(position); - Intent showFeed = new Intent(pActivity, FeedItemlistActivity.class); + Intent showFeed = new Intent(getActivity(), FeedItemlistActivity.class); showFeed.putExtra(EXTRA_SELECTED_FEED, selection.getId()); - pActivity.startActivity(showFeed); + getActivity().startActivity(showFeed); } @Override diff --git a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java index cdccdc338..6b516f888 100644 --- a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.fragment; import java.util.List; +import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -34,35 +35,30 @@ import de.danoeh.antennapod.storage.DownloadRequester; import de.danoeh.antennapod.util.menuhandler.FeedItemMenuHandler; /** Displays a list of FeedItems. */ +@SuppressLint("ValidFragment") public class ItemlistFragment extends SherlockListFragment { private static final String TAG = "ItemlistFragment"; public static final String EXTRA_SELECTED_FEEDITEM = "extra.de.danoeh.antennapod.activity.selected_feeditem"; public static final String ARGUMENT_FEED_ID = "argument.de.danoeh.antennapod.feed_id"; protected AbstractFeedItemlistAdapter fila; - protected FeedManager manager; - protected DownloadRequester requester; + protected FeedManager manager = FeedManager.getInstance(); + protected DownloadRequester requester = DownloadRequester.getInstance(); - /** The feed which the activity displays */ - protected List items; - /** - * This is only not null if the fragment displays the items of a specific - * feed - */ - protected Feed feed; + private AbstractFeedItemlistAdapter.ItemAccess itemAccess; + private Feed feed; + protected FeedItem selectedItem = null; protected boolean contextMenuClosed = true; /** Argument for FeeditemlistAdapter */ protected boolean showFeedtitle; - public ItemlistFragment(List items, boolean showFeedtitle) { + public ItemlistFragment(AbstractFeedItemlistAdapter.ItemAccess itemAccess, boolean showFeedtitle) { super(); - this.items = items; + this.itemAccess = itemAccess; this.showFeedtitle = showFeedtitle; - manager = FeedManager.getInstance(); - requester = DownloadRequester.getInstance(); } public ItemlistFragment() { @@ -94,15 +90,27 @@ public class ItemlistFragment extends SherlockListFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (items == null) { + if (itemAccess == null) { long feedId = getArguments().getLong(ARGUMENT_FEED_ID); - feed = FeedManager.getInstance().getFeed(feedId); - items = feed.getItems(); + final Feed feed = FeedManager.getInstance().getFeed(feedId); + this.feed = feed; + itemAccess = new AbstractFeedItemlistAdapter.ItemAccess() { + + @Override + public FeedItem getItem(int position) { + return feed.getItemAtIndex(true, position); + } + + @Override + public int getCount() { + return feed.getNumOfItems(true); + } + }; } } protected AbstractFeedItemlistAdapter createListAdapter() { - return new FeedItemlistAdapter(getActivity(), 0, items, + return new FeedItemlistAdapter(getActivity(), itemAccess, adapterCallback, showFeedtitle); } @@ -178,7 +186,7 @@ public class ItemlistFragment extends SherlockListFragment { getSherlockActivity() .setSupportProgressBarIndeterminateVisibility(false); } - getSherlockActivity().invalidateOptionsMenu(); + getSherlockActivity().supportInvalidateOptionsMenu(); } } diff --git a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index a2826c977..17ff9c6a1 100644 --- a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -7,13 +7,27 @@ import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import de.danoeh.antennapod.AppConfig; +import de.danoeh.antennapod.adapter.AbstractFeedItemlistAdapter; +import de.danoeh.antennapod.feed.FeedItem; import de.danoeh.antennapod.feed.FeedManager; public class PlaybackHistoryFragment extends ItemlistFragment { private static final String TAG = "PlaybackHistoryFragment"; public PlaybackHistoryFragment() { - super(FeedManager.getInstance().getPlaybackHistory(), true); + super(new AbstractFeedItemlistAdapter.ItemAccess() { + + @Override + public FeedItem getItem(int position) { + return FeedManager.getInstance().getPlaybackHistoryItemIndex( + position); + } + + @Override + public int getCount() { + return FeedManager.getInstance().getPlaybackHistorySize(); + } + }, true); } @Override diff --git a/src/de/danoeh/antennapod/preferences/UserPreferences.java b/src/de/danoeh/antennapod/preferences/UserPreferences.java index 7625f88e4..c0f0f9353 100644 --- a/src/de/danoeh/antennapod/preferences/UserPreferences.java +++ b/src/de/danoeh/antennapod/preferences/UserPreferences.java @@ -45,7 +45,7 @@ public class UserPreferences implements private boolean pauseOnHeadsetDisconnect; private boolean followQueue; private boolean downloadMediaOnWifiOnly; - private int updateInterval; + private long updateInterval; private boolean allowMobileUpdate; private boolean autoQueue; private boolean displayOnlyEpisodes; @@ -55,10 +55,6 @@ public class UserPreferences implements private UserPreferences(Context context) { this.context = context; loadPreferences(); - createImportDirectory(); - createNoMediaFile(); - PreferenceManager.getDefaultSharedPreferences(context) - .registerOnSharedPreferenceChangeListener(this); } /** @@ -73,6 +69,11 @@ public class UserPreferences implements if (context == null) throw new IllegalArgumentException("Context must not be null"); instance = new UserPreferences(context); + + createImportDirectory(); + createNoMediaFile(); + PreferenceManager.getDefaultSharedPreferences(context) + .registerOnSharedPreferenceChangeListener(instance); } private void loadPreferences() { @@ -83,7 +84,8 @@ public class UserPreferences implements followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false); downloadMediaOnWifiOnly = sp.getBoolean( PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY, true); - updateInterval = sp.getInt(PREF_UPDATE_INTERVAL, 0); + updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL, + "0")); allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false); autoQueue = sp.getBoolean(PREF_AUTO_QUEUE, true); displayOnlyEpisodes = sp.getBoolean(PREF_DISPLAY_ONLY_EPISODES, false); @@ -102,6 +104,11 @@ public class UserPreferences implements } } + private long readUpdateInterval(String valueFromPrefs) { + int hours = Integer.parseInt(valueFromPrefs); + return TimeUnit.HOURS.toMillis(hours); + } + private static void instanceAvailable() { if (instance == null) { throw new IllegalStateException( @@ -124,7 +131,7 @@ public class UserPreferences implements return instance.downloadMediaOnWifiOnly; } - public static int getUpdateInterval() { + public static long getUpdateInterval() { instanceAvailable(); return instance.updateInterval; } @@ -170,18 +177,16 @@ public class UserPreferences implements followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false); } else if (key.equals(PREF_UPDATE_INTERVAL)) { - updateInterval = sp.getInt(PREF_UPDATE_INTERVAL, 0); AlarmManager alarmManager = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); - int hours = Integer.parseInt(sp - .getString(PREF_UPDATE_INTERVAL, "0")); + updateInterval = readUpdateInterval(sp.getString( + PREF_UPDATE_INTERVAL, "0")); PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, new Intent(FeedUpdateReceiver.ACTION_REFRESH_FEEDS), 0); alarmManager.cancel(updateIntent); - if (hours != 0) { - long newIntervall = TimeUnit.HOURS.toMillis(hours); + if (updateInterval != 0) { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, - newIntervall, newIntervall, updateIntent); + updateInterval, updateInterval, updateIntent); if (AppConfig.DEBUG) Log.d(TAG, "Changed alarm to new intervall"); } else { diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java index 18262c396..d42e7ebc0 100644 --- a/src/de/danoeh/antennapod/service/download/DownloadService.java +++ b/src/de/danoeh/antennapod/service/download/DownloadService.java @@ -755,7 +755,7 @@ public class DownloadService extends Service { } private boolean hasValidFeedItems(Feed feed) { - for (FeedItem item : feed.getItems()) { + for (FeedItem item : feed.getItemsArray()) { if (item.getTitle() == null) { Log.e(TAG, "Item has no title"); return false; diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java index 4045f8664..f1842800b 100644 --- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java +++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java @@ -334,7 +334,7 @@ public class PodDBAdapter { public void setCompleteFeed(Feed feed) { db.beginTransaction(); setFeed(feed); - for (FeedItem item : feed.getItems()) { + for (FeedItem item : feed.getItemsArray()) { setFeedItem(item); } db.setTransactionSuccessful(); @@ -485,7 +485,7 @@ public class PodDBAdapter { if (feed.getImage() != null) { removeFeedImage(feed.getImage()); } - for (FeedItem item : feed.getItems()) { + for (FeedItem item : feed.getItemsArray()) { removeFeedItem(item); } db.delete(TABLE_NAME_FEEDS, KEY_ID + "=?", diff --git a/src/de/danoeh/antennapod/syndication/handler/HandlerState.java b/src/de/danoeh/antennapod/syndication/handler/HandlerState.java index 6c206b8f3..f36307ef7 100644 --- a/src/de/danoeh/antennapod/syndication/handler/HandlerState.java +++ b/src/de/danoeh/antennapod/syndication/handler/HandlerState.java @@ -1,6 +1,8 @@ package de.danoeh.antennapod.syndication.handler; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Stack; import de.danoeh.antennapod.feed.Feed; @@ -8,11 +10,15 @@ import de.danoeh.antennapod.feed.FeedItem; import de.danoeh.antennapod.syndication.namespace.Namespace; import de.danoeh.antennapod.syndication.namespace.SyndElement; -/** Contains all relevant information to describe the current state of a SyndHandler.*/ +/** + * Contains all relevant information to describe the current state of a + * SyndHandler. + */ public class HandlerState { - + /** Feed that the Handler is currently processing. */ protected Feed feed; + protected ArrayList items; protected FeedItem currentItem; protected Stack tagstack; /** Namespaces that have been defined so far. */ @@ -20,43 +26,49 @@ public class HandlerState { protected Stack defaultNamespaces; /** Buffer for saving characters. */ protected StringBuffer contentBuf; - + public HandlerState(Feed feed) { this.feed = feed; + items = new ArrayList(); tagstack = new Stack(); namespaces = new HashMap(); defaultNamespaces = new Stack(); } - - + public Feed getFeed() { return feed; } + + public ArrayList getItems() { + return items; + } + public FeedItem getCurrentItem() { return currentItem; } + public Stack getTagstack() { return tagstack; } - public void setFeed(Feed feed) { this.feed = feed; } - public void setCurrentItem(FeedItem currentItem) { this.currentItem = currentItem; } - /** Returns the SyndElement that comes after the top element of the tagstack. */ + /** + * Returns the SyndElement that comes after the top element of the tagstack. + */ public SyndElement getSecondTag() { SyndElement top = tagstack.pop(); SyndElement second = tagstack.peek(); tagstack.push(top); return second; } - + public SyndElement getThirdTag() { SyndElement top = tagstack.pop(); SyndElement second = tagstack.pop(); @@ -65,13 +77,9 @@ public class HandlerState { tagstack.push(top); return third; } - + public StringBuffer getContentBuf() { return contentBuf; } - - - - } diff --git a/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java b/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java index f830f0933..c51d054d4 100644 --- a/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java +++ b/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java @@ -120,6 +120,12 @@ public class SyndHandler extends DefaultHandler { return handler; } + @Override + public void endDocument() throws SAXException { + super.endDocument(); + state.getFeed().setItems(state.getItems()); + } + public HandlerState getState() { return state; } diff --git a/src/de/danoeh/antennapod/syndication/namespace/NSRSS20.java b/src/de/danoeh/antennapod/syndication/namespace/NSRSS20.java index a8c43800c..4d0b42132 100644 --- a/src/de/danoeh/antennapod/syndication/namespace/NSRSS20.java +++ b/src/de/danoeh/antennapod/syndication/namespace/NSRSS20.java @@ -43,7 +43,7 @@ public class NSRSS20 extends Namespace { Attributes attributes) { if (localName.equals(ITEM)) { state.setCurrentItem(new FeedItem()); - state.getFeed().getItems().add(state.getCurrentItem()); + state.getItems().add(state.getCurrentItem()); state.getCurrentItem().setFeed(state.getFeed()); } else if (localName.equals(ENCLOSURE)) { diff --git a/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java b/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java index e3cdce534..522b16efe 100644 --- a/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java +++ b/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java @@ -55,7 +55,7 @@ public class NSAtom extends Namespace { Attributes attributes) { if (localName.equals(ENTRY)) { state.setCurrentItem(new FeedItem()); - state.getFeed().getItems().add(state.getCurrentItem()); + state.getItems().add(state.getCurrentItem()); state.getCurrentItem().setFeed(state.getFeed()); } else if (localName.matches(isText)) { String type = attributes.getValue(TEXT_TYPE); diff --git a/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java b/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java index 37f5fd0d3..af8538e83 100644 --- a/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java +++ b/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java @@ -33,7 +33,7 @@ public class FeedMenuHandler { if (AppConfig.DEBUG) Log.d(TAG, "Preparing options menu"); menu.findItem(R.id.mark_all_read_item).setVisible( - selectedFeed.hasNewItems()); + selectedFeed.hasNewItems(true)); if (selectedFeed.getPaymentLink() != null) { menu.findItem(R.id.support_item).setVisible(true); } diff --git a/tests/src/de/danoeh/antennapod/test/FeedHandlerTest.java b/tests/src/de/danoeh/antennapod/test/FeedHandlerTest.java index d95fe69c3..132d40eba 100644 --- a/tests/src/de/danoeh/antennapod/test/FeedHandlerTest.java +++ b/tests/src/de/danoeh/antennapod/test/FeedHandlerTest.java @@ -93,10 +93,6 @@ public class FeedHandlerTest extends AndroidTestCase { Log.e(TAG, "Feed has no title"); return false; } - if (feed.getItems() == null) { - Log.e(TAG, "Feed has no items"); - return false; - } if (!hasValidFeedItems(feed)) { Log.e(TAG, "Feed has invalid items"); return false; @@ -122,7 +118,7 @@ public class FeedHandlerTest extends AndroidTestCase { } private boolean hasValidFeedItems(Feed feed) { - for (FeedItem item : feed.getItems()) { + for (FeedItem item : feed.getItemsArray()) { if (item.getTitle() == null) { Log.e(TAG, "Item has no title"); return false;