Skip to content

Commit 04a8e8f

Browse files
feat: add vuplex webview for android (#3956)
1 parent fc2dcd4 commit 04a8e8f

5 files changed

Lines changed: 177 additions & 3 deletions

File tree

src/Packages/Passport/Runtime/Scripts/Private/Immutable.Passport.Runtime.Private.asmdef

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"UniTask",
77
"Immutable.Browser.Core",
88
"Immutable.Browser.Gree",
9-
"Immutable.Passport.Core.Logging"
9+
"Immutable.Passport.Core.Logging",
10+
"Vuplex.WebView"
1011
],
1112
"includePlatforms": [
1213
"Android",

src/Packages/Passport/Runtime/Scripts/Private/UI/AndroidPassportWebView.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ private void CreateWebViewObject()
248248
UnityEngine.Object.DontDestroyOnLoad(webViewGameObject);
249249

250250
// Add WebViewObject component
251-
webViewObject = webViewGameObject.AddComponent<WebViewObject>();
251+
webViewObject = new WebViewObject();
252252

253253
PassportLogger.Info($"{TAG} Gree WebViewObject created successfully");
254254
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Cysharp.Threading.Tasks;
4+
using UnityEngine;
5+
using UnityEngine.UI;
6+
using Immutable.Passport.Core.Logging;
7+
using Vuplex.WebView;
8+
9+
namespace Immutable.Passport
10+
{
11+
public class AndroidVuplexWebView : IPassportWebView
12+
{
13+
private const string TAG = "[AndroidWebView]";
14+
private CanvasWebViewPrefab _webViewPrefab;
15+
private readonly Dictionary<string, Action<string>> _jsHandlers = new Dictionary<string, Action<string>>();
16+
private readonly RawImage _canvasReference;
17+
private bool _isInitialized = false;
18+
19+
public event Action<string> OnJavaScriptMessage;
20+
public event Action OnLoadFinished;
21+
public event Action OnLoadStarted;
22+
23+
// Safe access - check initialization
24+
public bool IsVisible => _webViewPrefab?.Visible ?? false;
25+
public string CurrentUrl => _webViewPrefab?.WebView?.Url ?? "";
26+
27+
public AndroidVuplexWebView(RawImage canvasReference)
28+
{
29+
_canvasReference = canvasReference ?? throw new ArgumentNullException(nameof(canvasReference));
30+
}
31+
32+
public void Initialize(PassportWebViewConfig config)
33+
{
34+
if (_isInitialized)
35+
{
36+
PassportLogger.Warn($"{TAG} Already initialized, skipping");
37+
return;
38+
}
39+
40+
try
41+
{
42+
PassportLogger.Info($"{TAG} Initializing Vuplex WebView...");
43+
44+
// Start async initialization but don't wait
45+
InitializeAsync(config).Forget();
46+
}
47+
catch (Exception ex)
48+
{
49+
PassportLogger.Error($"{TAG} Failed to initialize: {ex.Message}");
50+
throw;
51+
}
52+
}
53+
54+
private async UniTaskVoid InitializeAsync(PassportWebViewConfig config)
55+
{
56+
try
57+
{
58+
// Create WebView prefab and parent to Canvas
59+
_webViewPrefab = CanvasWebViewPrefab.Instantiate();
60+
_webViewPrefab.Native2DModeEnabled = true;
61+
62+
// Must be child of Canvas for Vuplex to work
63+
_webViewPrefab.transform.SetParent(_canvasReference.canvas.transform, false);
64+
65+
// Set up full-screen layout for Native 2D Mode
66+
var rect = _webViewPrefab.GetComponent<RectTransform>();
67+
rect.anchorMin = Vector2.zero;
68+
rect.anchorMax = Vector2.one;
69+
rect.offsetMin = rect.offsetMax = Vector2.zero;
70+
71+
// Wait for WebView initialization
72+
await _webViewPrefab.WaitUntilInitialized();
73+
74+
// Setup event handlers
75+
_webViewPrefab.WebView.LoadProgressChanged += (s, e) =>
76+
{
77+
if (e.Type == ProgressChangeType.Started)
78+
{
79+
OnLoadStarted?.Invoke();
80+
}
81+
else if (e.Type == ProgressChangeType.Finished)
82+
{
83+
OnLoadFinished?.Invoke();
84+
}
85+
};
86+
_webViewPrefab.WebView.MessageEmitted += (s, e) =>
87+
{
88+
foreach (var h in _jsHandlers)
89+
{
90+
if (e.Value.StartsWith($"{h.Key}:"))
91+
{
92+
h.Value?.Invoke(e.Value.Substring(h.Key.Length + 1));
93+
return;
94+
}
95+
}
96+
97+
OnJavaScriptMessage?.Invoke(e.Value);
98+
};
99+
_webViewPrefab.WebView.LoadFailed += (s, e) => PassportLogger.Warn($"{TAG} Load failed: {e.NativeErrorCode} for {e.Url}");
100+
101+
_isInitialized = true;
102+
PassportLogger.Info($"{TAG} Vuplex WebView initialized successfully");
103+
}
104+
catch (Exception ex)
105+
{
106+
PassportLogger.Error($"{TAG} Failed to initialize async: {ex.Message}");
107+
throw;
108+
}
109+
}
110+
111+
public void LoadUrl(string url)
112+
{
113+
if (!_isInitialized || _webViewPrefab?.WebView == null)
114+
{
115+
PassportLogger.Error($"{TAG} Cannot load URL - WebView not initialized");
116+
return;
117+
}
118+
119+
_webViewPrefab.WebView.LoadUrl(url);
120+
}
121+
122+
public void Show()
123+
{
124+
if (_webViewPrefab != null)
125+
{
126+
_webViewPrefab.Visible = true;
127+
}
128+
}
129+
130+
public void Hide()
131+
{
132+
if (_webViewPrefab != null)
133+
{
134+
_webViewPrefab.Visible = false;
135+
}
136+
}
137+
138+
public void ExecuteJavaScript(string js)
139+
{
140+
if (!_isInitialized || _webViewPrefab?.WebView == null)
141+
{
142+
PassportLogger.Error($"{TAG} Cannot execute JavaScript - WebView not initialized");
143+
return;
144+
}
145+
146+
_webViewPrefab.WebView.ExecuteJavaScript(js);
147+
}
148+
149+
public void RegisterJavaScriptMethod(string methodName, Action<string> handler)
150+
{
151+
_jsHandlers[methodName] = handler;
152+
153+
if (_isInitialized && _webViewPrefab?.WebView != null)
154+
{
155+
ExecuteJavaScript($"window.{methodName}=d=>window.vuplex?.postMessage('{methodName}:'+(typeof d==='object'?JSON.stringify(d):d))");
156+
}
157+
}
158+
159+
public void Dispose()
160+
{
161+
if (_webViewPrefab != null)
162+
{
163+
_webViewPrefab.Destroy();
164+
_webViewPrefab = null;
165+
}
166+
167+
_jsHandlers.Clear();
168+
_isInitialized = false;
169+
}
170+
}
171+
}

src/Packages/Passport/Runtime/Scripts/Private/UI/AndroidVuplexWebView.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Packages/Passport/Runtime/Scripts/Public/PassportUI.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ private IPassportWebView CreatePlatformWebView()
202202
return new iOSPassportWebView(rawImage, this);
203203
#elif UNITY_ANDROID
204204
PassportLogger.Info($"{TAG} Creating Android WebView");
205-
return new AndroidPassportWebView(rawImage, this);
205+
return new AndroidVuplexWebView(rawImage);
206206
#elif UNITY_STANDALONE_OSX
207207
PassportLogger.Info($"{TAG} Creating macOS WebView (WKWebView)");
208208
// TODO: Implement macOS WebView

0 commit comments

Comments
 (0)