diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ad03fc1e7..ecacd413c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -29,6 +29,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/searchlist_item.xml b/res/layout/searchlist_item.xml
new file mode 100644
index 000000000..13ad5d883
--- /dev/null
+++ b/res/layout/searchlist_item.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1c32ce086..2a00375d0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -136,6 +136,10 @@
The import directory is empty.
Select all
Deselect all
+ Search for Feeds or Episodes
+ Found in:\u0020
+ Found in shownotes
+ Found in chapters
\ No newline at end of file
diff --git a/res/xml/searchable.xml b/res/xml/searchable.xml
new file mode 100644
index 000000000..522bd9be5
--- /dev/null
+++ b/res/xml/searchable.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/de/danoeh/antennapod/AppConfig.java b/src/de/danoeh/antennapod/AppConfig.java
index ab3626388..7aab19fd3 100644
--- a/src/de/danoeh/antennapod/AppConfig.java
+++ b/src/de/danoeh/antennapod/AppConfig.java
@@ -1,5 +1,5 @@
package de.danoeh.antennapod;
public final class AppConfig {
- public final static boolean DEBUG = false;
+ public final static boolean DEBUG = true;
}
diff --git a/src/de/danoeh/antennapod/activity/SearchActivity.java b/src/de/danoeh/antennapod/activity/SearchActivity.java
new file mode 100644
index 000000000..9cc3b1717
--- /dev/null
+++ b/src/de/danoeh/antennapod/activity/SearchActivity.java
@@ -0,0 +1,70 @@
+package de.danoeh.antennapod.activity;
+
+import java.util.ArrayList;
+
+import android.annotation.SuppressLint;
+import android.app.SearchManager;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.actionbarsherlock.app.SherlockListActivity;
+
+import de.danoeh.antennapod.AppConfig;
+import de.danoeh.antennapod.adapter.SearchlistAdapter;
+import de.danoeh.antennapod.feed.FeedComponent;
+import de.danoeh.antennapod.feed.FeedSearcher;
+import de.danoeh.antennapod.feed.SearchResult;
+
+public class SearchActivity extends SherlockListActivity {
+ private static final String TAG = "SearchActivity";
+
+ private SearchlistAdapter searchAdapter;
+ private ArrayList content;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Starting search");
+ String query = getIntent().getStringExtra(SearchManager.QUERY);
+ startSearch(query);
+ }
+ }
+
+ @SuppressLint({ "NewApi", "NewApi" })
+ private void startSearch(String query) {
+ AsyncTask> executor = new AsyncTask>() {
+
+ @Override
+ protected ArrayList doInBackground(String... params) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Starting background work");
+ return FeedSearcher.performSearch(params[0]);
+ }
+
+ @Override
+ protected void onPostExecute(ArrayList 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 (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
+ executor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, query);
+ } else {
+ executor.execute(query);
+ }
+ }
+}
diff --git a/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java b/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java
new file mode 100644
index 000000000..e9cb3e290
--- /dev/null
+++ b/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java
@@ -0,0 +1,74 @@
+package de.danoeh.antennapod.adapter;
+
+import java.util.List;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+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.FeedComponent;
+import de.danoeh.antennapod.feed.FeedItem;
+import de.danoeh.antennapod.feed.SearchResult;
+
+/** List adapter for search activity. */
+public class SearchlistAdapter extends ArrayAdapter {
+
+ public SearchlistAdapter(Context context, int textViewResourceId,
+ List objects) {
+ super(context, textViewResourceId, objects);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ Holder holder;
+ SearchResult result = getItem(position);
+ FeedComponent component = result.getComponent();
+
+ // Inflate Layout
+ if (convertView == null) {
+ holder = new Holder();
+ LayoutInflater inflater = (LayoutInflater) getContext()
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ convertView = inflater.inflate(R.layout.searchlist_item, null);
+ holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
+ holder.cover = (ImageView) convertView
+ .findViewById(R.id.imgvFeedimage);
+ holder.subtitle = (TextView) convertView
+ .findViewById(R.id.txtvSubtitle);
+
+ convertView.setTag(holder);
+ } else {
+ holder = (Holder) convertView.getTag();
+ }
+ if (component.getClass() == Feed.class) {
+ Feed feed = (Feed) component;
+ holder.title.setText(feed.getTitle());
+ holder.subtitle.setVisibility(View.GONE);
+ FeedImageLoader.getInstance().loadBitmap(feed.getImage(),
+ holder.cover);
+
+ } else if (component.getClass() == FeedItem.class) {
+ FeedItem item = (FeedItem) component;
+ holder.title.setText(item.getTitle());
+ holder.subtitle.setVisibility(View.VISIBLE);
+ holder.subtitle.setText(result.getSubtitle());
+ FeedImageLoader.getInstance().loadBitmap(item.getFeed().getImage(),
+ holder.cover); }
+
+ return convertView;
+ }
+
+ static class Holder {
+ ImageView cover;
+ TextView title;
+ TextView subtitle;
+ }
+
+}
diff --git a/src/de/danoeh/antennapod/feed/FeedSearcher.java b/src/de/danoeh/antennapod/feed/FeedSearcher.java
new file mode 100644
index 000000000..ff9f5a4c8
--- /dev/null
+++ b/src/de/danoeh/antennapod/feed/FeedSearcher.java
@@ -0,0 +1,113 @@
+package de.danoeh.antennapod.feed;
+
+import java.util.ArrayList;
+
+import android.util.Log;
+
+import de.danoeh.antennapod.AppConfig;
+import de.danoeh.antennapod.PodcastApp;
+import de.danoeh.antennapod.R;
+
+/** Performs search on Feeds and FeedItems */
+public class FeedSearcher {
+ private static final String TAG = "FeedSearcher";
+
+ public static ArrayList performSearch(final String query) {
+ String lcQuery = query.toLowerCase();
+ ArrayList result = new ArrayList();
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Searching Feed titles");
+ searchFeedtitles(lcQuery, result);
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Searching Feeditem titles");
+ searchFeedItemTitles(lcQuery, result);
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Searching item-chaptertitles");
+
+ searchFeedItemChapters(lcQuery, result);
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Searching item descriptions");
+
+ searchFeedItemDescription(lcQuery, result);
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Searching item content encoded data");
+
+ searchFeedItemContentEncoded(lcQuery, result);
+ return result;
+ }
+
+ private static void searchFeedtitles(String query,
+ ArrayList destination) {
+ FeedManager manager = FeedManager.getInstance();
+ for (Feed feed : manager.getFeeds()) {
+ if (feed.getTitle().toLowerCase().contains(query)) {
+ destination.add(new SearchResult(feed, null));
+ }
+ }
+ }
+
+ private static void searchFeedItemTitles(String query,
+ ArrayList destination) {
+ FeedManager manager = FeedManager.getInstance();
+ for (Feed feed : manager.getFeeds()) {
+ for (FeedItem item : feed.getItems()) {
+ if (item.getTitle().toLowerCase().contains(query)) {
+ destination.add(new SearchResult(item, PodcastApp
+ .getInstance().getString(R.string.found_in_label)
+ + item.getFeed().getTitle()));
+ }
+ }
+ }
+ }
+
+ private static void searchFeedItemChapters(String query,
+ ArrayList destination) {
+ FeedManager manager = FeedManager.getInstance();
+ for (Feed feed : manager.getFeeds()) {
+ for (FeedItem item : feed.getItems()) {
+ if (item.getSimpleChapters() != null) {
+ for (SimpleChapter sc : item.getSimpleChapters()) {
+ if (sc.getTitle().toLowerCase().contains(query)) {
+ destination.add(new SearchResult(item, PodcastApp
+ .getInstance().getString(
+ R.string.found_in_chapters_label)));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static void searchFeedItemDescription(String query,
+ ArrayList destination) {
+ FeedManager manager = FeedManager.getInstance();
+ for (Feed feed : manager.getFeeds()) {
+ for (FeedItem item : feed.getItems()) {
+ if (item.getDescription() != null
+ && item.getDescription().toLowerCase().contains(query)) {
+ destination.add(new SearchResult(item, PodcastApp
+ .getInstance().getString(
+ R.string.found_in_shownotes_label)));
+ }
+ }
+ }
+ }
+
+ private static void searchFeedItemContentEncoded(String query,
+ ArrayList destination) {
+ FeedManager manager = FeedManager.getInstance();
+ for (Feed feed : manager.getFeeds()) {
+ for (FeedItem item : feed.getItems()) {
+ if (!destination.contains(item)
+ && item.getContentEncoded() != null
+ && item.getContentEncoded().toLowerCase()
+ .contains(query)) {
+ destination.add(new SearchResult(item, PodcastApp
+ .getInstance().getString(
+ R.string.found_in_shownotes_label)));
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/de/danoeh/antennapod/feed/SearchResult.java b/src/de/danoeh/antennapod/feed/SearchResult.java
new file mode 100644
index 000000000..3378918f7
--- /dev/null
+++ b/src/de/danoeh/antennapod/feed/SearchResult.java
@@ -0,0 +1,22 @@
+package de.danoeh.antennapod.feed;
+
+public class SearchResult {
+ private FeedComponent component;
+ /** Additional information (e.g. where it was found) */
+ private String subtitle;
+
+ public SearchResult(FeedComponent component, String subtitle) {
+ super();
+ this.component = component;
+ this.subtitle = subtitle;
+ }
+
+ public FeedComponent getComponent() {
+ return component;
+ }
+
+ public String getSubtitle() {
+ return subtitle;
+ }
+
+}