summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/de/danoeh/antennapod/activity/SearchActivity.java78
-rw-r--r--src/de/danoeh/antennapod/feed/Feed.java9
-rw-r--r--src/de/danoeh/antennapod/feed/FeedItem.java67
-rw-r--r--src/de/danoeh/antennapod/feed/FeedManager.java188
-rw-r--r--src/de/danoeh/antennapod/feed/FeedSearcher.java157
-rw-r--r--src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java39
-rw-r--r--src/de/danoeh/antennapod/storage/PodDBAdapter.java100
7 files changed, 496 insertions, 142 deletions
diff --git a/src/de/danoeh/antennapod/activity/SearchActivity.java b/src/de/danoeh/antennapod/activity/SearchActivity.java
index a073b43cc..9b2f5188b 100644
--- a/src/de/danoeh/antennapod/activity/SearchActivity.java
+++ b/src/de/danoeh/antennapod/activity/SearchActivity.java
@@ -69,8 +69,10 @@ public class SearchActivity extends SherlockListActivity {
if (AppConfig.DEBUG)
Log.d(TAG, "Starting search");
String query = intent.getStringExtra(SearchManager.QUERY);
- getSupportActionBar().setSubtitle(
- getString(R.string.search_term_label) + "\"" + query + "\"");
+ getSupportActionBar()
+ .setSubtitle(
+ getString(R.string.search_term_label) + "\""
+ + query + "\"");
handleSearchRequest(query);
}
}
@@ -133,48 +135,46 @@ public class SearchActivity extends SherlockListActivity {
}
@SuppressLint({ "NewApi", "NewApi" })
- private void handleSearchRequest(String query) {
- AsyncTask<String, Void, ArrayList<SearchResult>> executor = new AsyncTask<String, Void, ArrayList<SearchResult>>() {
-
- @Override
- protected void onPreExecute() {
- if (searchAdapter != null) {
- searchAdapter.clear();
- searchAdapter.notifyDataSetChanged();
- }
- txtvStatus.setText(R.string.search_status_searching);
- }
+ private void handleSearchRequest(final String query) {
+ if (searchAdapter != null) {
+ searchAdapter.clear();
+ searchAdapter.notifyDataSetChanged();
+ }
+ txtvStatus.setText(R.string.search_status_searching);
- @Override
- protected ArrayList<SearchResult> doInBackground(String... params) {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Starting background work");
- return FeedSearcher.performSearch(params[0], selectedFeed);
- }
+ Thread thread = new Thread() {
@Override
- protected void onPostExecute(ArrayList<SearchResult> result) {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Background work finished");
- if (AppConfig.DEBUG)
- Log.d(TAG, "Found " + result.size() + " results");
- content = result;
-
- searchAdapter = new SearchlistAdapter(SearchActivity.this, 0,
- content);
- getListView().setAdapter(searchAdapter);
- searchAdapter.notifyDataSetChanged();
- if (content.isEmpty()) {
- txtvStatus.setText(R.string.search_status_no_results);
+ public void run() {
+ Log.d(TAG, "Starting background work");
+ final ArrayList<SearchResult> result = FeedSearcher
+ .performSearch(SearchActivity.this, query, selectedFeed);
+ if (SearchActivity.this != null) {
+ SearchActivity.this.runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Background work finished");
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Found " + result.size()
+ + " results");
+ content = result;
+
+ searchAdapter = new SearchlistAdapter(
+ SearchActivity.this, 0, content);
+ getListView().setAdapter(searchAdapter);
+ searchAdapter.notifyDataSetChanged();
+ if (content.isEmpty()) {
+ txtvStatus
+ .setText(R.string.search_status_no_results);
+ }
+ }
+ });
}
-
}
-
};
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, query);
- } else {
- executor.execute(query);
- }
+ thread.start();
+
}
}
diff --git a/src/de/danoeh/antennapod/feed/Feed.java b/src/de/danoeh/antennapod/feed/Feed.java
index 6cea571f6..55256ea31 100644
--- a/src/de/danoeh/antennapod/feed/Feed.java
+++ b/src/de/danoeh/antennapod/feed/Feed.java
@@ -144,6 +144,15 @@ public class Feed extends FeedFile {
return download_url;
}
}
+
+ /** Calls cacheDescriptions on all items. */
+ protected void cacheDescriptionsOfItems() {
+ if (items != null) {
+ for (FeedItem item : items) {
+ item.cacheDescriptions();
+ }
+ }
+ }
@Override
public int getTypeAsInt() {
diff --git a/src/de/danoeh/antennapod/feed/FeedItem.java b/src/de/danoeh/antennapod/feed/FeedItem.java
index 93655f8cb..6227298df 100644
--- a/src/de/danoeh/antennapod/feed/FeedItem.java
+++ b/src/de/danoeh/antennapod/feed/FeedItem.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.feed;
+import java.lang.ref.SoftReference;
import java.util.Date;
import java.util.List;
@@ -13,11 +14,23 @@ import de.danoeh.antennapod.PodcastApp;
*/
public class FeedItem extends FeedComponent {
- /** The id/guid that can be found in the rss/atom feed. Might not be set.*/
+ /** The id/guid that can be found in the rss/atom feed. Might not be set. */
private String itemIdentifier;
private String title;
+ /**
+ * The description of a feeditem. This field should only be set by the
+ * parser.
+ */
private String description;
+ /**
+ * The content of the content-encoded tag of a feeditem. This field should
+ * only be set by the parser.
+ */
private String contentEncoded;
+
+ private SoftReference<String> cachedDescription;
+ private SoftReference<String> cachedContentEncoded;
+
private String link;
private Date pubDate;
private FeedMedia media;
@@ -30,16 +43,19 @@ public class FeedItem extends FeedComponent {
this.read = true;
}
- public FeedItem(String title, String description, String link,
- Date pubDate, FeedMedia media, Feed feed) {
- super();
- this.title = title;
- this.description = description;
- this.link = link;
- this.pubDate = pubDate;
- this.media = media;
- this.feed = feed;
- this.read = true;
+ /**
+ * Moves the 'description' and 'contentEncoded' field of feeditem to their
+ * SoftReference fields.
+ */
+ protected void cacheDescriptions() {
+ if (description != null) {
+ cachedDescription = new SoftReference<String>(description);
+ }
+ if (contentEncoded != null) {
+ cachedContentEncoded = new SoftReference<String>(contentEncoded);
+ }
+ description = null;
+ contentEncoded = null;
}
/** Get the chapter that fits the position. */
@@ -62,11 +78,12 @@ public class FeedItem extends FeedComponent {
public Chapter getCurrentChapter() {
return getCurrentChapter(media.getPosition());
}
-
- /** Returns the value that uniquely identifies this FeedItem.
- * If the itemIdentifier attribute is not null, it will be returned.
- * Else it will try to return the title. If the title is not given, it will
- * use the link of the entry.
+
+ /**
+ * Returns the value that uniquely identifies this FeedItem. If the
+ * itemIdentifier attribute is not null, it will be returned. Else it will
+ * try to return the title. If the title is not given, it will use the link
+ * of the entry.
* */
public String getIdentifyingValue() {
if (itemIdentifier != null) {
@@ -87,6 +104,9 @@ public class FeedItem extends FeedComponent {
}
public String getDescription() {
+ if (description == null && cachedDescription != null) {
+ return cachedDescription.get();
+ }
return description;
}
@@ -131,6 +151,10 @@ public class FeedItem extends FeedComponent {
}
public String getContentEncoded() {
+ if (contentEncoded == null && cachedContentEncoded != null) {
+ return cachedContentEncoded.get();
+
+ }
return contentEncoded;
}
@@ -161,7 +185,7 @@ public class FeedItem extends FeedComponent {
public void setItemIdentifier(String itemIdentifier) {
this.itemIdentifier = itemIdentifier;
}
-
+
public boolean isPlaying() {
if (media != null) {
if (PodcastApp.getCurrentlyPlayingMediaId() == media.getId()) {
@@ -170,6 +194,13 @@ public class FeedItem extends FeedComponent {
}
return false;
}
-
+
+ public void setCachedDescription(String d) {
+ cachedDescription = new SoftReference<String>(d);
+ }
+
+ public void setCachedContentEncoded(String c) {
+ cachedContentEncoded = new SoftReference<String>(c);
+ }
}
diff --git a/src/de/danoeh/antennapod/feed/FeedManager.java b/src/de/danoeh/antennapod/feed/FeedManager.java
index 3f774b4bd..7f4a1c5aa 100644
--- a/src/de/danoeh/antennapod/feed/FeedManager.java
+++ b/src/de/danoeh/antennapod/feed/FeedManager.java
@@ -774,6 +774,7 @@ public class FeedManager {
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
adapter.setCompleteFeed(feed);
+ feed.cacheDescriptionsOfItems();
adapter.close();
}
});
@@ -867,6 +868,7 @@ public class FeedManager {
public void setFeed(Feed feed, PodDBAdapter adapter) {
if (adapter != null) {
adapter.setFeed(feed);
+ feed.cacheDescriptionsOfItems();
} else {
Log.w(TAG, "Adapter in setFeed was null");
}
@@ -914,6 +916,7 @@ public class FeedManager {
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
adapter.setFeed(feed);
+ feed.cacheDescriptionsOfItems();
adapter.close();
}
});
@@ -1009,6 +1012,19 @@ public class FeedManager {
return null;
}
+ /** Get a FeedItem by its id and the id of its feed. */
+ public FeedItem getFeedItem(long itemId, long feedId) {
+ Feed feed = getFeed(feedId);
+ if (feed != null && feed.getItems() != null) {
+ for (FeedItem item : feed.getItems()) {
+ if (item.getId() == itemId) {
+ return item;
+ }
+ }
+ }
+ return null;
+ }
+
/** Get a FeedMedia object by the id of the Media object and the feed object */
public FeedMedia getFeedMedia(long id, Feed feed) {
if (feed != null) {
@@ -1129,37 +1145,34 @@ public class FeedManager {
do {
FeedItem item = new FeedItem();
- item.id = itemlistCursor.getLong(PodDBAdapter.KEY_ID_INDEX);
+ item.id = itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_ID);
item.setFeed(feed);
item.setTitle(itemlistCursor
- .getString(PodDBAdapter.KEY_TITLE_INDEX));
+ .getString(PodDBAdapter.IDX_FI_SMALL_TITLE));
item.setLink(itemlistCursor
- .getString(PodDBAdapter.KEY_LINK_INDEX));
- item.setDescription(itemlistCursor
- .getString(PodDBAdapter.KEY_DESCRIPTION_INDEX));
- item.setContentEncoded(itemlistCursor
- .getString(PodDBAdapter.KEY_CONTENT_ENCODED_INDEX));
+ .getString(PodDBAdapter.IDX_FI_SMALL_LINK));
item.setPubDate(new Date(itemlistCursor
- .getLong(PodDBAdapter.KEY_PUBDATE_INDEX)));
+ .getLong(PodDBAdapter.IDX_FI_SMALL_PUBDATE)));
item.setPaymentLink(itemlistCursor
- .getString(PodDBAdapter.KEY_PAYMENT_LINK_INDEX));
+ .getString(PodDBAdapter.IDX_FI_SMALL_PAYMENT_LINK));
long mediaId = itemlistCursor
- .getLong(PodDBAdapter.KEY_MEDIA_INDEX);
+ .getLong(PodDBAdapter.IDX_FI_SMALL_MEDIA);
if (mediaId != 0) {
mediaIds.add(String.valueOf(mediaId));
item.setMedia(new FeedMedia(mediaId, item));
}
- item.read = (itemlistCursor.getInt(PodDBAdapter.KEY_READ_INDEX) > 0) ? true
+ item.read = (itemlistCursor
+ .getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0) ? true
: false;
item.setItemIdentifier(itemlistCursor
- .getString(PodDBAdapter.KEY_ITEM_IDENTIFIER_INDEX));
+ .getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER));
if (!item.read) {
unreadItems.add(item);
}
// extract chapters
boolean hasSimpleChapters = itemlistCursor
- .getInt(PodDBAdapter.KEY_HAS_SIMPLECHAPTERS_INDEX) > 0;
+ .getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0;
if (hasSimpleChapters) {
Cursor chapterCursor = adapter
.getSimpleChaptersOfFeedItemCursor(item);
@@ -1325,6 +1338,57 @@ public class FeedManager {
cursor.close();
}
+ public void loadExtraInformationOfItem(final Context context,
+ final FeedItem item, FeedManager.TaskCallback callback) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "Loading extra information of item with id " + item.getId());
+ dbExec.execute(new FeedManager.Task(new Handler(), callback) {
+
+ @Override
+ public void execute() {
+ PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ Cursor extraCursor = adapter.getExtraInformationOfItem(item);
+ if (extraCursor.moveToFirst()) {
+ item.setCachedDescription(extraCursor
+ .getString(PodDBAdapter.IDX_FI_EXTRA_DESCRIPTION));
+ item.setCachedContentEncoded(extraCursor
+ .getString(PodDBAdapter.IDX_FI_EXTRA_CONTENT_ENCODED));
+ }
+ adapter.close();
+ }
+ });
+ }
+
+ public void searchFeedItemDescription(final Context context,
+ final Feed feed, final String query,
+ FeedManager.QueryTaskCallback callback) {
+ dbExec.execute(new FeedManager.QueryTask(context, new Handler(), callback) {
+
+ @Override
+ public void execute(PodDBAdapter adapter) {
+ Cursor searchResult = adapter.searchItemDescriptions(feed,
+ query);
+ setResult(searchResult);
+ }
+ });
+ }
+
+ public void searchFeedItemContentEncoded(final Context context,
+ final Feed feed, final String query,
+ FeedManager.QueryTaskCallback callback) {
+ dbExec.execute(new FeedManager.QueryTask(context, new Handler(), callback) {
+
+ @Override
+ public void execute(PodDBAdapter adapter) {
+ Cursor searchResult = adapter.searchItemContentEncoded(feed,
+ query);
+ setResult(searchResult);
+ }
+ });
+ }
+
public List<Feed> getFeeds() {
return feeds;
}
@@ -1345,4 +1409,102 @@ public class FeedManager {
return playbackHistory;
}
+ /** Is called by a FeedManagerTask after completion. */
+ public interface TaskCallback {
+ void onCompletion(Cursor result);
+ }
+
+ /** Is called by a FeedManager.QueryTask after completion. */
+ public interface QueryTaskCallback {
+ void handleResult(Cursor result);
+ void onCompletion();
+ }
+
+ /** A runnable that can post a callback to a handler after completion. */
+ abstract class Task implements Runnable {
+ private Handler handler;
+ private TaskCallback callback;
+
+ /**
+ * Standard contructor. No callbacks are going to be posted to a
+ * handler.
+ */
+ public Task() {
+ super();
+ }
+
+ /**
+ * The Task will post a Runnable to 'handler' that will execute the
+ * 'callback' after completion.
+ */
+ public Task(Handler handler, TaskCallback callback) {
+ super();
+ this.handler = handler;
+ this.callback = callback;
+ }
+
+ @Override
+ public final void run() {
+ execute();
+ if (handler != null && callback != null) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onCompletion(null);
+ }
+ });
+ }
+ }
+
+ /** This method will be executed in the same thread as the run() method. */
+ public abstract void execute();
+ }
+
+ /**
+ * A runnable which should be used for database queries. The onCompletion
+ * method is executed on the database executor to handle Cursors correctly.
+ * This class automatically creates a PodDBAdapter object and closes it when
+ * it is no longer in use.
+ */
+ abstract class QueryTask implements Runnable {
+ private QueryTaskCallback callback;
+ private Cursor result;
+ private Context context;
+ private Handler handler;
+
+ public QueryTask(Context context, Handler handler, QueryTaskCallback callback) {
+ this.callback = callback;
+ this.context = context;
+ this.handler = handler;
+ }
+
+ @Override
+ public final void run() {
+ PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ execute(adapter);
+ callback.handleResult(result);
+ if (result != null && !result.isClosed()) {
+ result.close();
+ }
+ adapter.close();
+ if (handler != null && callback != null) {
+ handler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ callback.onCompletion();
+ }
+
+ });
+ }
+ }
+
+ public abstract void execute(PodDBAdapter adapter);
+
+ protected void setResult(Cursor c) {
+ result = c;
+ }
+ }
+
}
diff --git a/src/de/danoeh/antennapod/feed/FeedSearcher.java b/src/de/danoeh/antennapod/feed/FeedSearcher.java
index f53ff5ae7..ab7c174bc 100644
--- a/src/de/danoeh/antennapod/feed/FeedSearcher.java
+++ b/src/de/danoeh/antennapod/feed/FeedSearcher.java
@@ -5,10 +5,14 @@ import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.Looper;
import android.util.Log;
import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.storage.PodDBAdapter;
import de.danoeh.antennapod.util.comparator.SearchResultValueComparator;
/** Performs search on Feeds and FeedItems */
@@ -23,10 +27,10 @@ public class FeedSearcher {
private static final int VALUE_WORD_MATCH = 4;
/** Performs a search in all feeds or one specific feed. */
- public static ArrayList<SearchResult> performSearch(final String query,
- Feed selectedFeed) {
- String lcQuery = query.toLowerCase();
- ArrayList<SearchResult> result = new ArrayList<SearchResult>();
+ public static ArrayList<SearchResult> performSearch(final Context context,
+ final String query, final Feed selectedFeed) {
+ final String lcQuery = query.toLowerCase();
+ final ArrayList<SearchResult> result = new ArrayList<SearchResult>();
if (selectedFeed == null) {
if (AppConfig.DEBUG)
Log.d(TAG, "Performing global search");
@@ -45,14 +49,40 @@ public class FeedSearcher {
Log.d(TAG, "Searching item-chaptertitles");
searchFeedItemChapters(lcQuery, result, selectedFeed);
- if (AppConfig.DEBUG)
- Log.d(TAG, "Searching item descriptions");
- searchFeedItemDescription(lcQuery, result, selectedFeed);
+ final FeedManager manager = FeedManager.getInstance();
+ Looper.prepare();
+ manager.searchFeedItemDescription(context, selectedFeed, lcQuery,
+ new FeedManager.QueryTaskCallback() {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Searching item content encoded data");
- searchFeedItemContentEncoded(lcQuery, result, selectedFeed);
+ @Override
+ public void handleResult(Cursor cResult) {
+ searchFeedItemContentEncodedCursor(lcQuery, result,
+ selectedFeed, cResult);
+
+ }
+ @Override
+ public void onCompletion() {
+ manager.searchFeedItemContentEncoded(context,
+ selectedFeed, lcQuery,
+ new FeedManager.QueryTaskCallback() {
+
+ @Override
+ public void handleResult(Cursor cResult) {
+ searchFeedItemDescriptionCursor(
+ lcQuery, result, selectedFeed,
+ cResult);
+ }
+
+ @Override
+ public void onCompletion() {
+ Looper.myLooper().quit();
+ }
+ });
+ }
+ });
+
+ Looper.loop();
if (AppConfig.DEBUG)
Log.d(TAG, "Sorting results");
Collections.sort(result, new SearchResultValueComparator());
@@ -127,61 +157,74 @@ public class FeedSearcher {
}
}
- private static void searchFeedItemDescription(String query,
- ArrayList<SearchResult> destination, Feed selectedFeed) {
+ private static void searchFeedItemDescriptionCursor(String query,
+ ArrayList<SearchResult> destination, Feed feed, Cursor cursor) {
FeedManager manager = FeedManager.getInstance();
- if (selectedFeed == null) {
- for (Feed feed : manager.getFeeds()) {
- searchFeedItemDescriptionSingleFeed(query, destination, feed);
- }
- } else {
- searchFeedItemDescriptionSingleFeed(query, destination,
- selectedFeed);
- }
- }
-
- private static void searchFeedItemDescriptionSingleFeed(String query,
- ArrayList<SearchResult> destination, Feed feed) {
- for (FeedItem item : feed.getItems()) {
- if (item.getDescription() != null) {
- SearchResult result = createSearchResult(item, query, item
- .getDescription().toLowerCase(), VALUE_ITEM_DESCRIPTION);
- if (result != null) {
- result.setSubtitle(PodcastApp.getInstance().getString(
- R.string.found_in_shownotes_label));
- destination.add(result);
+ if (cursor.moveToFirst()) {
+ do {
+ final long itemId = cursor
+ .getLong(PodDBAdapter.IDX_FI_EXTRA_ID);
+ String content = cursor
+ .getString(PodDBAdapter.IDX_FI_EXTRA_DESCRIPTION);
+ if (content != null) {
+ content = content.toLowerCase();
+ final long feedId = cursor
+ .getLong(PodDBAdapter.IDX_FI_EXTRA_FEED);
+ FeedItem item = null;
+ if (feed == null) {
+ item = manager.getFeedItem(itemId, feedId);
+ } else {
+ item = manager.getFeedItem(itemId, feed);
+ }
+ if (item != null) {
+ SearchResult searchResult = createSearchResult(item,
+ query, content, VALUE_ITEM_DESCRIPTION);
+ if (searchResult != null) {
+ searchResult.setSubtitle(PodcastApp.getInstance()
+ .getString(
+ R.string.found_in_shownotes_label));
+ destination.add(searchResult);
+
+ }
+ }
}
- }
+ } while (cursor.moveToNext());
}
}
- private static void searchFeedItemContentEncoded(String query,
- ArrayList<SearchResult> destination, Feed selectedFeed) {
+ private static void searchFeedItemContentEncodedCursor(String query,
+ ArrayList<SearchResult> destination, Feed feed, Cursor cursor) {
FeedManager manager = FeedManager.getInstance();
- if (selectedFeed == null) {
- for (Feed feed : manager.getFeeds()) {
- searchFeedItemContentEncodedSingleFeed(query, destination, feed);
- }
- } else {
- searchFeedItemContentEncodedSingleFeed(query, destination,
- selectedFeed);
- }
- }
-
- private static void searchFeedItemContentEncodedSingleFeed(String query,
- ArrayList<SearchResult> destination, Feed feed) {
- for (FeedItem item : feed.getItems()) {
- if (!destination.contains(item) && item.getContentEncoded() != null) {
- SearchResult result = createSearchResult(item, query, item
- .getContentEncoded().toLowerCase(),
- VALUE_ITEM_DESCRIPTION);
- if (result != null) {
- result.setSubtitle(PodcastApp.getInstance().getString(
- R.string.found_in_shownotes_label));
- destination.add(result);
+ if (cursor.moveToFirst()) {
+ do {
+ final long itemId = cursor
+ .getLong(PodDBAdapter.IDX_FI_EXTRA_ID);
+ String content = cursor
+ .getString(PodDBAdapter.IDX_FI_EXTRA_CONTENT_ENCODED);
+ if (content != null) {
+ content = content.toLowerCase();
+
+ final long feedId = cursor
+ .getLong(PodDBAdapter.IDX_FI_EXTRA_FEED);
+ FeedItem item = null;
+ if (feed == null) {
+ item = manager.getFeedItem(itemId, feedId);
+ } else {
+ item = manager.getFeedItem(itemId, feed);
+ }
+ if (item != null) {
+ SearchResult searchResult = createSearchResult(item,
+ query, content, VALUE_ITEM_DESCRIPTION);
+ if (searchResult != null) {
+ searchResult.setSubtitle(PodcastApp.getInstance()
+ .getString(
+ R.string.found_in_shownotes_label));
+ destination.add(searchResult);
+ }
+ }
}
- }
+ } while (cursor.moveToNext());
}
}
diff --git a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
index b05df96b2..42041ce2e 100644
--- a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
+++ b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
@@ -4,6 +4,7 @@ import org.apache.commons.lang3.StringEscapeUtils;
import android.annotation.SuppressLint;
import android.app.Activity;
+import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
@@ -104,16 +105,22 @@ public class ItemDescriptionFragment extends SherlockFragment {
}
}
- @SuppressLint("NewApi")
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (item != null) {
- webViewLoader = createLoader();
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- webViewLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ if (item.getDescription() == null && item.getDescription() == null) {
+ Log.i(TAG, "Loading data");
+ FeedManager.getInstance().loadExtraInformationOfItem(
+ getActivity(), item, new FeedManager.TaskCallback() {
+ @Override
+ public void onCompletion(Cursor result) {
+ startLoader();
+ }
+ });
} else {
- webViewLoader.execute();
+ Log.i(TAG, "Using cached data");
+ startLoader();
}
} else {
Log.e(TAG, "Error in onViewCreated: Item was null");
@@ -125,6 +132,16 @@ public class ItemDescriptionFragment extends SherlockFragment {
super.onResume();
}
+ @SuppressLint("NewApi")
+ private void startLoader() {
+ webViewLoader = createLoader();
+ if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
+ webViewLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } else {
+ webViewLoader.execute();
+ }
+ }
+
private AsyncTask<Void, Void, Void> createLoader() {
return new AsyncTask<Void, Void, Void>() {
@Override
@@ -145,8 +162,10 @@ public class ItemDescriptionFragment extends SherlockFragment {
// /webvDescription.loadData(url, "text/html", "utf-8");
webvDescription.loadDataWithBaseURL(null, data, "text/html",
"utf-8", "about:blank");
- getSherlockActivity()
- .setSupportProgressBarIndeterminateVisibility(false);
+ if (getSherlockActivity() != null) {
+ getSherlockActivity()
+ .setSupportProgressBarIndeterminateVisibility(false);
+ }
if (AppConfig.DEBUG)
Log.d(TAG, "Webview loaded");
webViewLoader = null;
@@ -155,8 +174,10 @@ public class ItemDescriptionFragment extends SherlockFragment {
@Override
protected void onPreExecute() {
super.onPreExecute();
- getSherlockActivity()
- .setSupportProgressBarIndeterminateVisibility(true);
+ if (getSherlockActivity() != null) {
+ getSherlockActivity()
+ .setSupportProgressBarIndeterminateVisibility(true);
+ }
}
@Override
diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
index 5bb0afd2f..9b60521cf 100644
--- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java
+++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
@@ -180,6 +180,39 @@ public class PodDBAdapter {
private final Context context;
private PodDBHelper helper;
+ /**
+ * Select all columns from the feeditems-table except description and
+ * content-encoded.
+ */
+ private static final String[] SEL_FI_SMALL = { KEY_ID, KEY_TITLE,
+ KEY_PUBDATE, KEY_READ, KEY_LINK, KEY_PAYMENT_LINK, KEY_MEDIA,
+ KEY_FEED, KEY_HAS_CHAPTERS, KEY_ITEM_IDENTIFIER };
+
+ // column indices for SEL_FI_SMALL
+
+ public static final int IDX_FI_SMALL_ID = 0;
+ public static final int IDX_FI_SMALL_TITLE = 1;
+ public static final int IDX_FI_SMALL_PUBDATE = 2;
+ public static final int IDX_FI_SMALL_READ = 3;
+ public static final int IDX_FI_SMALL_LINK = 4;
+ public static final int IDX_FI_SMALL_PAYMENT_LINK = 5;
+ public static final int IDX_FI_SMALL_MEDIA = 6;
+ public static final int IDX_FI_SMALL_FEED = 7;
+ public static final int IDX_FI_SMALL_HAS_CHAPTERS = 8;
+ public static final int IDX_FI_SMALL_ITEM_IDENTIFIER = 9;
+
+ /** Select id, description and content-encoded column from feeditems. */
+ public static final String[] SEL_FI_EXTRA = { KEY_ID, KEY_DESCRIPTION,
+ KEY_CONTENT_ENCODED, KEY_FEED };
+
+ // column indices for SEL_FI_EXTRA
+
+ public static final int IDX_FI_EXTRA_ID = 0;
+ public static final int IDX_FI_EXTRA_DESCRIPTION = 1;
+ public static final int IDX_FI_EXTRA_CONTENT_ENCODED = 2;
+ public static final int IDX_FI_EXTRA_FEED = 3;
+
+
public PodDBAdapter(Context c) {
this.context = c;
helper = new PodDBHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -280,7 +313,8 @@ public class PodDBAdapter {
values.put(KEY_DOWNLOADED, media.isDownloaded());
values.put(KEY_FILE_URL, media.getFile_url());
if (media.getPlaybackCompletionDate() != null) {
- values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime());
+ values.put(KEY_PLAYBACK_COMPLETION_DATE, media
+ .getPlaybackCompletionDate().getTime());
} else {
values.put(KEY_PLAYBACK_COMPLETION_DATE, 0);
}
@@ -324,8 +358,12 @@ public class PodDBAdapter {
ContentValues values = new ContentValues();
values.put(KEY_TITLE, item.getTitle());
values.put(KEY_LINK, item.getLink());
- values.put(KEY_DESCRIPTION, item.getDescription());
- values.put(KEY_CONTENT_ENCODED, item.getContentEncoded());
+ if (item.getDescription() != null) {
+ values.put(KEY_DESCRIPTION, item.getDescription());
+ }
+ if (item.getContentEncoded() != null) {
+ values.put(KEY_CONTENT_ENCODED, item.getContentEncoded());
+ }
values.put(KEY_PUBDATE, item.getPubDate().getTime());
values.put(KEY_PAYMENT_LINK, item.getPaymentLink());
if (item.getMedia() != null) {
@@ -471,7 +509,7 @@ public class PodDBAdapter {
}
/**
- * Returns a cursor with all FeedItems of a Feed.
+ * Returns a cursor with all FeedItems of a Feed. Uses SEL_FI_SMALL
*
* @param feed
* The feed you want to get the FeedItems from.
@@ -479,9 +517,18 @@ public class PodDBAdapter {
* */
public final Cursor getAllItemsOfFeedCursor(final Feed feed) {
open();
+ Cursor c = db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_SMALL, KEY_FEED
+ + "=?", new String[] { String.valueOf(feed.getId()) }, null,
+ null, null);
+ return c;
+ }
+
+ /** Return a cursor with the SEL_FI_EXTRA selection of a single feeditem. */
+ public final Cursor getExtraInformationOfItem(final FeedItem item) {
+ open();
Cursor c = db
- .query(TABLE_NAME_FEED_ITEMS, null, KEY_FEED + "=?",
- new String[] { String.valueOf(feed.getId()) }, null,
+ .query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA, KEY_ID + "=?",
+ new String[] { String.valueOf(item.getId()) }, null,
null, null);
return c;
}
@@ -603,6 +650,47 @@ public class PodDBAdapter {
return image;
}
+ /**
+ * Searches for the given query in the description of all items or the items
+ * of a specified feed.
+ *
+ * @return A cursor with all search results in SEL_FI_EXTRA selection.
+ * */
+ public Cursor searchItemDescriptions(Feed feed, String query) {
+ if (feed != null) {
+ // search items in specific feed
+ return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA, KEY_FEED
+ + "=? AND " + KEY_DESCRIPTION + " LIKE '%" + query + "%'", new String[] {
+ String.valueOf(feed.getId()) }, null, null, null);
+ } else {
+ // search through all items
+ return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA,
+ KEY_DESCRIPTION + " LIKE '%" + query + "%'", null, null,
+ null, null);
+ }
+ }
+
+ /**
+ * Searches for the given query in the content-encoded field of all items or
+ * the items of a specified feed.
+ *
+ * @return A cursor with all search results in SEL_FI_EXTRA selection.
+ * */
+ public Cursor searchItemContentEncoded(Feed feed, String query) {
+ if (feed != null) {
+ // search items in specific feed
+ return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA, KEY_FEED
+ + "=? AND " + KEY_CONTENT_ENCODED + " LIKE '%" + query + "%'",
+ new String[] { String.valueOf(feed.getId())}, null,
+ null, null);
+ } else {
+ // search through all items
+ return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA,
+ KEY_CONTENT_ENCODED + " LIKE '%" + query + "%'", null,
+ null, null, null);
+ }
+ }
+
/** Helper class for opening the Antennapod database. */
private static class PodDBHelper extends SQLiteOpenHelper {
/**