package com.battlelancer.seriesguide.util; import android.app.SearchManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import com.battlelancer.seriesguide.R; import com.squareup.picasso.NetworkPolicy; import com.squareup.picasso.Picasso; import com.squareup.picasso.RequestCreator; /** * Helper methods to interact with third-party services trakt and The Movie Database used within * SeriesGuide. */ public final class ServiceUtils { public static final String TAG = "Service Utils"; private static final String IMDB_APP_TITLE_URI_POSTFIX = "/"; private static final String IMDB_APP_TITLE_URI = "imdb:///title/"; public static final String IMDB_TITLE_URL = "http://imdb.com/title/"; private static final String TVDB_SHOW_URL = "http://thetvdb.com/?tab=series&id="; private static final String TVDB_EPISODE_URL = "http://thetvdb.com/?tab=episode&seriesid="; private static final String TVDB_EPISODE_URL_SEASON_PARAM = "&seasonid="; private static final String TVDB_EPISODE_URL_EPISODE_PARAM = "&id="; private static final String YOUTUBE_BASE_URL = "http://www.youtube.com/watch?v="; private static final String YOUTUBE_SEARCH = "http://www.youtube.com/results?search_query=%s"; private static final String YOUTUBE_PACKAGE = "com.google.android.youtube"; /* This class is never initialized */ private ServiceUtils() { } /** * Build Picasso {@link com.squareup.picasso.RequestCreator} which respects user requirement of * only loading images over WiFi. * * <p>If {@link Utils#isAllowedLargeDataConnection} is false, will set {@link * com.squareup.picasso.NetworkPolicy#OFFLINE} (which will set {@link * okhttp3.CacheControl#FORCE_CACHE} on requests) to skip the network and accept stale images. * * @param context {@link Context#getApplicationContext() context.getApplicationContext()} will * be used. */ @NonNull public static RequestCreator loadWithPicasso(Context context, String path) { RequestCreator requestCreator = Picasso.with(context).load(path); if (!Utils.isAllowedLargeDataConnection(context.getApplicationContext())) { // avoid the network, hit the cache immediately + accept stale images. requestCreator.networkPolicy(NetworkPolicy.OFFLINE); } return requestCreator; } /** * Displays the IMDb page for the given id (show or episode) in the IMDb app or on the imdb.com * web page. If the IMDb id is empty, disables the button. */ public static void setUpImdbButton(final String imdbId, View imdbButton, final String logTag) { if (imdbButton != null) { if (!TextUtils.isEmpty(imdbId)) { imdbButton.setEnabled(true); imdbButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { openImdb(imdbId, logTag, v.getContext()); } }); } else { imdbButton.setEnabled(false); } } } /** * Open the IMDb app or web page for the given IMDb id. */ public static void openImdb(String imdbId, String logTag, Context context) { if (context == null || TextUtils.isEmpty(imdbId)) { return; } // try launching the IMDb app Intent intent = new Intent(Intent.ACTION_VIEW, Uri .parse(IMDB_APP_TITLE_URI + imdbId + IMDB_APP_TITLE_URI_POSTFIX)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); } else { //noinspection deprecation intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); } if (Utils.tryStartActivity(context, intent, false)) { Utils.trackAction(context, logTag, "IMDb"); } else { // on failure, try launching the web page Utils.launchWebsite(context, IMDB_TITLE_URL + imdbId, logTag, "IMDb"); } } /** * Returns a view {@link android.content.Intent} for a search of Google Play's movies category * (includes TV shows). */ public static Intent buildGooglePlayIntent(String title, Context context) { Intent intent = new Intent(Intent.ACTION_VIEW); String playStoreQuery = String.format(context.getString(R.string.url_movies_search), Uri.encode(title)); intent.setData(Uri.parse(playStoreQuery)); return intent; } /** * Tries to open Google Play to search for the given tv show, episode or movie title. */ public static void searchGooglePlay(final String title, final String logTag, Context context) { Intent intent = buildGooglePlayIntent(title, context); Utils.openNewDocument(context, intent, logTag, "Google Play"); } public static void setUpTraktShowButton(@Nullable View button, final int showTvdbId, @NonNull final String logTag) { if (button != null) { button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // build url on demand String uri = TraktTools.buildShowUrl(showTvdbId); Utils.launchWebsite(v.getContext(), uri, logTag, "trakt"); } }); } } public static void setUpTraktEpisodeButton(@Nullable View button, final int episodeTvdbId, @NonNull final String logTag) { if (button != null) { button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // build url on demand String uri = TraktTools.buildEpisodeUrl(episodeTvdbId); Utils.launchWebsite(v.getContext(), uri, logTag, "trakt"); } }); } } /** * Starts activity with {@link Intent#ACTION_VIEW} to display the given show or episodes * TVDb.com page.<br> If any of the season or episode numbers is below 0, displays the show * page. */ public static void setUpTvdbButton(final int showTvdbId, final int seasonTvdbId, final int episodeTvdbId, final View tvdbButton, final String logTag) { if (tvdbButton != null) { tvdbButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String uri; if (seasonTvdbId < 0 || episodeTvdbId < 0) { // look just for the show page uri = TVDB_SHOW_URL + showTvdbId; } else { // look for the episode page uri = TVDB_EPISODE_URL + showTvdbId + TVDB_EPISODE_URL_SEASON_PARAM + seasonTvdbId + TVDB_EPISODE_URL_EPISODE_PARAM + episodeTvdbId; } Utils.launchWebsite(v.getContext(), uri, logTag, "TVDb"); } }); } } /** * Starts activity with {@link Intent#ACTION_VIEW} to display the given shows TVDb.com page. */ public static void setUpTvdbButton(final int showTvdbId, View tvdbButton, final String logTag) { setUpTvdbButton(showTvdbId, -1, -1, tvdbButton, logTag); } /** * Opens the YouTube app or web page for the given video. */ public static void openYoutube(String videoId, String logTag, Context context) { Utils.launchWebsite(context, YOUTUBE_BASE_URL + videoId, logTag, "YouTube"); } /** * Builds a search {@link android.content.Intent} to open the YouTube application to search for * <code>query</code>. If the YouTube app is unavailable, a view {@link android.content.Intent} * with the web search URL is returned instead. */ public static Intent buildYouTubeIntent(Context context, String query) { PackageManager pm = context.getPackageManager(); boolean hasYouTube; try { pm.getPackageInfo(YOUTUBE_PACKAGE, PackageManager.GET_ACTIVITIES); hasYouTube = true; } catch (PackageManager.NameNotFoundException notInstalled) { hasYouTube = false; } Intent intent; if (hasYouTube) { // Directly search the YouTube app intent = new Intent(Intent.ACTION_SEARCH); intent.setPackage(YOUTUBE_PACKAGE); intent.putExtra("query", query); } else { // Launch a web search intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(String.format(YOUTUBE_SEARCH, Uri.encode(query)))); } return intent; } /** * Builds a search {@link android.content.Intent} using {@link Intent#ACTION_WEB_SEARCH} and * <code>query</code> as {@link android.app.SearchManager#QUERY} extra. */ public static Intent buildWebSearchIntent(String query) { Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); intent.putExtra(SearchManager.QUERY, query); return intent; } /** * Attempts to search the web for <code>query</code>. * * @param context The {@link Context} to use * @param query The search query * @param logTag The log tag to use, for Analytics */ public static void performWebSearch(Context context, String query, String logTag) { Utils.openNewDocument(context, buildWebSearchIntent(query), logTag, "Web search"); } /** * Used to search the web for <code>query</code> * * @param query The search query for the YouTube app * @param button The {@link Button} used to invoke the {@link android.view.View.OnClickListener} * @param logTag The log tag to use, for Analytics */ public static void setUpWebSearchButton(final String query, View button, final String logTag) { if (button == null) { // Return if the button isn't initialized return; } else if (TextUtils.isEmpty(query)) { // Disable the button if there's nothing to search for button.setEnabled(false); return; } button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { performWebSearch(v.getContext(), query, logTag); } }); } }