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 7524e5413..9fe351b4b 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
@@ -5,10 +5,9 @@ import static org.schabi.newpipe.MainActivity.DEBUG;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ClipboardManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
@@ -23,6 +22,7 @@ import androidx.core.content.FileProvider;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.RouterActivity;
import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.util.image.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
@@ -62,8 +62,9 @@ public final class ShareUtils {
}
/**
- * Open the url with the system default browser. If no browser is set as default, falls back to
- * {@link #openAppChooser(Context, Intent, boolean)}.
+ * Open the url with the system default browser. If no browser is installed, falls back to
+ * {@link #openAppChooser(Context, Intent, boolean)} (for displaying that no apps are available
+ * to handle the action, or possible OEM-related edge cases).
*
* 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.
@@ -77,44 +78,26 @@ public final class ShareUtils {
* @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.
+ // Target 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 `` in the manifest.
- final ResolveInfo defaultBrowserInfo;
final Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- defaultBrowserInfo = context.getPackageManager().resolveActivity(browserIntent,
- PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY));
- } else {
- defaultBrowserInfo = context.getPackageManager().resolveActivity(browserIntent,
- PackageManager.MATCH_DEFAULT_ONLY);
- }
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url))
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- if (defaultBrowserInfo == null) {
- // No app installed to open a web URL, but it may be handled by other apps so try
- // opening a system chooser for the link in this case (it could be bypassed by the
- // system if there is only one app which can open the link or a default app associated
- // with the link domain on Android 12 and higher)
+ // See https://stackoverflow.com/a/58801285 and `setSelector` documentation
+ intent.setSelector(browserIntent);
+ try {
+ context.startActivity(intent);
+ } catch (final ActivityNotFoundException e) {
+ // No browser is available. This should, in the end, yield a nice AOSP error message
+ // indicating that no app is available to handle this action.
+ //
+ // Note: there are some situations where modified OEM ROMs have apps that appear
+ // to be browsers but are actually app choosers. If starting the Activity fails
+ // related to this, opening the system app chooser is still the correct behavior.
+ intent.setSelector(null);
openAppChooser(context, intent, true);
- return;
- }
-
- final String defaultBrowserPackage = defaultBrowserInfo.activityInfo.packageName;
-
- if (defaultBrowserPackage.equals("android")) {
- // No browser set as default (doesn't work on some devices)
- openAppChooser(context, intent, true);
- } else {
- try {
- intent.setPackage(defaultBrowserPackage);
- context.startActivity(intent);
- } catch (final ActivityNotFoundException e) {
- // Not a browser but an app chooser because of OEMs changes
- intent.setPackage(null);
- openAppChooser(context, intent, true);
- }
}
}
@@ -190,6 +173,18 @@ public final class ShareUtils {
chooserIntent.putExtra(Intent.EXTRA_TITLE, context.getString(R.string.open_with));
}
+ // Avoid opening in NewPipe
+ // (Implementation note: if the URL is one for which NewPipe itself
+ // is set as handler on Android >= 12, we actually remove the only eligible app
+ // for this link, and browsers will not be offered to the user. For that, use
+ // `openUrlInBrowser`.)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ chooserIntent.putExtra(
+ Intent.EXTRA_EXCLUDE_COMPONENTS,
+ new ComponentName[]{new ComponentName(context, RouterActivity.class)}
+ );
+ }
+
// Migrate any clip data and flags from the original intent.
final int permFlags = intent.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION