From 9778f9857ff68e3c609c1323ff1a61ba4cb1121f Mon Sep 17 00:00:00 2001 From: Sebastian Knapp Date: Mon, 8 Feb 2016 10:27:08 +0100 Subject: [PATCH 1/6] Added workaround for missing communication between CoherentUI and Unity using WebView 47 on Android --- .../com/coherentlabs/ui/CoherentWebViewClient.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java b/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java index 7d5721f..22cf900 100644 --- a/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java +++ b/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java @@ -30,12 +30,25 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) { Log.v(LOG_TAG, "Overriding URL loading of \"" + url + "\" for view " + view.getId()); return true; } else { + // Workaround for Android 5+, because WebView 47+ does not call onLoadResource like the previous versions did. + // We could (or even should) be checking the WebView-Version here, but I didn't find a nice way to do that. + if (android.os.Build.VERSION.SDK_INT >= 21){ + loadResourceDirect(view, url); + } + return false; } } @Override public void onLoadResource(WebView view, String url) { + + if (android.os.Build.VERSION.SDK_INT < 21){ + loadResourceDirect(view, url); + } + } + + private void loadResourceDirect(WebView view, String url){ if (url != null && url.startsWith("coherent-js")) { triggerNativeCode(view.getId(), url); } From f586f9f640545a5bdc8acc79e092852dee81d2e7 Mon Sep 17 00:00:00 2001 From: Sebastian Knapp Date: Mon, 8 Feb 2016 10:53:53 +0100 Subject: [PATCH 2/6] Renamed function in workaround --- Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java b/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java index 22cf900..a96bfa3 100644 --- a/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java +++ b/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java @@ -33,7 +33,7 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) { // Workaround for Android 5+, because WebView 47+ does not call onLoadResource like the previous versions did. // We could (or even should) be checking the WebView-Version here, but I didn't find a nice way to do that. if (android.os.Build.VERSION.SDK_INT >= 21){ - loadResourceDirect(view, url); + callTriggerNativeCode(view, url); } return false; @@ -44,11 +44,11 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) { public void onLoadResource(WebView view, String url) { if (android.os.Build.VERSION.SDK_INT < 21){ - loadResourceDirect(view, url); + callTriggerNativeCode(view, url); } } - private void loadResourceDirect(WebView view, String url){ + private void callTriggerNativeCode(WebView view, String url){ if (url != null && url.startsWith("coherent-js")) { triggerNativeCode(view.getId(), url); } From b02a377646283c1d19bf8294cc8c56326c36e1ef Mon Sep 17 00:00:00 2001 From: Sebastian Knapp Date: Tue, 16 Feb 2016 11:17:52 +0100 Subject: [PATCH 3/6] Added direct communication between js and WebView on Android --- .../ui/CoherentAndroidViewBridge.java | 12 +- .../ui/CoherentJavaScriptInterface.java | 9 +- .../ui/CoherentWebViewClient.java | 15 +- .../MobileInput/javascript/coherent.js | 135 ++++++++++++------ 4 files changed, 107 insertions(+), 64 deletions(-) diff --git a/Src/Android/com/coherentlabs/ui/CoherentAndroidViewBridge.java b/Src/Android/com/coherentlabs/ui/CoherentAndroidViewBridge.java index 8734f8b..5695774 100644 --- a/Src/Android/com/coherentlabs/ui/CoherentAndroidViewBridge.java +++ b/Src/Android/com/coherentlabs/ui/CoherentAndroidViewBridge.java @@ -30,6 +30,8 @@ public class CoherentAndroidViewBridge { private Activity mActivity; private WebView mWebView; + private CoherentWebViewClient mClient; + private CoherentAndroidViewBridge mBridge; private boolean mIsTransparent; public CoherentAndroidViewBridge(Activity activity) { @@ -37,6 +39,7 @@ public CoherentAndroidViewBridge(Activity activity) { Log.wtf(LOG_TAG, "Trying to create Coherent UI View with null activity!"); } + mBridge = this; mActivity = activity; } @@ -165,10 +168,11 @@ public void run() { } // WebViewClient must be set BEFORE calling loadUrl! - mWebView.setWebViewClient(new CoherentWebViewClient(mActivity, usesDefaultFileHandler)); + mClient = new CoherentWebViewClient(mActivity, usesDefaultFileHandler); + mWebView.setWebViewClient(mClient); mWebView.setWebChromeClient(new CoherentWebChromeClient()); - mWebView.addJavascriptInterface(new CoherentJavaScriptInterface(mWebView), CoherentJavaScriptInterface.INTERFACE_NAME); + mWebView.addJavascriptInterface(new CoherentJavaScriptInterface(mWebView, mBridge), CoherentJavaScriptInterface.INTERFACE_NAME); if (width != 0 && height != 0) { mActivity.addContentView(mWebView, @@ -367,6 +371,10 @@ public void run() { } }); } + + public CoherentWebViewClient getWebViewClient(){ + return mClient; + } private native void notifySoftKeyboardVisible(boolean visible); private native void notifyOnBitmapReady(int viewId, ByteBuffer buffer, diff --git a/Src/Android/com/coherentlabs/ui/CoherentJavaScriptInterface.java b/Src/Android/com/coherentlabs/ui/CoherentJavaScriptInterface.java index 8fb3295..3db59bf 100644 --- a/Src/Android/com/coherentlabs/ui/CoherentJavaScriptInterface.java +++ b/Src/Android/com/coherentlabs/ui/CoherentJavaScriptInterface.java @@ -7,10 +7,12 @@ public class CoherentJavaScriptInterface { public static final String INTERFACE_NAME = "__couiAndroid"; private WebView mWebView; + private CoherentAndroidViewBridge mBridge; private float mDPtoPXCoef; - public CoherentJavaScriptInterface(WebView webView) { + public CoherentJavaScriptInterface(WebView webView, CoherentAndroidViewBridge bridge) { mWebView = webView; + mBridge = bridge; DisplayMetrics displayMetrics = webView.getContext().getResources().getDisplayMetrics(); mDPtoPXCoef = displayMetrics.densityDpi / 160.0f; @@ -27,4 +29,9 @@ public void addTouchEvent(int fingerId, int phase, int x, int y) { } public native void addCoherentTouchEvent(int id, int fingerId, int phase, int x, int y); + + @JavascriptInterface + public void triggerNativeCode(String event) { + this.mBridge.getWebViewClient().triggerNativeCode(mWebView.getId(), event); + } } diff --git a/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java b/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java index a96bfa3..4db8643 100644 --- a/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java +++ b/Src/Android/com/coherentlabs/ui/CoherentWebViewClient.java @@ -29,26 +29,13 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url != null && !shouldStartLoad(view.getId(), url)) { Log.v(LOG_TAG, "Overriding URL loading of \"" + url + "\" for view " + view.getId()); return true; - } else { - // Workaround for Android 5+, because WebView 47+ does not call onLoadResource like the previous versions did. - // We could (or even should) be checking the WebView-Version here, but I didn't find a nice way to do that. - if (android.os.Build.VERSION.SDK_INT >= 21){ - callTriggerNativeCode(view, url); - } - + } else { return false; } } @Override public void onLoadResource(WebView view, String url) { - - if (android.os.Build.VERSION.SDK_INT < 21){ - callTriggerNativeCode(view, url); - } - } - - private void callTriggerNativeCode(WebView view, String url){ if (url != null && url.startsWith("coherent-js")) { triggerNativeCode(view.getId(), url); } diff --git a/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js b/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js index 0f6115c..142e877 100644 --- a/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js +++ b/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js @@ -239,19 +239,35 @@ return promise; }; - var simpleEvent = function (type) { - return function () { - var prefix = ['coherent-js', type], - frame = document.createElement('iframe'); - prefix.push.apply(prefix, arguments); - frame.src = prefix.join(':'); - frame.width = '1px'; - frame.height = '1px'; - document.documentElement.appendChild(frame); - frame.parentNode.removeChild(frame); - }; - }; + var simpleEvent; + + if(window.__couiAndroid == undefined) { + simpleEvent = function (type) { + return function () { + var prefix = ['coherent-js', type], + frame = document.createElement('iframe'); + prefix.push.apply(prefix, arguments); + frame.src = prefix.join(':'); + frame.width = '1px'; + frame.height = '1px'; + frame.style.display = 'none'; + document.documentElement.appendChild(frame); + window.setTimeout(function(){frame.parentNode.removeChild(frame)}, 2000); + }; + }; + }else{ + simpleEvent = function (type) { + return function () { + var prefix = ['coherent-js', type]; + prefix.push.apply(prefix, arguments); + __couiAndroid.triggerNativeCode(prefix.join(':')); + }; + }; + + + } + if (engine === undefined) { if (window.__couiAndroid !== undefined && window.__couiAndroid.initCoui !== undefined) @@ -266,7 +282,7 @@ { simpleEvent('q')(); } - + engine = window.engine; } @@ -376,30 +392,57 @@ }; } - var frame = document.createElement('iframe'); + var createSendMessage; + var createTriggerEvent; + + if(window.__couiAndroid == undefined) { - var createSendMessage = function () { - var prefix = 'coherent-js:c:'; - return function () { - var json = JSON.stringify(toArray.call(arguments, 2)); - frame.src = prefix + arguments[0] + ':' + arguments[1] + ':' + encodeURIComponent(json); - frame.width = '1px'; - frame.height = '1px'; - document.documentElement.appendChild(frame); - frame.parentNode.removeChild(frame); + createSendMessage = function () { + var prefix = 'coherent-js:c:'; + return function () { + var frame = document.createElement('iframe'); + var json = JSON.stringify(toArray.call(arguments, 2)); + frame.src = prefix + arguments[0] + ':' + arguments[1] + ':' + encodeURIComponent(json); + frame.width = '1px'; + frame.height = '1px'; + frame.style.display = 'none'; + document.documentElement.appendChild(frame); + window.setTimeout(function(){frame.parentNode.removeChild(frame)}, 2000); + }; }; - }; - var createTriggerEvent = function () { - var prefix = 'coherent-js:e:'; - return function () { - var json = JSON.stringify(toArray.call(arguments, 1)); - frame.src = prefix + arguments[0] + ':' + encodeURIComponent(json); - frame.width = '1px'; - frame.height = '1px'; - document.documentElement.appendChild(frame); - frame.parentNode.removeChild(frame); + + createTriggerEvent = function () { + var prefix = 'coherent-js:e:'; + return function () { + var frame = document.createElement('iframe'); + var json = JSON.stringify(toArray.call(arguments, 1)); + frame.src = prefix + arguments[0] + ':' + encodeURIComponent(json); + frame.width = '1px'; + frame.height = '1px'; + frame.style.display = 'none'; + document.documentElement.appendChild(frame); + window.setTimeout(function(){frame.parentNode.removeChild(frame)}, 2000); + }; }; - }; + + }else{ + createSendMessage = function () { + var prefix = 'coherent-js:c:'; + return function () { + var json = JSON.stringify(toArray.call(arguments, 2)); + __couiAndroid.triggerNativeCode(prefix + arguments[0] + ':' + arguments[1] + ':' + encodeURIComponent(json)); + }; + }; + + createTriggerEvent = function () { + var prefix = 'coherent-js:e:'; + return function () { + var json = JSON.stringify(toArray.call(arguments, 1)); + __couiAndroid.triggerNativeCode(prefix + arguments[0] + ':' + encodeURIComponent(json)); + }; + }; + } + engine.SendMessage = createSendMessage(); engine.TriggerEvent = createTriggerEvent(); @@ -410,7 +453,7 @@ }; var unload = simpleEvent('u'); - var unloadEvent = ((window.__couiAndroid === undefined) ? 'pagehide' : 'beforeunload'); + var unloadEvent = ((window.__couiAndroid === undefined) ? 'unload' : 'beforeunload'); window.addEventListener(unloadEvent, unload); engine.__observeLifetime = function () { @@ -447,14 +490,12 @@ engine._Result = function (requestId) { var deferred = engine._ActiveRequests[requestId]; - if (deferred !== undefined) - { - delete engine._ActiveRequests[requestId]; - var resultArguments = Array.prototype.slice.call(arguments); - resultArguments.shift(); - deferred.resolve.apply(deferred, resultArguments); - } + delete engine._ActiveRequests[requestId]; + + var resultArguments = Array.prototype.slice.call(arguments); + resultArguments.shift(); + deferred.resolve.apply(deferred, resultArguments); }; engine._Errors = [ 'Success', 'ArgumentType', 'NoSuchMethod', 'NoResult' ]; @@ -605,7 +646,7 @@ { // Input state: Take none event.preventDefault(); - + var touches = event.changedTouches; for (var i = 0; i < touches.length; ++i) { window.__couiAndroid.addTouchEvent(Number(touches[i].identifier), phase, touches[i].screenX, touches[i].screenY); @@ -624,20 +665,20 @@ } }; }; - + var setupCoherentForAndroidFunc = function() { document.body.addEventListener('touchstart', touchListener(0)); document.body.addEventListener('touchend', touchListener(3)); document.body.addEventListener('touchcancel', touchListener(4)); document.body.addEventListener('touchmove', touchListener(1)); - + var newdiv = document.createElement('div'); newdiv.setAttribute('id', '__CoherentBackground'); newdiv.setAttribute('class', 'coui-noinput'); newdiv.setAttribute('style', 'background-color: "rgba(0,0,0,0)";' + 'width: 100%; height: 100%; position: absolute;' + 'z-index: -1000000;'); - + document.body.insertBefore(newdiv, document.body.firstChild); }; @@ -647,7 +688,7 @@ document.addEventListener('DOMContentLoaded', setupCoherentForAndroidFunc); } - } + } if (hasOnLoad) { global.onload = (function (originalWindowLoaded) { From b702ace36884607f99abeaf36942e4617a3abe72 Mon Sep 17 00:00:00 2001 From: Sebastian Knapp Date: Tue, 16 Feb 2016 11:22:12 +0100 Subject: [PATCH 4/6] Added missing iframe variable --- .../uiresources/MobileInput/javascript/coherent.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js b/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js index 142e877..ccaaa32 100644 --- a/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js +++ b/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js @@ -396,8 +396,10 @@ var createTriggerEvent; if(window.__couiAndroid == undefined) { - - createSendMessage = function () { + + var frame = document.createElement('iframe'); + + createSendMessage = function () { var prefix = 'coherent-js:c:'; return function () { var frame = document.createElement('iframe'); @@ -434,7 +436,7 @@ }; }; - createTriggerEvent = function () { + createTriggerEvent = function () { var prefix = 'coherent-js:e:'; return function () { var json = JSON.stringify(toArray.call(arguments, 1)); From eb6b13620da409b5bc73bb754adbefeca411982c Mon Sep 17 00:00:00 2001 From: Sebastian Knapp Date: Tue, 16 Feb 2016 11:31:32 +0100 Subject: [PATCH 5/6] Fixed version chaos in coherent js --- .../MobileInput/javascript/coherent.js | 48 ++++++++----------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js b/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js index ccaaa32..ed3b21d 100644 --- a/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js +++ b/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js @@ -238,22 +238,20 @@ return promise; }; - + var simpleEvent; if(window.__couiAndroid == undefined) { simpleEvent = function (type) { - return function () { + return function () { var prefix = ['coherent-js', type], frame = document.createElement('iframe'); prefix.push.apply(prefix, arguments); frame.src = prefix.join(':'); frame.width = '1px'; frame.height = '1px'; - frame.style.display = 'none'; document.documentElement.appendChild(frame); - window.setTimeout(function(){frame.parentNode.removeChild(frame)}, 2000); - + frame.parentNode.removeChild(frame); }; }; }else{ @@ -264,10 +262,8 @@ __couiAndroid.triggerNativeCode(prefix.join(':')); }; }; - - } - + if (engine === undefined) { if (window.__couiAndroid !== undefined && window.__couiAndroid.initCoui !== undefined) @@ -282,7 +278,7 @@ { simpleEvent('q')(); } - + engine = window.engine; } @@ -402,28 +398,23 @@ createSendMessage = function () { var prefix = 'coherent-js:c:'; return function () { - var frame = document.createElement('iframe'); var json = JSON.stringify(toArray.call(arguments, 2)); frame.src = prefix + arguments[0] + ':' + arguments[1] + ':' + encodeURIComponent(json); frame.width = '1px'; frame.height = '1px'; - frame.style.display = 'none'; document.documentElement.appendChild(frame); - window.setTimeout(function(){frame.parentNode.removeChild(frame)}, 2000); + frame.parentNode.removeChild(frame); }; }; - createTriggerEvent = function () { var prefix = 'coherent-js:e:'; return function () { - var frame = document.createElement('iframe'); var json = JSON.stringify(toArray.call(arguments, 1)); frame.src = prefix + arguments[0] + ':' + encodeURIComponent(json); frame.width = '1px'; frame.height = '1px'; - frame.style.display = 'none'; document.documentElement.appendChild(frame); - window.setTimeout(function(){frame.parentNode.removeChild(frame)}, 2000); + frame.parentNode.removeChild(frame); }; }; @@ -444,7 +435,6 @@ }; }; } - engine.SendMessage = createSendMessage(); engine.TriggerEvent = createTriggerEvent(); @@ -455,7 +445,7 @@ }; var unload = simpleEvent('u'); - var unloadEvent = ((window.__couiAndroid === undefined) ? 'unload' : 'beforeunload'); + var unloadEvent = ((window.__couiAndroid === undefined) ? 'pagehide' : 'beforeunload'); window.addEventListener(unloadEvent, unload); engine.__observeLifetime = function () { @@ -492,12 +482,14 @@ engine._Result = function (requestId) { var deferred = engine._ActiveRequests[requestId]; + if (deferred !== undefined) + { + delete engine._ActiveRequests[requestId]; - delete engine._ActiveRequests[requestId]; - - var resultArguments = Array.prototype.slice.call(arguments); - resultArguments.shift(); - deferred.resolve.apply(deferred, resultArguments); + var resultArguments = Array.prototype.slice.call(arguments); + resultArguments.shift(); + deferred.resolve.apply(deferred, resultArguments); + } }; engine._Errors = [ 'Success', 'ArgumentType', 'NoSuchMethod', 'NoResult' ]; @@ -648,7 +640,7 @@ { // Input state: Take none event.preventDefault(); - + var touches = event.changedTouches; for (var i = 0; i < touches.length; ++i) { window.__couiAndroid.addTouchEvent(Number(touches[i].identifier), phase, touches[i].screenX, touches[i].screenY); @@ -667,20 +659,20 @@ } }; }; - + var setupCoherentForAndroidFunc = function() { document.body.addEventListener('touchstart', touchListener(0)); document.body.addEventListener('touchend', touchListener(3)); document.body.addEventListener('touchcancel', touchListener(4)); document.body.addEventListener('touchmove', touchListener(1)); - + var newdiv = document.createElement('div'); newdiv.setAttribute('id', '__CoherentBackground'); newdiv.setAttribute('class', 'coui-noinput'); newdiv.setAttribute('style', 'background-color: "rgba(0,0,0,0)";' + 'width: 100%; height: 100%; position: absolute;' + 'z-index: -1000000;'); - + document.body.insertBefore(newdiv, document.body.firstChild); }; @@ -690,7 +682,7 @@ document.addEventListener('DOMContentLoaded', setupCoherentForAndroidFunc); } - } + } if (hasOnLoad) { global.onload = (function (originalWindowLoaded) { From d5a9cbfbb8747360f979647c7d982cf9c7a66d6d Mon Sep 17 00:00:00 2001 From: Sebastian Knapp Date: Wed, 27 Apr 2016 15:15:01 +0200 Subject: [PATCH 6/6] Code style changes --- .../uiresources/MobileInput/javascript/coherent.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js b/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js index ed3b21d..191b501 100644 --- a/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js +++ b/UnityIntegration/Assets/WebPlayerTemplates/uiresources/MobileInput/javascript/coherent.js @@ -241,7 +241,7 @@ var simpleEvent; - if(window.__couiAndroid == undefined) { + if (window.__couiAndroid == undefined) { simpleEvent = function (type) { return function () { var prefix = ['coherent-js', type], @@ -254,7 +254,7 @@ frame.parentNode.removeChild(frame); }; }; - }else{ + } else { simpleEvent = function (type) { return function () { var prefix = ['coherent-js', type]; @@ -391,7 +391,7 @@ var createSendMessage; var createTriggerEvent; - if(window.__couiAndroid == undefined) { + if (window.__couiAndroid == undefined) { var frame = document.createElement('iframe'); @@ -418,7 +418,7 @@ }; }; - }else{ + } else { createSendMessage = function () { var prefix = 'coherent-js:c:'; return function () {