summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/de/danoeh/antennapod/activity/SearchActivity.java2
-rw-r--r--src/de/danoeh/antennapod/feed/FeedManager.java98
-rw-r--r--src/de/danoeh/antennapod/feed/FeedSearcher.java157
-rw-r--r--src/de/danoeh/antennapod/storage/PodDBAdapter.java12
4 files changed, 183 insertions, 86 deletions
diff --git a/src/de/danoeh/antennapod/activity/SearchActivity.java b/src/de/danoeh/antennapod/activity/SearchActivity.java
index a073b43cc..8bc38fa5b 100644
--- a/src/de/danoeh/antennapod/activity/SearchActivity.java
+++ b/src/de/danoeh/antennapod/activity/SearchActivity.java
@@ -149,7 +149,7 @@ public class SearchActivity extends SherlockListActivity {
protected ArrayList<SearchResult> doInBackground(String... params) {
if (AppConfig.DEBUG)
Log.d(TAG, "Starting background work");
- return FeedSearcher.performSearch(params[0], selectedFeed);
+ return FeedSearcher.performSearch(SearchActivity.this, params[0], selectedFeed);
}
@Override
diff --git a/src/de/danoeh/antennapod/feed/FeedManager.java b/src/de/danoeh/antennapod/feed/FeedManager.java
index 479ce9732..285fc3539 100644
--- a/src/de/danoeh/antennapod/feed/FeedManager.java
+++ b/src/de/danoeh/antennapod/feed/FeedManager.java
@@ -1012,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) {
@@ -1346,32 +1359,28 @@ public class FeedManager {
public void searchFeedItemDescription(final Context context,
final Feed feed, final String query,
- FeedManager.TaskCallback callback) {
- dbExec.execute(new FeedManager.Task(new Handler(), callback) {
-
+ FeedManager.QueryTaskCallback callback) {
+ dbExec.execute(new FeedManager.QueryTask(context, new Handler(), callback) {
+
@Override
- public void execute() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- Cursor searchResult = adapter.searchItemDescriptions(feed, query);
+ public void execute(PodDBAdapter adapter) {
+ Cursor searchResult = adapter.searchItemDescriptions(feed,
+ query);
setResult(searchResult);
- adapter.close();
}
});
}
-
+
public void searchFeedItemContentEncoded(final Context context,
final Feed feed, final String query,
- FeedManager.TaskCallback callback) {
- dbExec.execute(new FeedManager.Task(new Handler(), callback) {
-
+ FeedManager.QueryTaskCallback callback) {
+ dbExec.execute(new FeedManager.QueryTask(context, new Handler(), callback) {
+
@Override
- public void execute() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- Cursor searchResult = adapter.searchItemContentEncoded(feed, query);
+ public void execute(PodDBAdapter adapter) {
+ Cursor searchResult = adapter.searchItemContentEncoded(feed,
+ query);
setResult(searchResult);
- adapter.close();
}
});
}
@@ -1400,15 +1409,18 @@ public class FeedManager {
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;
- /** Can be used for returning database query results. */
- private Cursor result;
-
/**
* Standard contructor. No callbacks are going to be posted to a
* handler.
@@ -1434,7 +1446,7 @@ public class FeedManager {
handler.post(new Runnable() {
@Override
public void run() {
- callback.onCompletion(result);
+ callback.onCompletion(null);
}
});
}
@@ -1442,11 +1454,53 @@ public class FeedManager {
/** 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/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
index 9026ad653..9b60521cf 100644
--- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java
+++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
@@ -660,12 +660,12 @@ public class PodDBAdapter {
if (feed != null) {
// search items in specific feed
return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA, KEY_FEED
- + "=? AND " + KEY_DESCRIPTION + " LIKE ?", new String[] {
- String.valueOf(feed.getId()), query }, null, null, null);
+ + "=? 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 ?", new String[] { query }, null,
+ KEY_DESCRIPTION + " LIKE '%" + query + "%'", null, null,
null, null);
}
}
@@ -680,13 +680,13 @@ public class PodDBAdapter {
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 ?",
- new String[] { String.valueOf(feed.getId()), query }, null,
+ + "=? 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 ?", new String[] { query },
+ KEY_CONTENT_ENCODED + " LIKE '%" + query + "%'", null,
null, null, null);
}
}