title: creator-webview与Android交互
categories: Cocos2dx
tags: [cocos2dx, creator, webview, 交互]
date: 2024-03-23 13:17:20
comments: false
mathjax: true
toc: true
creator-webview与Android交互
前篇
- Android:你要的WebView与 JS 交互方式 都在这里了 - https://cloud.tencent.com/developer/article/1394361
java 调用 js
-
使用
WebView.evaluateJavascript
执行 js 代码javaString callStr = String.format("window['java2js'](`%s`, `%s`)", funcName, jsonMsg); WebViewIns.evaluateJavascript(callStr, null);
如果要透传数据结构或 json, 最好用 base64 加密一下, 然后在 js 中再解密出来, 以保证这些数据不会破会 js 代码的结构
一般跨语言的交互中, 我都会使用 base64 去加密数据使之变成正常的字符串
js 调用 java
-
使用
WebView.addJavascriptInterface(Object, String);
映射对象和方法到 js 中一个变量, 例如:javapublic static class JsUtils { @JavascriptInterface public void call(String funcName, String jsonMsg) { // 具体多少个参数对上 js 即可 ... } } WebViewIns.addJavascriptInterface(new JsUtils(), "gJavaObj");
-
直接使用 gJavaObj 对象即可
jsgJavaObj.call(funcName, jsonMsg);
加载 js 代码
-
使用
WebView.loadUrl
jsString bdg = "js 代码"; WebView.loadUrl("javascript:" + bdg);
-
js 代码书写有严格的要求, 例如:
js// 1. 一定要以这种 执行方法 的方式初始化 // 2. 语句结尾要加 ;, 不然报错 Invalid left-hand side expression in postfix operation // 3. 注释必须清楚掉 (function() { window.cm = {}; window.java2js = function(f, m) { var oldCb = window.cm[f]; if (oldCb) oldCb(window.atob(m)); window.cm[f] = null; }; window.WebViewJavascriptBridge = { init: function() { }, registerHandler: function() { }, callHandler: function(f, m, c) { window.cm[f] = c; gJavaObj.call(f, m); }, }; document.dispatchEvent(new Event("WebViewJavascriptBridgeReady")); })()
-
可以使用 uglyjs 把代码压缩成一行
jsString bdg = "window.cm={},window.java2js=function(f,m){var oldCb=window.cm[f];oldCb&&oldCb(window.atob(m)),window.cm[f]=null},window.WebViewJavascriptBridge={init:function(){},registerHandler:function(){},callHandler:function(f,m,c){window.cm[f]=c,gJavaObj.call(f,m)}},document.dispatchEvent(new Event(\"WebViewJavascriptBridgeReady\"));"
-
完整的 java, html 代码
java
-
代码
jsonimport android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.net.http.SslError; import android.util.Base64; import android.view.ViewGroup; import android.webkit.JavascriptInterface; import android.webkit.SslErrorHandler; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.LinearLayout; import android.widget.RelativeLayout; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; public class WebviewHelper { public static WebviewHelper instance = null; private RelativeLayout mLayoutRoot; private WebView mWebview; private static Map<String, BridgeHandler> mJsCb = new HashMap<>(); public static void showWebview(final Activity activity, final String url, final ActivityMgr.CodeRunnable task) { closeWebview(activity, () -> { instance = new WebviewHelper(); instance.show(activity, url); if (task != null) { task.run(ActivityMgr.Ok, ""); } }); } public static void closeWebview(final Activity activity, final Runnable task) { activity.runOnUiThread(() -> { if (instance != null) { instance.destroy(); } if (task != null) { task.run(); } }); } public static boolean goBack() { ActivityMgr.Act.moveTaskToBack(true); return false; } @SuppressLint("SetJavaScriptEnabled") public void show(Activity activity, final String url) { final RelativeLayout rLayout = new RelativeLayout(activity); mLayoutRoot = rLayout; RelativeLayout.LayoutParams rParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); LinearLayout.LayoutParams lParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); final WebView wv = new WebView(activity); wv.setWebViewClient(new WebviewClientHelper()); mWebview = wv; wv.setLayoutParams(lParams); rLayout.addView(wv); activity.addContentView(rLayout, rParams); mWebview.addJavascriptInterface(new JsUtils(), "gJavaObj");//AndroidtoJS类对象映射到js的test对象 wv.loadUrl(url); // 设置webview WebSettings settings = wv.getSettings(); settings.setJavaScriptCanOpenWindowsAutomatically(true); settings.setJavaScriptEnabled(true); settings.setDomStorageEnabled(true); settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); // 有缓存就使用缓存 settings.setSupportZoom(false); settings.setBuiltInZoomControls(true); } public static void regHandler(String name, BridgeHandler bh) { mJsCb.put(name, bh); } private void destroy() { if (mWebview != null) { mWebview.destroy(); mWebview = null; } if (mLayoutRoot != null) { ViewGroup vg = (ViewGroup) mLayoutRoot.getParent(); vg.removeView(mLayoutRoot); mLayoutRoot = null; } instance = null; } public interface BridgeHandler { void handler(String var1, Consumer<String> var2); } public static class JsUtils { @JavascriptInterface public void call(String funcName, String jsonMsg) { BridgeHandler bh = mJsCb.get(funcName); if (bh == null) { ActivityMgr.E("no func: %s", funcName); return; } bh.handler(jsonMsg, (result) -> { try { // 交互是需要 base64 处理一下 result = Base64.encodeToString((result != null ? result : "").getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); String callStr = String.format("window['java2js'](`%s`, `%s`)", funcName, result); instance.mWebview.evaluateJavascript(callStr, null); } catch (Exception e) { e.printStackTrace(); } }); } } public static class WebviewClientHelper extends WebViewClient { public boolean isLoadBdg = false; @Override public void onPageFinished(WebView view, String url) { if (!isLoadBdg) { String bdg = "window.cm={},window.java2js=function(f,m){var oldCb=window.cm[f];oldCb&&oldCb(window.atob(m)),window.cm[f]=null},window.WebViewJavascriptBridge={init:function(){},registerHandler:function(){},callHandler:function(f,m,c){window.cm[f]=c,gJavaObj.call(f,m)}},document.dispatchEvent(new Event(\"WebViewJavascriptBridgeReady\"));"; view.loadUrl("javascript:" + bdg); isLoadBdg = true; } super.onPageFinished(view, url); } } }
html
-
代码
html<!DOCTYPE html> <html> <head> <script> document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { console.log("--- WebViewJavascriptBridgeReady"); }, false ); function js2java() { console.log("--- js2java"); // gJavaObj.hello("Hello Terry") var funcName = "StartInfo" var jsonMsg = "World 002" window.WebViewJavascriptBridge.callHandler(funcName, jsonMsg, function(responseData) { console.log("--- responseData:", responseData); }) } console.log("--- web loaded"); </script> <title>Test Webview</title> </head> <body> <div id="mydiv"> <br /><br /><button onclick="js2java()"> js2java </button> </div> </body> </html>