From ca254536c084441f16c4597d1c3038a4df2fed97 Mon Sep 17 00:00:00 2001 From: Dom Murray Date: Wed, 27 Sep 2023 16:05:26 +1000 Subject: [PATCH 1/3] feat: use chrome custom tabs for auth --- .../Editor/PassportAndroidProcessor.cs | 18 +++++++++++++ .../Assets/ImmutableAndroid.androidlib.meta | 27 +++++++++++++++++++ .../ImmutableAndroid.androidlib/build.gradle | 22 +++++++++++++++ .../src/main/AndroidManifest.xml | 4 +++ .../com/immutable/unity/ImmutableAndroid.java | 26 ++++++++++++++++++ .../Runtime/Scripts/Private/PassportImpl.cs | 13 ++++++++- .../Gree/Assets/Plugins/WebViewObject.cs | 10 +++---- 7 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib.meta create mode 100644 src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/build.gradle create mode 100644 src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/AndroidManifest.xml create mode 100644 src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/java/com/immutable/unity/ImmutableAndroid.java 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..b40a6728 --- /dev/null +++ b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ 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..9a825dff --- /dev/null +++ b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/java/com/immutable/unity/ImmutableAndroid.java @@ -0,0 +1,26 @@ +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.CustomTabsIntent; + +import java.util.ArrayList; +import java.util.List; + +public class ImmutableAndroid { + public static void launchUrl(Activity context, String url) { + CustomTabsIntent intent = new CustomTabsIntent.Builder().build(); + intent.launchUrl(context, Uri.parse(url)); + } +} \ No newline at end of file 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); From a2b471ec242fd6d4922b606667d7c75747251582 Mon Sep 17 00:00:00 2001 From: Dom Murray Date: Thu, 28 Sep 2023 11:37:04 +1000 Subject: [PATCH 2/3] feat: use same logic as unreal --- .../src/main/AndroidManifest.xml | 6 +- .../com/immutable/unity/ImmutableAndroid.java | 65 ++++++++++++++++++- 2 files changed, 68 insertions(+), 3 deletions(-) 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 index b40a6728..10b14f46 100644 --- a/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/AndroidManifest.xml +++ b/src/Packages/Passport/Runtime/Assets/ImmutableAndroid.androidlib/src/main/AndroidManifest.xml @@ -1,4 +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 index 9a825dff..a35dbb95 100644 --- 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 @@ -13,14 +13,75 @@ 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) { - CustomTabsIntent intent = new CustomTabsIntent.Builder().build(); - intent.launchUrl(context, Uri.parse(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))); + } } } \ No newline at end of file From 876dd389b38d3ae6b498d5975e06e541996410eb Mon Sep 17 00:00:00 2001 From: Dom Murray Date: Thu, 28 Sep 2023 11:58:23 +1000 Subject: [PATCH 3/3] fix: android lint --- .github/workflows/linter.yml | 2 +- .../src/main/java/com/immutable/unity/ImmutableAndroid.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/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 index a35dbb95..3e5b6616 100644 --- 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 @@ -84,4 +84,4 @@ public void onCustomTabsServiceConnected(@NonNull ComponentName name, @NonNull C context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); } } -} \ No newline at end of file +}