| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861 |
- /**
- * Copyright (c) 2021 Vuplex Inc. All rights reserved.
- *
- * Licensed under the Vuplex Commercial Software Library License, you may
- * not use this file except in compliance with the License. You may obtain
- * a copy of the License at
- *
- * https://vuplex.com/commercial-library-license
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #if UNITY_ANDROID && !UNITY_EDITOR
- #pragma warning disable CS0108
- #pragma warning disable CS0067
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using UnityEngine;
- using UnityEngine.Rendering;
- namespace Vuplex.WebView {
- /// <summary>
- /// The IWebView implementation used by 3D WebView for Android.
- /// This class also includes extra methods for Android-specific functionality.
- /// </summary>
- public class AndroidWebView : BaseWebView,
- IWebView,
- IWithMovablePointer,
- IWithPointerDownAndUp,
- IWithPopups {
- public WebPluginType PluginType {
- get {
- return WebPluginType.Android;
- }
- }
- /// <see cref="IWithPopups"/>
- public event EventHandler<PopupRequestedEventArgs> PopupRequested;
- /// <summary>
- /// Indicates that the browser's render process terminated, either because it
- /// crashed or because the operating system killed it.
- /// </summary>
- /// <remarks>
- /// 3D WebView for Android internally uses the `android.webkit.WebView` system
- /// package as its browser engine. Android's documentation indicates that
- /// the browser's render process can terminate in some rare circumstances.
- /// This RenderProcessGone event indicates when that occurs so that the application
- /// can recover be destroying the existing webviews and creating new webviews.
- ///
- /// Sources:
- /// - [`android.webkit.WebViewClient.onRenderProcessGone()`](https://developer.android.com/reference/android/webkit/WebViewClient#onRenderProcessGone(android.webkit.WebView,%20android.webkit.RenderProcessGoneDetail))
- /// - [Termination Handling API (Android docs)](https://developer.android.com/guide/webapps/managing-webview#termination-handle)
- /// </remarks>
- public event EventHandler RenderProcessGone;
- [Obsolete("The ScriptAlert event has been renamed to ScriptAlerted. Please use ScriptAlerted instead.", true)]
- public event EventHandler<ScriptDialogEventArgs> ScriptAlert;
- /// <summary>
- /// Event raised when a script in the page calls `window.alert()`.
- /// </summary>
- /// <remarks>
- /// If no handler is attached to this event, then `window.alert()` will return
- /// immediately and the script will continue execution. If a handler is attached to
- /// this event, then script execution will be paused until `ScriptDialogEventArgs.Continue()`
- /// is called.
- /// </remarks>
- public event EventHandler<ScriptDialogEventArgs> ScriptAlerted {
- add {
- if (_scriptAlertHandler != null) {
- throw new InvalidOperationException("ScriptAlerted supports only one event handler. Please remove the existing handler before adding a new one.");
- }
- _scriptAlertHandler = value;
- _webView.Call("setScriptAlertHandler", new AndroidStringAndBoolDelegateCallback(_handleScriptAlert));
- }
- remove {
- if (_scriptAlertHandler == value) {
- _scriptAlertHandler = null;
- _webView.Call("setScriptAlertHandler", null);
- }
- }
- }
- /// <summary>
- /// Event raised when a script in the page calls `window.confirm()`.
- /// </summary>
- /// <remarks>
- /// If no handler is attached to this event, then `window.confirm()` will return
- /// `false` immediately and the script will continue execution. If a handler is attached to
- /// this event, then script execution will be paused until `ScriptDialogEventArgs<bool>.Continue()`
- /// is called, and `window.confirm()` will return the value passed to `Continue()`.
- /// </remarks>
- public event EventHandler<ScriptDialogEventArgs<bool>> ScriptConfirmRequested {
- add {
- if (_scriptConfirmHandler != null) {
- throw new InvalidOperationException("ScriptConfirmRequested supports only one event handler. Please remove the existing handler before adding a new one.");
- }
- _scriptConfirmHandler = value;
- _webView.Call("setScriptConfirmHandler", new AndroidStringAndBoolDelegateCallback(_handleScriptConfirm));
- }
- remove {
- if (_scriptConfirmHandler == value) {
- _scriptConfirmHandler = null;
- _webView.Call("setScriptConfirmHandler", null);
- }
- }
- }
- public static AndroidWebView Instantiate() {
- return (AndroidWebView) new GameObject().AddComponent<AndroidWebView>();
- }
- public override void Init(Texture2D viewportTexture, float width, float height, Texture2D videoTexture) {
- AssertWebViewIsAvailable();
- _init(viewportTexture, width, height, videoTexture, null);
- }
- internal static void AssertWebViewIsAvailable() {
- if (!IsWebViewAvailable()) {
- throw new WebViewUnavailableException("The Android WebView package is currently unavailable. This is rare but can occur if it's not installed on the system or is currently being updated.");
- }
- }
- public override void Blur() {
- _assertValidState();
- _webView.Call("blur");
- }
- public override void CanGoBack(Action<bool> callback) {
- _assertValidState();
- _webView.Call("canGoBack", new AndroidBoolCallback(callback));
- }
- public override void CanGoForward(Action<bool> callback) {
- _assertValidState();
- _webView.Call("canGoForward", new AndroidBoolCallback(callback));
- }
- /// <summary>
- /// Overrides `BaseWebView.CaptureScreenshot()` because it doesn't work
- /// with Android OES textures.
- /// </summary>
- public override void CaptureScreenshot(Action<byte[]> callback) {
- _assertValidState();
- _webView.Call("captureScreenshot", new AndroidByteArrayCallback(callback));
- }
- public static void ClearAllData() {
- _class.CallStatic("clearAllData");
- }
- /// <summary>
- /// Clears the webview's back / forward navigation history.
- /// </summary>
- public void ClearHistory() {
- _assertValidState();
- _webView.Call("clearHistory");
- }
- public override void Click(Vector2 point) {
- _assertValidState();
- var nativeX = (int)(point.x * _nativeWidth);
- var nativeY = (int)(point.y * _nativeHeight);
- _webView.Call("click", nativeX, nativeY);
- }
- public override void DisableViewUpdates() {
- _assertValidState();
- _webView.Call("disableViewUpdates");
- _viewUpdatesAreEnabled = false;
- }
- public override void Dispose() {
- _assertValidState();
- // Cancel the render if it has been scheduled via GL.IssuePluginEvent().
- WebView_removePointer(_webView.GetRawObject());
- IsDisposed = true;
- _webView.Call("destroy");
- _webView.Dispose();
- Destroy(gameObject);
- }
- public override void EnableViewUpdates() {
- _assertValidState();
- _webView.Call("enableViewUpdates");
- _viewUpdatesAreEnabled = true;
- }
- public override void ExecuteJavaScript(string javaScript, Action<string> callback) {
- _assertValidState();
- var nativeCallback = callback == null ? null : new AndroidStringCallback(callback);
- _webView.Call("executeJavaScript", javaScript, nativeCallback);
- }
- public override void Focus() {
- _assertValidState();
- _webView.Call("focus");
- }
- public static string GetGraphicsApiErrorMessage(GraphicsDeviceType graphicsDeviceType) {
- var isValid = graphicsDeviceType == GraphicsDeviceType.OpenGLES3 || graphicsDeviceType == GraphicsDeviceType.OpenGLES2;
- if (isValid) {
- return null;
- }
- return String.Format("Unsupported graphics API: 3D WebView for Android requires OpenGLES3 or OpenGLES2, but the graphics API in use is {0}. Please go to Player Settings and set \"Graphics APIs\" to OpenGLES3 or OpenGLES2.", graphicsDeviceType);
- }
- /// <summary>
- /// Overrides `BaseWebView.GetRawTextureData()` because it's slow on Android.
- /// </summary>
- public override void GetRawTextureData(Action<byte[]> callback) {
- _assertValidState();
- _webView.Call("getRawTextureData", new AndroidByteArrayCallback(callback));
- }
- public static void GloballySetUserAgent(bool mobile) {
- _class.CallStatic("globallySetUserAgent", mobile);
- }
- public static void GloballySetUserAgent(string userAgent) {
- _class.CallStatic("globallySetUserAgent", userAgent);
- }
- [Obsolete("AndroidWebView.GloballyUseAlternativeInputEventSystem() has been removed. Please use AndroidWebView.SetAlternativePointerInputSystemEnabled() and/or SetAlternativeKeyboardInputSystemEnabled() instead.", true)]
- public static void GloballyUseAlternativeInputEventSystem(bool useAlternativeInputEventSystem) {}
- public override void GoBack() {
- _assertValidState();
- _webView.Call("goBack");
- }
- public override void GoForward() {
- _assertValidState();
- _webView.Call("goForward");
- }
- public override void HandleKeyboardInput(string input) {
- _assertValidState();
- _webView.Call("handleKeyboardInput", input);
- }
- /// <summary>
- /// Indicates whether native video rendering is available for the current
- /// version of Android and is enabled.
- /// </summary>
- /// <remarks>
- /// Native video rendering is available in Android API level 23 and above.
- /// If native video rendering isn't supported (i.e. the Android version is
- /// lower than 23), then the AndroidWebView plugin will use a fallback video
- /// implementation to support basic video playback.
- /// </remarks>
- public static bool IsUsingNativeVideoRendering() {
- return _class.CallStatic<bool>("isUsingNativeVideoRendering");
- }
- /// <summary>
- /// Indicates whether the Android WebView package is installed on the system and available.
- /// </summary>
- /// <remarks>
- /// 3D WebView internally depends on Android's WebView package, which is normally installed
- /// as part of the operating system. In rare circumstances, the Android WebView package may be unavailable.
- /// For example, this can happen if the user used developer tools to delete the WebView package
- /// or if [updates to the WebView package are currently being installed](https://bugs.chromium.org/p/chromium/issues/detail?id=506369) .
- /// </remarks>
- public static bool IsWebViewAvailable() {
- if (_webViewPackageIsAvailable == null) {
- _webViewPackageIsAvailable = _class.CallStatic<bool>("isWebViewAvailable");
- }
- return (bool)_webViewPackageIsAvailable;
- }
- public override void LoadHtml(string html) {
- _assertValidState();
- _webView.Call("loadHtml", html);
- }
- /// <summary>
- /// Like `LoadHtml(string html)`, but also allows a virtual base URL
- /// to be specified.
- /// </summary>
- public void LoadHtml(string html, string baseUrl) {
- _assertValidState();
- _webView.Call("loadHtml", html, baseUrl);
- }
- public override void LoadUrl(string url) {
- _assertValidState();
- _webView.Call("loadUrl", _transformStreamingAssetsUrlIfNeeded(url));
- }
- public override void LoadUrl(string url, Dictionary<string, string> additionalHttpHeaders) {
- _assertValidState();
- if (additionalHttpHeaders == null) {
- LoadUrl(url);
- } else {
- var map = _convertDictionaryToJavaMap(additionalHttpHeaders);
- _webView.Call("loadUrl", url, map);
- }
- }
- /// <see cref="IWithMovablePointer"/>
- public void MovePointer(Vector2 point) {
- _assertValidState();
- var nativeX = (int)(point.x * _nativeWidth);
- var nativeY = (int)(point.y * _nativeHeight);
- _webView.Call("movePointer", nativeX, nativeY);
- }
- /// <summary>
- /// Pauses processing, media, and rendering for this webview instance
- /// until `Resume()` is called.
- /// </summary>
- public void Pause() {
- _assertValidState();
- _webView.Call("pause");
- }
- /// <summary>
- /// Pauses processing, media, and rendering for all webview instances.
- /// This method is automatically called by the plugin when the application
- /// is paused.
- /// </summary>
- public static void PauseAll() {
- _class.CallStatic("pauseAll");
- }
- /// <see cref="IWithPointerDownAndUp"/>
- public void PointerDown(Vector2 point) {
- _pointerDown(point, MouseButton.Left, 1);
- }
- /// <see cref="IWithPointerDownAndUp"/>
- public void PointerDown(Vector2 point, PointerOptions options) {
- if (options == null) {
- options = new PointerOptions();
- }
- _pointerDown(point, options.Button, options.ClickCount);
- }
- /// <see cref="IWithPointerDownAndUp"/>
- public void PointerUp(Vector2 point) {
- _pointerUp(point, MouseButton.Left, 1);
- }
- /// <see cref="IWithPointerDownAndUp"/>
- public void PointerUp(Vector2 point, PointerOptions options) {
- if (options == null) {
- options = new PointerOptions();
- }
- _pointerUp(point, options.Button, options.ClickCount);
- }
- /// <summary>
- /// Loads the given URL using an HTTP POST request and the given
- /// application/x-www-form-urlencoded data.
- /// </summary>
- /// <example>
- /// webView.PostUrl("https://postman-echo.com/post", Encoding.Unicode.GetBytes("foo=bar"));
- /// </example>
- public void PostUrl(string url, byte[] data) {
- _assertValidState();
- _webView.Call("postUrl", url, data);
- }
- public override void Reload() {
- _assertValidState();
- _webView.Call("reload");
- }
- /// <summary>
- /// Resumes processing and rendering for all webview instances
- /// after a previous call to `Pause().`
- /// </summary>
- public void Resume() {
- _assertValidState();
- _webView.Call("resume");
- }
- /// <summary>
- /// Resumes processing and rendering for all webview instances
- /// after a previous call to `PauseAll().` This method
- /// is automatically called by the plugin when the application resumes after
- /// being paused.
- /// </summary>
- public static void ResumeAll() {
- _class.CallStatic("resumeAll");
- }
- public override void Scroll(Vector2 scrollDelta) {
- _assertValidState();
- var deltaX = (int)(scrollDelta.x * _numberOfPixelsPerUnityUnit);
- var deltaY = (int)(scrollDelta.y * _numberOfPixelsPerUnityUnit);
- _webView.Call("scroll", deltaX, deltaY);
- }
- public override void Scroll(Vector2 scrollDelta, Vector2 point) {
- _assertValidState();
- var deltaX = (int)(scrollDelta.x * _numberOfPixelsPerUnityUnit);
- var deltaY = (int)(scrollDelta.y * _numberOfPixelsPerUnityUnit);
- var pointerX = (int)(point.x * _nativeWidth);
- var pointerY = (int)(point.y * _nativeHeight);
- _webView.Call("scroll", deltaX, deltaY, pointerX, pointerY);
- }
- public static void SetAlternativeKeyboardInputSystemEnabled(bool enabled) {
- _class.CallStatic("setAlternativeKeyboardInputSystemEnabled", enabled);
- }
- /// <summary>
- /// By default, 3D WebView dispatches pointer (a.k.a mouse) events to the
- /// browser engine in a way that accurately mimics the functionality of
- /// a desktop browser. This works great in most cases, but on some systems
- /// (i.e. Oculus Quest 2), the system version of Chromium is buggy and out-of-date,
- /// which can lead to issues where pointer events aren't dispatched accurately.
- /// In those cases, this method can be used to enable an alternative pointer
- /// input system that is less flexible but doesn't suffer from the Chromium
- /// bugs. This method is called automatically by AndroidWebPlugin.cs when
- /// running on Oculus Quest 2. Note that calling this method effectively disables
- /// the ability to trigger hover or drag events with `MovePointer()`.
- /// </summary>
- public static void SetAlternativePointerInputSystemEnabled(bool enabled) {
- _class.CallStatic("setAlternativePointerInputSystemEnabled", enabled);
- }
- /// <summary>
- /// By default, web pages cannot access the device's
- /// camera or microphone via JavaScript, even if the user has granted
- /// the app permission to use them. Invoking `SetAudioAndVideoCaptureEnabled(true)` allows
- /// **all web pages** to access the camera and microphone if the user has
- /// granted the app permission to use them via the standard Android permission dialogs.
- /// </summary>
- /// <remarks>
- /// This is useful, for example, to enable WebRTC support.
- /// In addition to calling this method, the application must include the following Android
- /// permissions in its AndroidManifest.xml and also request the permissions at runtime.
- /// - android.permission.RECORD_AUDIO
- /// - android.permission.MODIFY_AUDIO_SETTINGS
- /// - android.permission.CAMERA
- /// </remarks>
- public static void SetAudioAndVideoCaptureEnabled(bool enabled) {
- _class.CallStatic("setAudioAndVideoCaptureEnabled", enabled);
- }
- public static void SetClickCorrectionEnabled(bool enabled) {
- _class.CallStatic("setClickCorrectionEnabled", enabled);
- }
- [Obsolete("AndroidWebView.SetCustomUriSchemesEnabled() has been removed. Now when a page redirects to a URI with a custom scheme, 3D WebView will automatically emit the UrlChanged and LoadProgressChanged events for the navigation, but a deep link (i.e. to an external application) won't occur.", true)]
- public static void SetCustomUriSchemesEnabled(bool enabled) {}
- [Obsolete("AndroidWebView.SetForceDrawEnabled() has been removed because it is no longer needed.", true)]
- public static void SetForceDrawEnabled(bool enabled) {}
- /// <summary>
- /// By default, web pages cannot access the device's
- /// geolocation via JavaScript, even if the user has granted
- /// the app permission to access location. Invoking `SetGeolocationPermissionEnabled(true)` allows
- /// **all web pages** to access the geolocation if the user has
- /// granted the app location permissions via the standard Android permission dialogs.
- /// </summary>
- /// <remarks>
- /// The following Android permissions must be included in the app's AndroidManifest.xml
- /// and also requested by the application at runtime:
- /// - android.permission.ACCESS_COARSE_LOCATION
- /// - android.permission.ACCESS_FINE_LOCATION
- /// </remarks>
- public static void SetGeolocationPermissionEnabled(bool enabled) {
- _class.CallStatic("setGeolocationPermissionEnabled", enabled);
- }
- public static void SetIgnoreCertificateErrors(bool ignore) {
- _class.CallStatic("setIgnoreCertificateErrors", ignore);
- }
- [Obsolete("AndroidWebView.SetIgnoreSslErrors() is now deprecated. Please use Web.SetIgnoreCertificateErrors() instead.")]
- public static void SetIgnoreSslErrors(bool ignore) {
- SetIgnoreCertificateErrors(ignore);
- }
- /// <summary>
- /// Sets the initial scale for web content, where 1.0 is the default scale.
- /// </summary>
- public void SetInitialScale(float scale) {
- _assertValidState();
- _webView.Call("setInitialScale", scale);
- }
- /// <summary>
- /// By default, AndroidWebView prevents JavaScript from auto-playing sound
- /// from most sites unless the user has first interacted with the page.
- /// You can call this method to disable or re-enable enforcement of this auto-play policy.
- /// </summary>
- public void SetMediaPlaybackRequiresUserGesture(bool mediaPlaybackRequiresUserGesture) {
- _assertValidState();
- _webView.Call("setMediaPlaybackRequiresUserGesture", mediaPlaybackRequiresUserGesture);
- }
- [Obsolete("AndroidWebView.SetNativeKeyboardEnabled() is now deprecated. Please use Web.SetTouchScreenKeyboardEnabled() instead.")]
- public static void SetNativeKeyboardEnabled(bool enabled) {
- SetTouchScreenKeyboardEnabled(enabled);
- }
- /// <summary>
- /// Enables or disables native video rendering on versions of Android
- /// that support native video rendering.
- /// </summary>
- /// <remarks>
- /// The default is enabled. If disabled, then the `AndroidWebView`
- /// plugin will use a fallback video implementation to support basic
- /// video playback. This method is automatically called when the
- /// Oculus VR SDK is enabled, because the Oculus Go and Quest
- /// headsets don't support native video rendering.
- /// </remarks>
- public static void SetNativeVideoRenderingEnabled(bool enabled) {
- _class.CallStatic("setNativeVideoRenderingEnabled", enabled);
- }
- /// <see cref="IWithPopups"/>
- public void SetPopupMode(PopupMode popupMode) {
- _assertValidState();
- _webView.Call("setPopupMode", (int)popupMode);
- }
- public static void SetStorageEnabled(bool enabled) {
- _class.CallStatic("setStorageEnabled", enabled);
- }
- /// <summary>
- /// Sets the `android.view.Surface` to which the webview renders.
- /// This can be used, for example, to render to an Oculus
- /// [OVROverlay](https://developer.oculus.com/reference/unity/1.30/class_o_v_r_overlay).
- /// After this method is called, the webview no longer renders
- /// to its original texture and instead renders to the given surface.
- /// </summary>
- /// <example>
- /// var surface = ovrOverlay.externalSurfaceObject();
- /// // Set the resolution to 1 px / Unity unit
- /// // to make it easy to specify the size in pixels.
- /// webView.SetResolution(1);
- /// // Or if the webview is attached to a prefab, call WebViewPrefab.Resize()
- /// webView.WebView.Resize(surface.externalSurfaceWidth(), surface.externalSurfaceHeight());
- /// #if UNITY_ANDROID && !UNITY_EDITOR
- /// (webView as AndroidWebView).SetSurface(surface);
- /// #endif
- /// </example>
- public void SetSurface(IntPtr surface) {
- _assertValidState();
- var surfaceObject = _convertIntPtrToAndroidJavaObject(surface);
- _webView.Call("setSurface", surfaceObject);
- }
- public static void SetTouchScreenKeyboardEnabled(bool enabled) {
- _class.CallStatic("setTouchScreenKeyboardEnabled", enabled);
- }
- /// <summary>
- /// Like `Web.SetUserAgent(bool mobile)`, except it sets the user-agent
- /// for a single webview instance instead of setting it globally.
- /// </summary>
- /// <remarks>
- /// If you globally set a default user-agent using `Web.SetUserAgent()`,
- /// you can still use this method to override the user-agent for a
- /// single webview instance.
- /// </remarks>
- public void SetUserAgent(bool mobile) {
- _assertValidState();
- _webView.Call("setUserAgent", mobile);
- }
- /// <summary>
- /// Like `Web.SetUserAgent(string userAgent)`, except it sets the user-agent
- /// for a single webview instance instead of setting it globally.
- /// </summary>
- /// <remarks>
- /// If you globally set a default user-agent using `Web.SetUserAgent()`,
- /// you can still use this method to override the user-agent for a
- /// single webview instance.
- /// </remarks>
- public void SetUserAgent(string userAgent) {
- _assertValidState();
- _webView.Call("setUserAgent", userAgent);
- }
- [Obsolete("AndroidWebView.UseAlternativeInputEventSystem() has been removed. Please use AndroidWebView.SetAlternativePointerInputSystemEnabled() and/or SetAlternativeKeyboardInputSystemEnabled() instead.", true)]
- public void UseAlternativeInputEventSystem(bool useAlternativeInputEventSystem) {}
- /// <summary>
- /// Zooms in or out by the given factor, which is multiplied by the current zoom level
- /// to reach the new zoom level.
- /// </summary>
- /// <remarks>
- /// Note that the zoom level gets reset when a new page is loaded.
- /// </remarks>
- /// <param name="zoomFactor">
- /// The zoom factor to apply in the range from 0.01 to 100.0.
- /// </param>
- public void ZoomBy(float zoomFactor) {
- _assertValidState();
- _webView.Call("zoomBy", zoomFactor);
- }
- public override void ZoomIn() {
- _assertValidState();
- _webView.Call("zoomIn");
- }
- public override void ZoomOut() {
- _assertValidState();
- _webView.Call("zoomOut");
- }
- // Get a reference to AndroidJavaObject's hidden constructor that takes
- // the IntPtr for a jobject as a parameter.
- readonly static ConstructorInfo _androidJavaObjectIntPtrConstructor = typeof(AndroidJavaObject).GetConstructor(
- BindingFlags.Instance | BindingFlags.NonPublic,
- null,
- new []{ typeof(IntPtr) },
- null
- );
- internal static AndroidJavaClass _class = new AndroidJavaClass(FULL_CLASS_NAME);
- const string FULL_CLASS_NAME = "com.vuplex.webview.WebView";
- EventHandler<ScriptDialogEventArgs> _scriptAlertHandler;
- EventHandler<ScriptDialogEventArgs<bool>> _scriptConfirmHandler;
- readonly WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame();
- internal AndroidJavaObject _webView;
- static bool? _webViewPackageIsAvailable = null;
- AndroidJavaObject _convertDictionaryToJavaMap(Dictionary<string, string> dictionary) {
- AndroidJavaObject map = new AndroidJavaObject("java.util.HashMap");
- IntPtr putMethod = AndroidJNIHelper.GetMethodID(map.GetRawClass(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
- foreach (var entry in dictionary) {
- AndroidJNI.CallObjectMethod(
- map.GetRawObject(),
- putMethod,
- AndroidJNIHelper.CreateJNIArgArray(new object[] { entry.Key, entry.Value })
- );
- }
- return map;
- }
- static AndroidJavaObject _convertIntPtrToAndroidJavaObject(IntPtr jobject) {
- if (jobject == IntPtr.Zero) {
- return null;
- }
- return (AndroidJavaObject) _androidJavaObjectIntPtrConstructor.Invoke(new object[] { jobject });
- }
- /// <summary>
- /// The native plugin invokes this method.
- /// </summary>
- protected virtual void HandleInitialVideoPlayRequest(string serializedVideo) {
- _assertValidState();
- var video = JsonUtility.FromJson<Video>(serializedVideo);
- var nativeVideoPlayer = _webView.Call<AndroidJavaObject>("getOrCreateVideoPlayer", serializedVideo, _videoTexture.GetNativeTexturePtr().ToInt32());
- nativeVideoPlayer.Call("play", video.videoUrl);
- }
- void _handlePopup(string url, AndroidJavaObject popupResultMessage) {
- var handler = PopupRequested;
- if (handler == null) {
- return;
- }
- if (popupResultMessage == null) {
- handler(this, new PopupRequestedEventArgs(url, null));
- return;
- }
- var popupWebView = Instantiate();
- Dispatcher.RunOnMainThread(() => {
- AndroidWebPlugin.Instance.CreateTexture(1, 1, texture => {
- // Use the same resolution and dimensions as the current webview.
- popupWebView.SetResolution(_numberOfPixelsPerUnityUnit);
- popupWebView._init(texture, _width, _height, null, popupResultMessage);
- handler(this, new PopupRequestedEventArgs(url, popupWebView));
- });
- });
- }
- /// <summary>
- /// The native plugin invokes this method.
- /// </summary>
- void HandleRenderProcessGone() {
- var handler = RenderProcessGone;
- if (handler != null) {
- handler(this, EventArgs.Empty);
- }
- }
- void _handleScriptAlert(string message, Action<bool> continueCallback) {
- _scriptAlertHandler(this, new ScriptDialogEventArgs(message, () => continueCallback(true)));
- }
- void _handleScriptConfirm(string message, Action<bool> continueCallback) {
- _scriptConfirmHandler(this, new ScriptDialogEventArgs<bool>(message, continueCallback));
- }
- void _init(Texture2D viewportTexture, float width, float height, Texture2D videoTexture, AndroidJavaObject popupResultMessage) {
- base.Init(viewportTexture, width, height, videoTexture);
- _webView = new AndroidJavaObject(
- FULL_CLASS_NAME,
- gameObject.name,
- viewportTexture.GetNativeTexturePtr().ToInt32(),
- _nativeWidth,
- _nativeHeight,
- SystemInfo.graphicsMultiThreaded,
- videoTexture != null,
- new AndroidStringAndObjectCallback(_handlePopup),
- popupResultMessage
- );
- }
- void OnEnable() {
- // Start the coroutine from OnEnable so that the coroutine
- // is restarted if the object is deactivated and then reactivated.
- StartCoroutine(_renderPluginOncePerFrame());
- }
- void _pointerDown(Vector2 point, MouseButton mouseButton, int clickCount) {
- _assertValidState();
- var nativeX = (int)(point.x * _nativeWidth);
- var nativeY = (int)(point.y * _nativeHeight);
- _webView.Call("pointerDown", nativeX, nativeY, (int)mouseButton, clickCount);
- }
- void _pointerUp(Vector2 point, MouseButton mouseButton, int clickCount) {
- _assertValidState();
- var nativeX = (int)(point.x * _nativeWidth);
- var nativeY = (int)(point.y * _nativeHeight);
- _webView.Call("pointerUp", nativeX, nativeY, (int)mouseButton, clickCount);
- }
- IEnumerator _renderPluginOncePerFrame() {
- while (true) {
- yield return _waitForEndOfFrame;
- if (!_viewUpdatesAreEnabled || IsDisposed || _webView == null) {
- continue;
- }
- var nativeWebViewPtr = _webView.GetRawObject();
- if (nativeWebViewPtr != IntPtr.Zero) {
- int pointerId = WebView_depositPointer(nativeWebViewPtr);
- GL.IssuePluginEvent(WebView_getRenderFunction(), pointerId);
- }
- }
- }
- protected override void _resize() {
- // Only trigger a resize if the webview has been initialized
- if (_viewportTexture) {
- _assertValidState();
- Utils.ThrowExceptionIfAbnormallyLarge(_nativeWidth, _nativeHeight);
- _webView.Call("resize", _nativeWidth, _nativeHeight);
- }
- }
- protected override void _setConsoleMessageEventsEnabled(bool enabled) {
- _assertValidState();
- _webView.Call("setConsoleMessageEventsEnabled", enabled);
- }
- protected override void _setFocusedInputFieldEventsEnabled(bool enabled) {
- _assertValidState();
- _webView.Call("setFocusedInputFieldEventsEnabled", enabled);
- }
- [DllImport(_dllName)]
- static extern IntPtr WebView_getRenderFunction();
- [DllImport(_dllName)]
- static extern int WebView_depositPointer(IntPtr pointer);
- [DllImport(_dllName)]
- static extern void WebView_removePointer(IntPtr pointer);
- }
- }
- #endif
|