1package com.cheogram.android;
2
3import android.content.Intent;
4import android.Manifest;
5import android.annotation.SuppressLint;
6import android.content.Context;
7import android.content.pm.PackageManager;
8import android.content.pm.ResolveInfo;
9import android.database.Cursor;
10import android.net.Uri;
11import android.os.Build;
12import android.content.ActivityNotFoundException;
13import java.util.HashSet;
14import java.util.List;
15import java.util.Set;
16import androidx.browser.customtabs.CustomTabsIntent;
17
18import eu.siacs.conversations.ui.XmppActivity;
19
20public class BrowserHelper {
21 static boolean launchNativeApi30(Context context, Uri uri) {
22 Intent nativeAppIntent = new Intent(Intent.ACTION_VIEW, uri)
23 .addCategory(Intent.CATEGORY_BROWSABLE)
24 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
25 Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER);
26 try {
27 context.startActivity(nativeAppIntent);
28 return true;
29 } catch (ActivityNotFoundException ex) {
30 return false;
31 }
32 }
33
34 private static Set<String> extractPackageNames(List<ResolveInfo> infos) {
35 Set<String> names = new HashSet<>();
36 for (ResolveInfo resolveInfo : infos) {
37 String packageName = resolveInfo.activityInfo.packageName;
38 names.add(packageName);
39 }
40 return names;
41 }
42
43 private static boolean launchNativeBeforeApi30(Context context, Uri uri) {
44 PackageManager pm = context.getPackageManager();
45
46 // Get all Apps that resolve a generic url
47 Intent browserActivityIntent = new Intent()
48 .setAction(Intent.ACTION_VIEW)
49 .addCategory(Intent.CATEGORY_BROWSABLE)
50 .setData(Uri.fromParts("http", "", null));
51 Set<String> genericResolvedList = extractPackageNames(
52 pm.queryIntentActivities(browserActivityIntent, 0));
53
54 // Get all apps that resolve the specific Url
55 Intent specializedActivityIntent = new Intent(Intent.ACTION_VIEW, uri)
56 .addCategory(Intent.CATEGORY_BROWSABLE);
57 Set<String> resolvedSpecializedList = extractPackageNames(
58 pm.queryIntentActivities(specializedActivityIntent, 0));
59
60 // Keep only the Urls that resolve the specific, but not the generic
61 // urls.
62 resolvedSpecializedList.removeAll(genericResolvedList);
63
64 // If the list is empty, no native app handlers were found.
65 if (resolvedSpecializedList.isEmpty()) {
66 return false;
67 }
68
69 // We found native handlers. Launch the Intent.
70 specializedActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
71 context.startActivity(specializedActivityIntent);
72 return true;
73 }
74
75 public static void launchUri(Context context, Uri uri) {
76 boolean launched = Build.VERSION.SDK_INT >= 30 ?
77 launchNativeApi30(context, uri) :
78 launchNativeBeforeApi30(context, uri);
79
80 if (!launched) {
81 var builder = new CustomTabsIntent.Builder().setShowTitle(true);
82 if (context instanceof XmppActivity) {
83 builder = builder.setColorScheme(((XmppActivity) context).isDark() ? CustomTabsIntent.COLOR_SCHEME_DARK : CustomTabsIntent.COLOR_SCHEME_LIGHT);
84 }
85 builder.build().launchUrl(context, uri);
86 }
87 }
88}