WebView 与 HTML

*JsBridge

v6.3.9新增
html>>

1<html>
2  <body style="font: size 2em">
3    <div style="font-size: 100px">原内容</div>
4    <!-- 导入依赖包,也可以不加,不过需要监听AutoxJsBridgeReady事件后才能使用$autox -->
5    <script src="autox://sdk.v1.js"></script>
6    <script>
7      function addText(text) {
8        const div = document.createElement("div");
9        div.innerHTML = text;
10        document.body.appendChild(div);
11      }
12      //注册一个监听函数
13      $autox.registerHandler("jsTest", (data, callBack) => {
14        addText(`来自安卓调用,data=${data}`);
15        setTimeout(() => {
16          //回调安卓
17          callBack("web回调数据");
18        }, 1000);
19      });
20      //调用安卓端
21      $autox.callHandler("test", "web调用数据", (data) => {
22        addText("安卓回调, data:" + data);
23      });
24
25      document.addEventListener("AutoxJsBridgeReady", () => {
26        //$autox.
27      });
28    </script>
29  </body>
30</html>

js代码

1"ui";
2
3ui.layout(`
4    <vertical>
5        <webview id="web" h="*"/>
6    </vertical>`)
7
8ui.web.loadUrl("file://" + files.path("./网页.html"))
9/*
10    注意:在web与安卓端传递的数据只能是字符串,其他数据需自行使用JSON序列化
11    在调用callHandler时传入了回调函数,但web端没有调用则会造成内存泄露。
12    jsBridge自动注入依赖于webViewClient,如设置了自定义webViewClient则需要在合适的时机(页面加载完成后)调用webview.injectionJsBridge()手动注入
13*/
14//注册一个监听函数
15ui.web.jsBridge.registerHandler("test", (data, callBack) => {
16    toastLog("web调用安卓,data:" + data)
17    setTimeout(() => {
18        //回调web
19        callBack("1155")
20    }, 2000)
21})
22//定时器中等待web加载完成
23setTimeout(() => {
24    ui.web.jsBridge.callHandler('jsTest', '数据', (data) => {
25        toastLog('web回调,data:' + data)
26    })
27}, 1000)

纯js实现

