- * For a list of supported urls see the
- *
- * Kore source code
- * .
- *
- * @param context the context to use
- * @param videoURL the url to the video
- */
- public static void playWithKore(final Context context, final Uri videoURL) {
- final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setPackage(context.getString(R.string.kore_package));
- intent.setData(videoURL);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
- }
-
/**
* Finish this Activity
as well as all Activities
running below it
* and then start MainActivity
.
diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/KoreUtils.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/KoreUtils.java
index 0df579d88..4dc9c7c07 100644
--- a/app/src/main/java/org/schabi/newpipe/util/external_communication/KoreUtils.java
+++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/KoreUtils.java
@@ -1,6 +1,11 @@
package org.schabi.newpipe.util.external_communication;
+import static org.schabi.newpipe.util.external_communication.ShareUtils.installApp;
+import static org.schabi.newpipe.util.external_communication.ShareUtils.tryOpenIntentInApp;
+
import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
@@ -8,7 +13,6 @@ import androidx.preference.PreferenceManager;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.ServiceList;
-import org.schabi.newpipe.util.NavigationHelper;
/**
* Util class that provides methods which are related to the Kodi Media Center and its Kore app.
@@ -29,13 +33,39 @@ public final class KoreUtils {
.getBoolean(context.getString(R.string.show_play_with_kodi_key), false);
}
- public static void showInstallKoreDialog(@NonNull final Context context) {
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setMessage(R.string.kore_not_found)
- .setPositiveButton(R.string.install, (dialog, which) ->
- NavigationHelper.installKore(context))
- .setNegativeButton(R.string.cancel, (dialog, which) -> {
- });
- builder.create().show();
+ /**
+ * Start an activity to install Kore.
+ *
+ * @param context the context to use
+ */
+ public static void installKore(final Context context) {
+ installApp(context, context.getString(R.string.kore_package));
+ }
+
+ /**
+ * Start Kore app to show a video on Kodi, and if the app is not installed ask the user to
+ * install it.
+ *
+ * For a list of supported urls see the + * + * Kore source code + * . + * + * @param context the context to use + * @param streamUrl the url to the stream to play + */ + public static void playWithKore(final Context context, final Uri streamUrl) { + final Intent intent = new Intent(Intent.ACTION_VIEW) + .setPackage(context.getString(R.string.kore_package)) + .setData(streamUrl) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + if (!tryOpenIntentInApp(context, intent)) { + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setMessage(R.string.kore_not_found) + .setPositiveButton(R.string.install, (dialog, which) -> installKore(context)) + .setNegativeButton(R.string.cancel, (dialog, which) -> { }); + builder.create().show(); + } } } diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java index 06dd3f945..2f50a94ae 100644 --- a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java @@ -41,60 +41,67 @@ public final class ShareUtils { * second param (a system chooser will be opened if there are multiple markets and no default) * and falls back to Google Play Store web URL if no app to handle the market scheme was found. *
- * It uses {@link #openIntentInApp(Context, Intent, boolean)} to open market scheme - * and {@link #openUrlInBrowser(Context, String, boolean)} to open Google Play Store - * web URL with false for the boolean param. + * It uses {@link #openIntentInApp(Context, Intent)} to open market scheme and {@link + * #openUrlInBrowser(Context, String)} to open Google Play Store web URL. * * @param context the context to use * @param packageId the package id of the app to be installed */ public static void installApp(@NonNull final Context context, final String packageId) { // Try market scheme - final boolean marketSchemeResult = openIntentInApp(context, new Intent(Intent.ACTION_VIEW, + final Intent marketSchemeIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageId)) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), false); - if (!marketSchemeResult) { + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (!tryOpenIntentInApp(context, marketSchemeIntent)) { // Fall back to Google Play Store Web URL (F-Droid can handle it) - openUrlInBrowser(context, - "https://play.google.com/store/apps/details?id=" + packageId, false); + openUrlInApp(context, "https://play.google.com/store/apps/details?id=" + packageId); } } /** - * Open the url with the system default browser. + * Open the url with the system default browser. If no browser is set as default, falls back to + * {@link #openAppChooser(Context, Intent, boolean)}. *
- * If no browser is set as default, fallbacks to - * {@link #openAppChooser(Context, Intent, boolean)} + * This function selects the package to open based on which apps respond to the {@code http://} + * schema alone, which should exclude special non-browser apps that are can handle the url (e.g. + * the official YouTube app). + *
+ * Therefore please prefer {@link #openUrlInApp(Context, String)}, that handles package
+ * resolution in a standard way, unless this is the action of an explicit "Open in browser"
+ * button.
*
- * @param context the context to use
- * @param url the url to browse
- * @param httpDefaultBrowserTest the boolean to set if the test for the default browser will be
- * for HTTP protocol or for the created intent
- * @return true if the URL can be opened or false if it cannot
- */
- public static boolean openUrlInBrowser(@NonNull final Context context,
- final String url,
- final boolean httpDefaultBrowserTest) {
- final String defaultPackageName;
+ * @param context the context to use
+ * @param url the url to browse
+ **/
+ public static void openUrlInBrowser(@NonNull final Context context, final String url) {
+ // Resolve using a generic http://, so we are sure to get a browser and not e.g. the yt app.
+ // Note that this requires the `http` schema to be added to `
- * If no browser is set as default, fallbacks to
- * {@link #openAppChooser(Context, Intent, boolean)}
- *
- * This calls {@link #openUrlInBrowser(Context, String, boolean)} with true
- * for the boolean parameter
+ * Open a url with the system default app using {@link Intent#ACTION_VIEW}, showing a toast in
+ * case of failure.
*
* @param context the context to use
- * @param url the url to browse
- * @return true if the URL can be opened or false if it cannot be
- **/
- public static boolean openUrlInBrowser(@NonNull final Context context, final String url) {
- return openUrlInBrowser(context, url, true);
+ * @param url the url to open
+ */
+ public static void openUrlInApp(@NonNull final Context context, final String url) {
+ openIntentInApp(context, new Intent(Intent.ACTION_VIEW, Uri.parse(url))
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
/**
* Open an intent with the system default app.
*
- * The intent can be of every type, excepted a web intent for which
- * {@link #openUrlInBrowser(Context, String, boolean)} should be used.
- *
- * If no app can open the intent, a toast with the message {@code No app on your device can
- * open this} is shown.
+ * Use {@link #openIntentInApp(Context, Intent)} to show a toast in case of failure.
*
- * @param context the context to use
- * @param intent the intent to open
- * @param showToast a boolean to set if a toast is displayed to user when no app is installed
- * to open the intent (true) or not (false)
- * @return true if the intent can be opened or false if it cannot be
+ * @param context the context to use
+ * @param intent the intent to open
+ * @return true if the intent could be opened successfully, false otherwise
*/
- public static boolean openIntentInApp(@NonNull final Context context,
- @NonNull final Intent intent,
- final boolean showToast) {
- final String defaultPackageName = getDefaultAppPackageName(context, intent);
-
- if (defaultPackageName.isEmpty()) {
- // No app installed to open the intent
- if (showToast) {
- Toast.makeText(context, R.string.no_app_to_open_intent, Toast.LENGTH_LONG)
- .show();
- }
- return false;
- } else {
+ public static boolean tryOpenIntentInApp(@NonNull final Context context,
+ @NonNull final Intent intent) {
+ try {
context.startActivity(intent);
+ } catch (final ActivityNotFoundException e) {
+ return false;
}
-
return true;
}
+ /**
+ * Open an intent with the system default app, showing a toast in case of failure.
+ *
+ * Use {@link #tryOpenIntentInApp(Context, Intent)} if you don't want the toast. Use {@link
+ * #openUrlInApp(Context, String)} as a shorthand for {@link Intent#ACTION_VIEW} with urls.
+ *
+ * @param context the context to use
+ * @param intent the intent to
+ */
+ public static void openIntentInApp(@NonNull final Context context,
+ @NonNull final Intent intent) {
+ if (!tryOpenIntentInApp(context, intent)) {
+ Toast.makeText(context, R.string.no_app_to_open_intent, Toast.LENGTH_LONG)
+ .show();
+ }
+ }
+
/**
* Open the system chooser to launch an intent.
*
@@ -206,31 +208,6 @@ public final class ShareUtils {
context.startActivity(chooserIntent);
}
- /**
- * Get the default app package name.
- *
- * If no app is set as default, it will return "android" (not on some devices because some
- * OEMs changed the app chooser).
- *
- * If no app is installed on user's device to handle the intent, it will return an empty string.
- *
- * @param context the context to use
- * @param intent the intent to get default app
- * @return the package name of the default app, an empty string if there's no app installed to
- * handle the intent or the app chooser if there's no default
- */
- private static String getDefaultAppPackageName(@NonNull final Context context,
- @NonNull final Intent intent) {
- final ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent,
- PackageManager.MATCH_DEFAULT_ONLY);
-
- if (resolveInfo == null) {
- return "";
- } else {
- return resolveInfo.activityInfo.packageName;
- }
- }
-
/**
* Open the android share sheet to share a content.
*
diff --git a/app/src/main/java/org/schabi/newpipe/util/text/UrlLongPressClickableSpan.java b/app/src/main/java/org/schabi/newpipe/util/text/UrlLongPressClickableSpan.java
index eb0d7425e..61c1a546d 100644
--- a/app/src/main/java/org/schabi/newpipe/util/text/UrlLongPressClickableSpan.java
+++ b/app/src/main/java/org/schabi/newpipe/util/text/UrlLongPressClickableSpan.java
@@ -30,7 +30,7 @@ final class UrlLongPressClickableSpan extends LongPressClickableSpan {
public void onClick(@NonNull final View view) {
if (!InternalUrlsHandler.handleUrlDescriptionTimestamp(
disposables, context, url)) {
- ShareUtils.openUrlInBrowser(context, url, false);
+ ShareUtils.openUrlInApp(context, url);
}
}
diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
index bfb6a15e2..695e7aead 100644
--- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
+++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
@@ -1,6 +1,5 @@
package us.shandian.giga.ui.adapter;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
import static us.shandian.giga.get.DownloadMission.ERROR_CONNECT_HOST;
@@ -345,16 +344,7 @@ public class MissionAdapter extends Adapter