diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml
index 18457ab3..dcba90b3 100644
--- a/.github/workflows/linter.yml
+++ b/.github/workflows/linter.yml
@@ -57,6 +57,6 @@ jobs:
VALIDATE_ALL_CODEBASE: true
DEFAULT_BRANCH: main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- FILTER_REGEX_EXCLUDE: (.*src/Packages/Passport/Runtime/ThirdParty/.*|.*src/Packages/Passport/Runtime/Resources/.*|.*Plugins/.*)
+ FILTER_REGEX_EXCLUDE: (.*src/Packages/Passport/Runtime/ThirdParty/.*|.*src/Packages/Passport/Runtime/Resources/.*|.*Plugins/.*|.*src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/.*)
VALIDATE_MARKDOWN: false
VALIDATE_GITLEAKS: false
diff --git a/src/Packages/Passport/Editor/PassportAndroidProcessor.cs b/src/Packages/Passport/Editor/PassportAndroidProcessor.cs
index a4e77dec..b656e359 100644
--- a/src/Packages/Passport/Editor/PassportAndroidProcessor.cs
+++ b/src/Packages/Passport/Editor/PassportAndroidProcessor.cs
@@ -1,5 +1,6 @@
#if UNITY_EDITOR
+using System;
using System.IO;
using UnityEditor;
using UnityEditor.Android;
@@ -24,6 +25,23 @@ public void OnPostGenerateGradleAndroidProject(string path)
FileHelpers.CopyDirectory(passportWebFilesDir, $"{path}/src/main/assets/ImmutableSDK/Runtime/Passport");
Debug.Log($"Sucessfully copied Passport files");
+
+ AddUseAndroidX(path);
+ }
+
+ private void AddUseAndroidX(string path)
+ {
+ var parentDir = Directory.GetParent(path).FullName;
+ var gradlePath = parentDir + "/gradle.properties";
+
+ if(!File.Exists(gradlePath))
+ throw new Exception("gradle.properties does not exist");
+
+ var text = File.ReadAllText(gradlePath);
+
+ text += "\nandroid.useAndroidX=true\nandroid.enableJetifier=true";
+
+ File.WriteAllText(gradlePath, text);
}
}
}
diff --git a/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib.meta b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib.meta
new file mode 100644
index 00000000..5ed1faff
--- /dev/null
+++ b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib.meta
@@ -0,0 +1,27 @@
+fileFormatVersion: 2
+guid: fdcd7aa1984da404d890f63f81d0a65b
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 1
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/build.gradle b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/build.gradle
new file mode 100644
index 00000000..5a0d5996
--- /dev/null
+++ b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/build.gradle
@@ -0,0 +1,22 @@
+apply plugin: 'com.android.library'
+
+dependencies {
+ implementation('androidx.browser:browser:1.6.0')
+}
+
+android {
+ compileSdkVersion 33
+ buildToolsVersion '30.0.3'
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ minSdkVersion 22
+ targetSdkVersion 33
+ versionCode 1
+ versionName '1.0'
+ }
+}
diff --git a/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/AndroidManifest.xml b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..10b14f46
--- /dev/null
+++ b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/java/com/immutable/unity/ImmutableAndroid.java b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/java/com/immutable/unity/ImmutableAndroid.java
new file mode 100644
index 00000000..3e5b6616
--- /dev/null
+++ b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/java/com/immutable/unity/ImmutableAndroid.java
@@ -0,0 +1,87 @@
+package com.immutable.unity;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.Insets;
+import android.net.Uri;
+import android.os.Build;
+import android.util.DisplayMetrics;
+import android.view.WindowInsets;
+import android.view.WindowMetrics;
+
+import androidx.annotation.NonNull;
+import androidx.browser.customtabs.CustomTabsCallback;
+import androidx.browser.customtabs.CustomTabsClient;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsServiceConnection;
+import androidx.browser.customtabs.CustomTabsSession;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ImmutableAndroid {
+ private static CustomTabsServiceConnection customTabsServiceConnection;
+
+ private static int getCustomTabsHeight(Activity context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ WindowMetrics windowMetrics = context.getWindowManager().getCurrentWindowMetrics();
+ Insets insets = windowMetrics.getWindowInsets()
+ .getInsetsIgnoringVisibility(WindowInsets.Type.systemBars());
+ return windowMetrics.getBounds().height() - insets.top - insets.bottom;
+ } else {
+ DisplayMetrics displayMetrics = new DisplayMetrics();
+ context.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
+ return displayMetrics.heightPixels;
+ }
+ }
+
+ public static void launchUrl(Activity context, String url) {
+ // Get all apps that can support Custom Tabs Service
+ // i.e. services that can handle ACTION_CUSTOM_TABS_CONNECTION intents
+ PackageManager packageManager = context.getPackageManager();
+ Intent serviceIntent = new Intent();
+ serviceIntent.setAction(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION);
+ List resolvedList = packageManager.queryIntentServices(serviceIntent, 0);
+ List packageNames = new ArrayList<>();
+ for (ResolveInfo info : resolvedList) {
+ if (info.serviceInfo != null) {
+ packageNames.add(info.serviceInfo.packageName);
+ }
+ }
+
+ if (packageNames.size() > 0) {
+ // Get the preferred Custom Tabs package
+ String customTabsPackageName = CustomTabsClient.getPackageName(context, packageNames);
+ if (customTabsPackageName == null) {
+ // Could not get the preferred Custom Tab browser, so launch URL in any browser
+ context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
+ } else {
+ customTabsServiceConnection = new CustomTabsServiceConnection() {
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ customTabsServiceConnection = null;
+ }
+
+ @Override
+ public void onCustomTabsServiceConnected(@NonNull ComponentName name, @NonNull CustomTabsClient client) {
+ CustomTabsSession session = client.newSession(new CustomTabsCallback());
+ // Need to set the session to get custom tabs to show as a bottom sheet
+ CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder(session)
+ .setInitialActivityHeightPx(getCustomTabsHeight(context))
+ .setUrlBarHidingEnabled(true)
+ .build();
+ customTabsIntent.launchUrl(context, Uri.parse(url));
+ }
+ };
+ CustomTabsClient.bindCustomTabsService(context, customTabsPackageName, customTabsServiceConnection);
+ }
+ } else {
+ // Custom Tabs not supported by any browser on the device so launch URL in any browser
+ context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
+ }
+ }
+}
diff --git a/src/Packages/Passport/Runtime/Scripts/Private/PassportImpl.cs b/src/Packages/Passport/Runtime/Scripts/Private/PassportImpl.cs
index 2dae7707..c21a60f5 100644
--- a/src/Packages/Passport/Runtime/Scripts/Private/PassportImpl.cs
+++ b/src/Packages/Passport/Runtime/Scripts/Private/PassportImpl.cs
@@ -11,6 +11,9 @@
using Cysharp.Threading.Tasks;
using System.Web;
using System.Threading;
+#if UNITY_ANDROID
+using UnityEngine.Android;
+#endif
namespace Immutable.Passport
{
@@ -107,7 +110,15 @@ private async UniTask LaunchAuthUrl()
if (response?.Success == true && response?.Result != null)
{
- Application.OpenURL(response.Result.Replace(" ", "+"));
+ string url = response.Result.Replace(" ", "+");
+#if UNITY_ANDROID
+ AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
+ AndroidJavaObject activity = unityPlayer.GetStatic("currentActivity");
+ AndroidJavaClass customTabLauncher = new AndroidJavaClass("com.immutable.unity.ImmutableAndroid");
+ customTabLauncher.CallStatic("launchUrl", activity, url);
+#else
+ Application.OpenURL(url);
+#endif
return;
}
else
diff --git a/src/Packages/Passport/Runtime/ThirdParty/Gree/Assets/Plugins/WebViewObject.cs b/src/Packages/Passport/Runtime/ThirdParty/Gree/Assets/Plugins/WebViewObject.cs
index 10d3abc3..0f0b8e01 100644
--- a/src/Packages/Passport/Runtime/ThirdParty/Gree/Assets/Plugins/WebViewObject.cs
+++ b/src/Packages/Passport/Runtime/ThirdParty/Gree/Assets/Plugins/WebViewObject.cs
@@ -191,15 +191,15 @@ public void Init(
onError = err;
onHttpError = httpErr;
#if UNITY_WEBGL
- #if !UNITY_EDITOR
+#if !UNITY_EDITOR
_gree_unity_webview_init();
- #endif
+#endif
#elif UNITY_WEBPLAYER
Application.ExternalCall("unityWebView.init");
#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_LINUX
//TODO: UNSUPPORTED
Debug.LogError("Webview is not supported on this platform.");
-#elif UNITY_IPHONE || UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
+#elif UNITY_IPHONE || UNITY_STANDALONE_OSX
webView = _CWebViewPlugin_Init(ua);
Singleton.Instance.onJS = ((message) => CallFromJS(message));
Singleton.Instance.onError = ((message) => CallOnError(message));
@@ -226,7 +226,7 @@ public void LoadURL(string url)
Application.ExternalCall("unityWebView.loadURL", url);
#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_LINUX
//TODO: UNSUPPORTED
-#elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX || UNITY_IPHONE
+#elif UNITY_STANDALONE_OSX || UNITY_IPHONE
if (webView == IntPtr.Zero)
return;
_CWebViewPlugin_LoadURL(webView, url);
@@ -247,7 +247,7 @@ public void EvaluateJS(string js)
Application.ExternalCall("unityWebView.evaluateJS", js);
#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_LINUX
//TODO: UNSUPPORTED
-#elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX || UNITY_IPHONE
+#elif UNITY_STANDALONE_OSX || UNITY_IPHONE
if (webView == IntPtr.Zero)
return;
_CWebViewPlugin_EvaluateJS(webView, js);