1"ui";
2ui.layout(
3    <vertical>
4        <horizontal bg="#c7edcc" gravity="center" h="auto">
5            <button text="网络冲浪" id="surfInternetBtn" style="Widget.AppCompat.Button.Colored" w="auto" />
6            <button text="记忆翻牌" id="loadLocalHtmlBtn" style="Widget.AppCompat.Button.Colored" w="auto" />
7            <button text="控制台" id="consoleBtn" style="Widget.AppCompat.Button.Colored" w="auto" />
8        </horizontal>
9        <vertical h="*" w="*">
10            <webview id="webView" layout_below="title" w="*" h="*" />
11        </vertical>
12    </vertical>
13);
14
15function callJavaScript(webViewWidget, script, callback) {
16    try {
17        console.assert(webViewWidget != null, "webView控件为空");
18        //console.log(script.toString())
19        webViewWidget.evaluateJavascript("javascript:" + script, new JavaAdapter(android.webkit.ValueCallback, {
20            onReceiveValue: (val) => {
21                if (callback) {
22                    callback(val);
23                }
24            }
25        }));
26    } catch (e) {
27        console.error("执行JavaScript失败");
28        console.trace(e);
29    }
30}
31
32function AutoX() {
33    let getAutoXFrame = () => {
34        let bridgeFrame = document.getElementById("AutoXFrame");
35        if (!bridgeFrame) {
36            bridgeFrame = document.createElement('iframe');
37            bridgeFrame.id = "AutoXFrame";
38            bridgeFrame.style = "display: none";
39            document.body.append(bridgeFrame);
40        }
41        return bridgeFrame;
42    };
43    const h5Callbackers = {};
44    let h5CallbackIndex = 1;
45    let setCallback = (callback) => {
46        let callId = h5CallbackIndex++;
47        h5Callbackers[callId] = {
48            "callback": callback
49        };
50        return callId;
51    };
52    let getCallback = (callId) => {
53        let callback = h5Callbackers[callId];
54        if (callback) {
55            delete h5Callbackers[callId];
56        }
57        return callback;
58    };
59
60    function invoke(cmd, params, callback) {
61        let callId = null;
62        try {
63            let paramsStr = JSON.stringify(params);
64            let AutoXFrame = getAutoXFrame();
65            callId = setCallback(callback);
66            AutoXFrame.src = "jsbridge://" + cmd + "/" + callId + "/" + encodeURIComponent(paramsStr);
67        } catch (e) {
68            if (callId) {
69                getCallback(callId);
70            }
71            console.trace(e);
72        }
73    };
74    let callback = (data) => {
75        let callId = data.callId;
76        let params = data.params;
77        let callbackFun = getCallback(callId);
78        if (callbackFun) {
79            callbackFun.callback(params);
80        }
81    };
82    return {
83        invoke: invoke,
84        callback: callback
85    };
86};
87function bridgeHandler_handle(cmd, params) {
88    console.log('bridgeHandler处理 cmd=%s, params=%s', cmd, JSON.stringify(params));
89    let fun = this[cmd];
90    if (!fun) {
91        throw new Error("cmd= " + cmd + " 没有定义实现");
92    }
93    let ret = fun(params)
94    return ret;
95}
96function mFunction(params) {
97    toastLog(params.toString());
98    device.vibrate(120);
99    return files.isDir('/storage/emulated/0/Download')//'toast提示成功';
100}
101function webViewExpand_init(webViewWidget) {
102    webViewWidget.webViewClient = new JavaAdapter(android.webkit.WebViewClient, {
103        onPageFinished: (webView, curUrl) => {
104            try {
105                // 注入 AutoX
106                callJavaScript(webView, AutoX.toString() + ";var auto0 = AutoX();auto0.invoke('mFunction','This is AutoX!',(data) => {console.log('接收到callback1:' + JSON.stringify(data));});", null);
107            } catch (e) {
108                console.trace(e)
109            }
110        },
111        shouldOverrideUrlLoading: (webView, request) => {
112            let url = '';
113            try {
114                url = (request.a && request.a.a) || (request.url);
115                if (url instanceof android.net.Uri) {
116                    url = url.toString();
117                }
118                if (url.indexOf("jsbridge://") == 0) {
119                    let uris = url.split("/");
120                    let cmd = uris[2];
121                    let callId = uris[3];
122                    let params = java.net.URLDecoder.decode(uris[4], "UTF-8");
123                    console.log('AutoX处理JavaScript调用请求: callId=%s, cmd=%s, params=%s', callId, cmd, params);
124                    let result = null;
125                    try {
126                        result = bridgeHandler_handle(cmd, JSON.parse(params));
127                    } catch (e) {
128                        console.trace(e);
129                        result = {
130                            message: e.message
131                        };
132                    }
133                    result = result || {};
134                    webView.loadUrl("javascript:auto0.callback({'callId':" + callId + ", 'params': " + JSON.stringify(result) + "});");
135                } else if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("file://") || url.startsWith("ws://") || url.startsWith("wss://")) {
136                    webView.loadUrl(url);
137                } else {
138                }
139                return true;
140            } catch (e) {
141                if (e.javaException instanceof android.content.ActivityNotFoundException) {
142                    webView.loadUrl(url);
143                } else {
144                    toastLog('无法打开URL: ' + url);
145                }
146                console.trace(e);
147            }
148        },
149        onReceivedError: (webView, webResourceRequest, webResourceError) => {
150            let url = webResourceRequest.getUrl();
151            let errorCode = webResourceError.getErrorCode();
152            let description = webResourceError.getDescription();
153            console.trace(errorCode + " " + description + " " + url);
154        }
155    });
156    webViewWidget.webChromeClient = new JavaAdapter(android.webkit.WebChromeClient, {
157        onConsoleMessage: (msg) => {
158            console.log("[%s:%s]: %s", msg.sourceId(), msg.lineNumber(), msg.message());
159        }
160    });
161}
162webViewExpand_init(ui.webView)
163ui.webView.loadUrl("https://wht.im");
164
165ui.surfInternetBtn.on("click", () => {
166    webViewExpand_init(ui.webView);
167    ui.webView.loadUrl("https://wht.im");
168});
169ui.consoleBtn.on("click", () => {
170    app.startActivity("console");
171});
172ui.loadLocalHtmlBtn.on('click', () => {
173    webViewExpand_init(ui.webView);
174    let path = "file:" + files.path("game.html");
175    ui.webView.loadUrl(path);
176});