summaryrefslogtreecommitdiff
path: root/app/src/main/java/de/danoeh/antennapod
diff options
context:
space:
mode:
authorTom Hennen <TomHennen@users.noreply.github.com>2016-01-24 18:32:37 -0500
committerTom Hennen <TomHennen@users.noreply.github.com>2016-01-24 18:32:37 -0500
commit0eefa8c5412bf15c00fd83f318629377b4805c20 (patch)
tree2209e743a085de53ae6829bb4436210aa1842681 /app/src/main/java/de/danoeh/antennapod
parentb0f65e1b64a6226de53cec2ad110b4f2cd0c2d92 (diff)
parent5a077774fcfeb89fc3eac6993c4320d81c5ed157 (diff)
downloadAntennaPod-0eefa8c5412bf15c00fd83f318629377b4805c20.zip
Merge pull request #1576 from mfietz/issue/1553-itunes-search
iTunes Search improvement
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java51
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java247
2 files changed, 246 insertions, 52 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
index 08ffdd197..47ac4c757 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
@@ -10,6 +10,7 @@ import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -65,6 +66,12 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
//Set the title
viewHolder.titleView.setText(podcast.title);
+ if(!podcast.feedUrl.contains("itunes.apple.com")) {
+ viewHolder.urlView.setText(podcast.feedUrl);
+ viewHolder.urlView.setVisibility(View.VISIBLE);
+ } else {
+ viewHolder.urlView.setVisibility(View.GONE);
+ }
//Update the empty imageView with the image from the feed
Glide.with(context)
@@ -94,6 +101,8 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
*/
public final TextView titleView;
+ public final TextView urlView;
+
/**
* Constructor
@@ -102,6 +111,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
PodcastViewHolder(View view){
coverView = (ImageView) view.findViewById(R.id.imgvCover);
titleView = (TextView) view.findViewById(R.id.txtvTitle);
+ urlView = (TextView) view.findViewById(R.id.txtvUrl);
}
}
@@ -124,16 +134,47 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
*/
public final String feedUrl;
+
+ private Podcast(String title, String imageUrl, String feedUrl) {
+ this.title = title;
+ this.imageUrl = imageUrl;
+ this.feedUrl = feedUrl;
+ }
+
+ /**
+ * Constructs a Podcast instance from a iTunes search result
+ *
+ * @param json object holding the podcast information
+ * @throws JSONException
+ */
+ public static Podcast fromSearch(JSONObject json) throws JSONException {
+ String title = json.getString("collectionName");
+ String imageUrl = json.getString("artworkUrl100");
+ String feedUrl = json.getString("feedUrl");
+ return new Podcast(title, imageUrl, feedUrl);
+ }
+
/**
- * Constructor.
+ * Constructs a Podcast instance from iTunes toplist entry
*
* @param json object holding the podcast information
* @throws JSONException
*/
- public Podcast(JSONObject json) throws JSONException {
- title = json.getString("collectionName");
- imageUrl = json.getString("artworkUrl100");
- feedUrl = json.getString("feedUrl");
+ public static Podcast fromToplist(JSONObject json) throws JSONException {
+ String title = json.getJSONObject("title").getString("label");
+ String imageUrl = null;
+ JSONArray images = json.getJSONArray("im:image");
+ for(int i=0; imageUrl == null && i < images.length(); i++) {
+ JSONObject image = images.getJSONObject(i);
+ String height = image.getJSONObject("attributes").getString("height");
+ if(Integer.valueOf(height) >= 100) {
+ imageUrl = image.getString("label");
+ }
+ }
+ String feedUrl = "https://itunes.apple.com/lookup?id=" +
+ json.getJSONObject("id").getJSONObject("attributes").getString("im:id");
+ return new Podcast(title, imageUrl, feedUrl);
}
+
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
index e92df4885..eb947dc2b 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
@@ -1,17 +1,23 @@
package de.danoeh.antennapod.fragment;
import android.content.Intent;
-import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.Fragment;
+import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
+import android.widget.Button;
import android.widget.GridView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import com.afollestad.materialdialogs.MaterialDialog;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
@@ -25,13 +31,14 @@ import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
import de.danoeh.antennapod.adapter.itunes.ItunesAdapter;
import de.danoeh.antennapod.core.ClientConfig;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
+import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
@@ -46,21 +53,22 @@ public class ItunesSearchFragment extends Fragment {
private static final String API_URL = "https://itunes.apple.com/search?media=podcast&term=%s";
- /**
- * Search input field
- */
- private SearchView searchView;
/**
* Adapter responsible with the search results
*/
private ItunesAdapter adapter;
+ private GridView gridView;
+ private ProgressBar progressBar;
+ private TextView txtvError;
+ private Button butRetry;
+ private TextView txtvEmpty;
/**
* List of podcasts retreived from the search
*/
private List<Podcast> searchResults;
-
+ private List<Podcast> topList;
private Subscription subscription;
/**
@@ -70,13 +78,17 @@ public class ItunesSearchFragment extends Fragment {
void updateData(List<Podcast> result) {
this.searchResults = result;
adapter.clear();
-
- //ArrayAdapter.addAll() requires minsdk > 10
- for(Podcast p: result) {
- adapter.add(p);
+ if (result != null && result.size() > 0) {
+ gridView.setVisibility(View.VISIBLE);
+ txtvEmpty.setVisibility(View.GONE);
+ for (Podcast p : result) {
+ adapter.add(p);
+ }
+ adapter.notifyDataSetInvalidated();
+ } else {
+ gridView.setVisibility(View.GONE);
+ txtvEmpty.setVisibility(View.VISIBLE);
}
-
- adapter.notifyDataSetInvalidated();
}
/**
@@ -89,47 +101,105 @@ public class ItunesSearchFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- adapter = new ItunesAdapter(getActivity(), new ArrayList<Podcast>());
-
+ setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
- View view = inflater.inflate(R.layout.fragment_itunes_search, container, false);
- GridView gridView = (GridView) view.findViewById(R.id.gridView);
+ View root = inflater.inflate(R.layout.fragment_itunes_search, container, false);
+ gridView = (GridView) root.findViewById(R.id.gridView);
+ adapter = new ItunesAdapter(getActivity(), new ArrayList<>());
gridView.setAdapter(adapter);
//Show information about the podcast when the list item is clicked
- gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Intent intent = new Intent(getActivity(),
- OnlineFeedViewActivity.class);
-
- //Tell the OnlineFeedViewActivity where to go
- String url = searchResults.get(position).feedUrl;
- intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, url);
-
+ gridView.setOnItemClickListener((parent, view1, position, id) -> {
+ Podcast podcast = searchResults.get(position);
+ if (!podcast.feedUrl.contains("itunes.apple.com")) {
+ Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
+ intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, podcast.feedUrl);
intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, "iTunes");
startActivity(intent);
+ } else {
+ gridView.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ rx.Observable.create((Observable.OnSubscribe<String>) subscriber -> {
+ OkHttpClient client = AntennapodHttpClient.getHttpClient();
+ Request.Builder httpReq = new Request.Builder()
+ .url(podcast.feedUrl)
+ .header("User-Agent", ClientConfig.USER_AGENT);
+ try {
+ Response response = client.newCall(httpReq.build()).execute();
+ if (response.isSuccessful()) {
+ String resultString = response.body().string();
+ JSONObject result = new JSONObject(resultString);
+ JSONObject results = result.getJSONArray("results").getJSONObject(0);
+ String feedUrl = results.getString("feedUrl");
+ subscriber.onNext(feedUrl);
+ } else {
+ String prefix = getString(R.string.error_msg_prefix);
+ subscriber.onError(new IOException(prefix + response));
+ }
+ } catch (IOException | JSONException e) {
+ subscriber.onError(e);
+ }
+ subscriber.onCompleted();
+ })
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(feedUrl -> {
+ progressBar.setVisibility(View.GONE);
+ gridView.setVisibility(View.VISIBLE);
+ Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
+ intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, feedUrl);
+ intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, "iTunes");
+ startActivity(intent);
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ progressBar.setVisibility(View.GONE);
+ gridView.setVisibility(View.VISIBLE);
+ String prefix = getString(R.string.error_msg_prefix);
+ new MaterialDialog.Builder(getActivity())
+ .content(prefix + " " + error.getMessage())
+ .neutralText(android.R.string.ok)
+ .show();
+ });
}
});
+ progressBar = (ProgressBar) root.findViewById(R.id.progressBar);
+ txtvError = (TextView) root.findViewById(R.id.txtvError);
+ butRetry = (Button) root.findViewById(R.id.butRetry);
+ txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
+
+ loadToplist();
+
+ return root;
+ }
- //Configure search input view to be expanded by default with a visible submit button
- searchView = (SearchView) view.findViewById(R.id.itunes_search_view);
- searchView.setIconifiedByDefault(false);
- searchView.setIconified(false);
- searchView.setSubmitButtonEnabled(true);
- searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (subscription != null) {
+ subscription.unsubscribe();
+ }
+ adapter = null;
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.itunes_search, menu);
+ MenuItem searchItem = menu.findItem(R.id.action_search);
+ final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
+ MenuItemUtils.adjustTextColor(getActivity(), sv);
+ sv.setQueryHint(getString(R.string.search_itunes_label));
+ sv.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
- //This prevents onQueryTextSubmit() from being called twice when keyboard is used
- //to submit the query.
- searchView.clearFocus();
+ sv.clearFocus();
search(s);
- return false;
+ return true;
}
@Override
@@ -137,21 +207,97 @@ public class ItunesSearchFragment extends Fragment {
return false;
}
});
+ MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ return true;
+ }
- SearchView.SearchAutoComplete textField = (SearchView.SearchAutoComplete) searchView.findViewById(de.danoeh.antennapod.R.id.search_src_text);
- if(UserPreferences.getTheme() == de.danoeh.antennapod.R.style.Theme_AntennaPod_Dark) {
- textField.setTextColor(Resources.getSystem().getColor(android.R.color.white));
- } else {
- textField.setTextColor(Resources.getSystem().getColor(android.R.color.black));
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ if(searchResults != null) {
+ searchResults = null;
+ updateData(topList);
+ }
+ return true;
+ }
+ });
+ }
+
+ private void loadToplist() {
+ if (subscription != null) {
+ subscription.unsubscribe();
}
+ gridView.setVisibility(View.GONE);
+ txtvError.setVisibility(View.GONE);
+ butRetry.setVisibility(View.GONE);
+ txtvEmpty.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ subscription = rx.Observable.create((Observable.OnSubscribe<List<Podcast>>) subscriber -> {
+ String lang = Locale.getDefault().getLanguage();
+ String url = "https://itunes.apple.com/" + lang + "/rss/toppodcasts/limit=25/explicit=true/json";
+ OkHttpClient client = AntennapodHttpClient.getHttpClient();
+ Request.Builder httpReq = new Request.Builder()
+ .url(url)
+ .header("User-Agent", ClientConfig.USER_AGENT);
+ List<Podcast> results = new ArrayList<>();
+ try {
+ Response response = client.newCall(httpReq.build()).execute();
+ if(!response.isSuccessful()) {
+ // toplist for language does not exist, fall back to united states
+ url = "https://itunes.apple.com/us/rss/toppodcasts/limit=25/explicit=true/json";
+ httpReq = new Request.Builder()
+ .url(url)
+ .header("User-Agent", ClientConfig.USER_AGENT);
+ response = client.newCall(httpReq.build()).execute();
+ }
+ if(response.isSuccessful()) {
+ String resultString = response.body().string();
+ JSONObject result = new JSONObject(resultString);
+ JSONObject feed = result.getJSONObject("feed");
+ JSONArray entries = feed.getJSONArray("entry");
- return view;
+ for(int i=0; i < entries.length(); i++) {
+ JSONObject json = entries.getJSONObject(i);
+ Podcast podcast = Podcast.fromToplist(json);
+ results.add(podcast);
+ }
+ }
+ else {
+ String prefix = getString(R.string.error_msg_prefix);
+ subscriber.onError(new IOException(prefix + response));
+ }
+ } catch (IOException | JSONException e) {
+ subscriber.onError(e);
+ }
+ subscriber.onNext(results);
+ subscriber.onCompleted();
+ })
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(podcasts -> {
+ progressBar.setVisibility(View.GONE);
+ topList = podcasts;
+ updateData(topList);
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ progressBar.setVisibility(View.GONE);
+ txtvError.setText(error.toString());
+ txtvError.setVisibility(View.VISIBLE);
+ butRetry.setOnClickListener(v -> loadToplist());
+ butRetry.setVisibility(View.VISIBLE);
+ });
}
private void search(String query) {
if (subscription != null) {
subscription.unsubscribe();
}
+ gridView.setVisibility(View.GONE);
+ txtvError.setVisibility(View.GONE);
+ butRetry.setVisibility(View.GONE);
+ txtvEmpty.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
subscription = rx.Observable.create((Observable.OnSubscribe<List<Podcast>>) subscriber -> {
String encodedQuery = null;
try {
@@ -181,15 +327,16 @@ public class ItunesSearchFragment extends Fragment {
for (int i = 0; i < j.length(); i++) {
JSONObject podcastJson = j.getJSONObject(i);
- Podcast podcast = new Podcast(podcastJson);
+ Podcast podcast = Podcast.fromSearch(podcastJson);
podcasts.add(podcast);
}
}
else {
- subscriber.onError(new IOException("Unexpected error: " + response));
+ String prefix = getString(R.string.error_msg_prefix);
+ subscriber.onError(new IOException(prefix + response));
}
} catch (IOException | JSONException e) {
- Log.e(TAG, Log.getStackTraceString(e));
+ subscriber.onError(e);
}
subscriber.onNext(podcasts);
subscriber.onCompleted();
@@ -197,9 +344,15 @@ public class ItunesSearchFragment extends Fragment {
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(podcasts -> {
+ progressBar.setVisibility(View.GONE);
updateData(podcasts);
}, error -> {
Log.e(TAG, Log.getStackTraceString(error));
+ progressBar.setVisibility(View.GONE);
+ txtvError.setText(error.toString());
+ txtvError.setVisibility(View.VISIBLE);
+ butRetry.setOnClickListener(v -> search(query));
+ butRetry.setVisibility(View.VISIBLE);
});
}