M8Test Help

使用 WebViewBridge

从脚本调用JavaScript

import com.m8test.script.GlobalVariables.* // ---------------------------------------------------- // 示例 3.1: 脚本调用JS (完整代码) // ---------------------------------------------------- _console.info("\n--- 开始示例 3.1: 脚本调用JS ---") // 1. 基础设置 val scope = _coroutines.newScope { setDispatcher { it.getIO() } } val bridge = _webView.getBridge() val controller = bridge.getController() _activity.start() // 2. 准备HTML val html = """ <html><body> <div id="message">...</div> <script> (function () { function init() { // ${'$'}webViewBridge.registerHandler() 用于设置供脚本端调用的处理器,第一个参数是处理器名,第二个参数是一个函数,会在处理器被调用时执行 ${'$'}webViewBridge.registerHandler("updateMessage", function (name, callback) { // name 为脚本端调用处理器时传递过来的参数 // callback 用于返回处理结果到脚本端 if (callback) { document.getElementById('message').innerText = '你好, ' + name + '!'; callback('JS已成功更新消息'); } }) } if (window.${'$'}webViewBridge) { init(); } else { document.addEventListener( 'WebViewBridgeReady', function () { //do your work here init(); }, false ); } })() </script> </body></html> """ // 3. 开始异步操作链 scope.delay(1000) // 关键延时:等待Activity和WebView初始化完成 .then { s, _ -> controller.loadDataWithBaseURL(s, "https://native2js.test", html, null, null, "https://native2js.test") } .then { s, _ -> _console.log("页面加载指令已发出,等待渲染...") s.delay(1000) } .then { s, _ -> bridge.callHandler("updateMessage", "\"M8Test\"") { result -> _console.log("来自JS的回调:", result) } s.delay(500) // 等待JS执行和DOM更新 } .then { s, _ -> controller.getTextContent(s, "//*[@id='message']") } .then { s, message -> _console.assertTrue(message.toString().contains("M8Test"), "JS函数调用验证失败") _console.info("--- 示例 3.1: 成功 ---") s.resolve(null) } .onError { e -> _console.error("--- 示例 3.1: 失败 ---", e.stackTraceToString()) }
// ---------------------------------------------------- // 示例 3.1: 脚本调用JS (完整代码) // ---------------------------------------------------- $console.info("\n--- 开始示例 3.1: 脚本调用JS ---") // 1. 基础设置 def scope = $coroutines.newScope { it.setDispatcher { it.getIO() } } def bridge = $webView.getBridge() def controller = bridge.getController() $activity.start() // 2. 准备HTML def html = """ <html><body> <div id="message">...</div> <script> (function () { function init() { // \$webViewBridge.registerHandler() 用于设置供脚本端调用的处理器,第一个参数是处理器名,第二个参数是一个函数,会在处理器被调用时执行 \$webViewBridge.registerHandler("updateMessage", function (name, callback) { // name 为脚本端调用处理器时传递过来的参数 // callback 用于返回处理结果到脚本端 if (callback) { document.getElementById('message').innerText = '你好, ' + name + '!'; callback('JS已成功更新消息'); } }) } if (window.\$webViewBridge) { init(); } else { document.addEventListener( 'WebViewBridgeReady', function () { //do your work here init(); }, false ); } })() </script> </body></html> """ // 3. 开始异步操作链 scope.delay(1000) // 关键延时:等待Activity和WebView初始化完成 .then { s, _ -> return controller.loadDataWithBaseURL(s, "https://native2js.test", html, null, null, "https://native2js.test") } .then { s, _ -> $console.log("页面加载指令已发出,等待渲染...") return s.delay(1000) } .then { s, _ -> bridge.callHandler("updateMessage", '"M8Test"') { result -> $console.log("来自JS的回调:", result) } return s.delay(500) // 等待JS执行和DOM更新 } .then { s, _ -> return controller.getTextContent(s, "//*[@id='message']") } .then { s, message -> $console.assertTrue(message.contains("M8Test"), "JS函数调用验证失败") $console.info("--- 示例 3.1: 成功 ---") return s.resolve(null) } .onError { e -> $console.error("--- 示例 3.1: 失败 ---", e.stackTraceToString()) }
// ---------------------------------------------------- // 示例 3.1: 脚本调用JS (完整代码) // ---------------------------------------------------- $console.info("\n--- 开始示例 3.1: 脚本调用JS ---"); // 1. 基础设置 const scope = $coroutines.newScope(it => it.setDispatcher(it => it.getIO())); const bridge = $webView.getBridge(); const controller = bridge.getController(); $activity.start(); // 2. 准备HTML const html = ` <html><body> <div id="message">...</div> <script> (function () { function init() { // \$webViewBridge.registerHandler() 用于设置供脚本端调用的处理器,第一个参数是处理器名,第二个参数是一个函数,会在处理器被调用时执行 \$webViewBridge.registerHandler("updateMessage", function (name, callback) { // name 为脚本端调用处理器时传递过来的参数 // callback 用于返回处理结果到脚本端 if (callback) { document.getElementById('message').innerText = '你好, ' + name + '!'; callback('JS已成功更新消息'); } }) } if (window.\$webViewBridge) { init(); } else { document.addEventListener( 'WebViewBridgeReady', function () { //do your work here init(); }, false ); } })() </script> </body></html> `; // 3. 开始异步操作链 scope.delay(1000) // 关键延时:等待Activity和WebView初始化完成 .then((s, _) => { return controller.loadDataWithBaseURL(s, "https://native2js.test", html, null, null, "https://native2js.test"); }) .then((s, _) => { $console.log("页面加载指令已发出,等待渲染..."); return s.delay(1000); }) .then((s, _) => { bridge.callHandler("updateMessage", '"M8Test"', result => { $console.log("来自JS的回调:", result); }); return s.delay(500); // 等待JS执行和DOM更新 }) .then((s, _) => { return controller.getTextContent(s, "//*[@id='message']"); }) .then((s, message) => { $console.assertTrue(message.includes("M8Test"), "JS函数调用验证失败"); $console.info("--- 示例 3.1: 成功 ---"); return s.resolve(null); }) .onError(e => $console.error("--- 示例 3.1: 失败 ---", e.stackTraceToString()));
-- ---------------------------------------------------- -- 示例 3.1: 脚本调用JS (完整代码) -- ---------------------------------------------------- _console:info("\n--- 开始示例 3.1: 脚本调用JS ---") -- 1. 基础设置 local scope = _coroutines:newScope(function(it) it:setDispatcher(function(it) return it:getIO() end) end) local bridge = _webView:getBridge() local controller = bridge:getController() _activity:start() -- 2. 准备HTML local html = [[ <html><body> <div id="message">...</div> <script> (function () { function init() { // $webViewBridge.registerHandler() 用于设置供脚本端调用的处理器,第一个参数是处理器名,第二个参数是一个函数,会在处理器被调用时执行 $webViewBridge.registerHandler("updateMessage", function (name, callback) { // name 为脚本端调用处理器时传递过来的参数 // callback 用于返回处理结果到脚本端 if (callback) { document.getElementById('message').innerText = '你好, ' + name + '!'; callback('JS已成功更新消息'); } }) } if (window.$webViewBridge) { init(); } else { document.addEventListener( 'WebViewBridgeReady', function () { //do your work here init(); }, false ); } })() </script> </body></html> ]] -- 3. 开始异步操作链 scope:delay(1000) -- 关键延时:等待Activity和WebView初始化完成 :_then(function(s, _) return controller:loadDataWithBaseURL(s, "https://native2js.test", html, nil, nil, "https://native2js.test") end) :_then(function(s, _) _console:log("页面加载指令已发出,等待渲染...") return s:delay(1000) end) :_then(function(s, _) bridge:callHandler("updateMessage", '"M8Test"', function(result) _console:log("来自JS的回调:", result) end) return s:delay(500) -- 等待JS执行和DOM更新 end) :_then(function(s, _) return controller:getTextContent(s, "//*[@id='message']") end) :_then(function(s, message) -- 修复: 1. 检查 message 是否为 nil. 2. 使用 string.find 替代 :contains _console:assertTrue(message and string.find(message, "M8Test"), "JS函数调用验证失败") _console:info("--- 示例 3.1: 成功 ---") return s:resolve(nil) end) :onError(function(e) _console:error("--- 示例 3.1: 失败 ---", e:stackTraceToString()) end)
<?php /** @var m8test_java\com\m8test\script\core\api\console\Console $console */ global $console; /** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */ global $coroutines; /** @var m8test_java\com\m8test\script\core\api\ui\webview\WebView $webView */ global $webView; /** @var m8test_java\com\m8test\script\core\api\ui\Activity $activity */ global $activity; /** @var m8test_java\com\m8test\script\core\api\resource\StringResources $strings */ global $strings; // ---------------------------------------------------- // 示例 3.1: 脚本调用JS (完整代码) // ---------------------------------------------------- $console->info(javaString("\n--- 开始示例 3.1: 脚本调用JS ---")); // 1. 基础设置 $scope = $coroutines->newScope(function ($it) { $it->setDispatcher(function ($dispatchers) { return $dispatchers->getScriptMain(); }); }); $bridge = $webView->getBridge(); $controller = $bridge->getController(); $activity->start(); // 2. 准备HTML $html = <<<HTML <html><body> <div id="message">...</div> <script> (function () { function init() { // \$webViewBridge.registerHandler() 用于设置供脚本端调用的处理器,第一个参数是处理器名,第二个参数是一个函数,会在处理器被调用时执行 \$webViewBridge.registerHandler("updateMessage", function (name, callback) { // name 为脚本端调用处理器时传递过来的参数 // callback 用于返回处理结果到脚本端 if (callback) { document.getElementById('message').innerText = '你好, ' + name + '!'; callback('JS已成功更新消息'); } }) } if (window.\$webViewBridge) { init(); } else { document.addEventListener( 'WebViewBridgeReady', function () { //do your work here init(); }, false ); } })() </script> </body></html> HTML; // 3. 开始异步操作链 $scope->delay(1000) // 关键延时:等待Activity和WebView初始化完成 ->then(function ($s, $unused) use ($controller, $html) { return $controller->loadDataWithBaseURL($s, javaString("https://native2js.test"), javaString($html), null, null, javaString("https://native2js.test")); }) ->then(function ($s, $unused) { global $console; $console->log(javaString("页面加载指令已发出,等待渲染...")); return $s->delay(1000); }) ->then(function ($s, $unused) use ($bridge) { $bridge->callHandler(javaString("updateMessage"), javaString('"M8Test"'), function ($result) { global $console; $console->log(javaString("来自JS的回调:"), $result); }); return $s->delay(500); // 等待JS执行和DOM更新 }) ->then(function ($s, $unused) use ($controller) { return $controller->getTextContent($s, javaString("//*[@id='message']")); }) ->then(function ($s, $message) { global $console, $strings; $console->assertTrue($strings->contains($message, javaString("M8Test")), javaString("JS函数调用验证失败")); $console->info(javaString("--- 示例 3.1: 成功 ---")); return $s->resolve(null); }) ->onError(function ($e) { global $console; $console->error(javaString("--- 示例 3.1: 失败 ---"), $e->stackTraceToString()); });
# ---------------------------------------------------- # 示例 3.1: 脚本调用JS (完整代码) # ---------------------------------------------------- # 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _console from m8test_java.com.m8test.script.GlobalVariables import _coroutines from m8test_java.com.m8test.script.GlobalVariables import _webView from m8test_java.com.m8test.script.GlobalVariables import _activity _console.info("\n--- 开始示例 3.1: 脚本调用JS ---") # 1. 基础设置 # 【已修正】: 使用 getScriptMain() scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda d: d.getScriptMain())) bridge = _webView.getBridge() controller = bridge.getController() _activity.start() # 2. 准备HTML html = """ <html><body> <div id="message">...</div> <script> (function () { function init() { // $webViewBridge.registerHandler() 用于设置供脚本端调用的处理器,第一个参数是处理器名,第二个参数是一个函数,会在处理器被调用时执行 $webViewBridge.registerHandler("updateMessage", function (name, callback) { // name 为脚本端调用处理器时传递过来的参数 // callback 用于返回处理结果到脚本端 if (callback) { document.getElementById('message').innerText = '你好, ' + name + '!'; callback('JS已成功更新消息'); } }) } if (window.$webViewBridge) { init(); } else { document.addEventListener( 'WebViewBridgeReady', function () { //do your work here init(); }, false ); } })() </script> </body></html> """ # 3. 开始异步操作链 scope.delay(1000).then(lambda s, _: controller.loadDataWithBaseURL(s, "https://native2js.test", html, None, None, "https://native2js.test") ).then(lambda s, _: ( _console.log("页面加载指令已发出,等待渲染..."), s.delay(1000) )[-1]).then(lambda s, _: ( # Groovy's trailing closure is converted to a positional lambda argument bridge.callHandler("updateMessage", '"M8Test"', lambda result: _console.log("来自JS的回调:", str(result)) ), s.delay(500) # 等待JS执行和DOM更新 )[-1]).then(lambda s, _: controller.getTextContent(s, "//*[@id='message']") ).then(lambda s, message: ( _console.assertTrue("M8Test" in str(message), "JS函数调用验证失败"), _console.info("--- 示例 3.1: 成功 ---"), s.resolve(None) )[-1]).onError(lambda e: _console.error("--- 示例 3.1: 失败 ---", e.stackTraceToString()) )
# encoding: utf-8 # ---------------------------------------------------- # 示例 3.1: 脚本调用JS (完整代码) # ---------------------------------------------------- $console.info("\n--- 开始示例 3.1: 脚本调用JS ---") # 1. 基础设置 scope = $coroutines.newScope { |it| it.setDispatcher { |d| d.getIO() } } bridge = $webView.getBridge() controller = bridge.getController() $activity.start() # 2. 准备HTML html = <<-HTML <html><body> <div id="message">...</div> <script> (function () { function init() { // $webViewBridge.registerHandler() 用于设置供脚本端调用的处理器,第一个参数是处理器名,第二个参数是一个函数,会在处理器被调用时执行 $webViewBridge.registerHandler("updateMessage", function (name, callback) { // name 为脚本端调用处理器时传递过来的参数 // callback 用于返回处理结果到脚本端 if (callback) { document.getElementById('message').innerText = '你好, ' + name + '!'; callback('JS已成功更新消息'); } }) } if (window.$webViewBridge) { init(); } else { document.addEventListener( 'WebViewBridgeReady', function () { //do your work here init(); }, false ); } })() </script> </body></html> HTML # 3. 开始异步操作链 scope.delay(1000). # 关键延时:等待Activity和WebView初始化完成 then { |s, _| controller.loadDataWithBaseURL(s, "https://native2js.test", html, nil, nil, "https://native2js.test") }. then { |s, _| $console.log("页面加载指令已发出,等待渲染...") s.delay(1000) }. then { |s, _| bridge.callHandler("updateMessage", '"M8Test"') { |result| $console.log("来自JS的回调:", result) } s.delay(500) # 等待JS执行和DOM更新 }. then { |s, _| controller.getTextContent(s, "//*[@id='message']") }. then { |s, message| $console.assertTrue(message.include?("M8Test"), "JS函数调用验证失败") $console.info("--- 示例 3.1: 成功 ---") s.resolve(nil) }. onError { |e| $console.error("--- 示例 3.1: 失败 ---", e.to_s) }

从JavaScript调用脚本

import com.m8test.script.GlobalVariables.* // ---------------------------------------------------- // 示例 3.2: JS调用脚本 (完整代码) // ---------------------------------------------------- _console.info("\n--- 开始示例 3.2: JS调用脚本 ---") // 1. 基础设置 val scope = _coroutines.newScope { setDispatcher { it.getIO() } } val bridge = _webView.getBridge() val controller = bridge.getController() _activity.start() // 2. 同步注册处理器 bridge.registerHandler("getDeviceInfo") { params -> _console.log("JS调用了 getDeviceInfo, 参数:", params) "{\"platform\": \"Android\"}" } // 3. 准备HTML val html = """ <html><body> <div id="device-info"></div> <script> setTimeout(function() { window.WebViewJavascriptBridge.callHandler('getDeviceInfo', null, function(info) { var data = JSON.parse(info); document.getElementById('device-info').innerText = '平台: ' + data.platform; }); }, 1000); </script> </body></html> """ // 4. 开始异步操作链 scope.delay(1000) // 关键延时:等待Activity和WebView初始化完成 .then { s, _ -> controller.loadDataWithBaseURL(s, "https://js2native.test", html, null, null, "https://js2native.test") } .then { s, _ -> // 等待页面加载和JS中的setTimeout执行 s.delay(2000) } .then { s, _ -> controller.getTextContent(s, "//*[@id='device-info']") } .then { s, infoText -> _console.log("页面显示的设备信息:", infoText) _console.assertTrue(infoText.toString().contains("Android"), "JS调用脚本验证失败") _console.info("--- 示例 3.2: 成功 ---") s.resolve(null) } .onComplete { bridge.unregisterHandler("getDeviceInfo") } .onError { e -> _console.error("--- 示例 3.2: 失败 ---", e.stackTraceToString()) }
// ---------------------------------------------------- // 示例 3.2: JS调用脚本 (完整代码) // ---------------------------------------------------- $console.info("\n--- 开始示例 3.2: JS调用脚本 ---") // 1. 基础设置 def scope = $coroutines.newScope { it.setDispatcher { it.getIO() } } def bridge = $webView.getBridge() def controller = bridge.getController() $activity.start() // 2. 同步注册处理器 bridge.registerHandler("getDeviceInfo") { params -> $console.log("JS调用了 getDeviceInfo, 参数:", params) return '{"platform": "Android"}' } // 3. 准备HTML def html = """ <html><body> <div id="device-info"></div> <script> setTimeout(function() { window.WebViewJavascriptBridge.callHandler('getDeviceInfo', null, function(info) { var data = JSON.parse(info); document.getElementById('device-info').innerText = '平台: ' + data.platform; }); }, 1000); </script> </body></html> """ // 4. 开始异步操作链 scope.delay(1000) // 关键延时:等待Activity和WebView初始化完成 .then { s, _ -> return controller.loadDataWithBaseURL(s, "https://js2native.test", html, null, null, "https://js2native.test") } .then { s, _ -> // 等待页面加载和JS中的setTimeout执行 return s.delay(2000) } .then { s, _ -> return controller.getTextContent(s, "//*[@id='device-info']") } .then { s, infoText -> $console.log("页面显示的设备信息:", infoText) $console.assertTrue(infoText.contains("Android"), "JS调用脚本验证失败") $console.info("--- 示例 3.2: 成功 ---") return s.resolve(null) } .onComplete { bridge.unregisterHandler("getDeviceInfo") } .onError { e -> $console.error("--- 示例 3.2: 失败 ---", e.stackTraceToString()) }
// ---------------------------------------------------- // 示例 3.2: JS调用脚本 (完整代码) // ---------------------------------------------------- $console.info("\n--- 开始示例 3.2: JS调用脚本 ---"); // 1. 基础设置 const scope = $coroutines.newScope(it => it.setDispatcher(it => it.getIO())); const bridge = $webView.getBridge(); const controller = bridge.getController(); $activity.start(); // 2. 同步注册处理器 bridge.registerHandler("getDeviceInfo", params => { $console.log("JS调用了 getDeviceInfo, 参数:", params); return '{"platform": "Android"}'; }); // 3. 准备HTML const html = ` <html><body> <div id="device-info"></div> <script> setTimeout(function() { window.WebViewJavascriptBridge.callHandler('getDeviceInfo', null, function(info) { var data = JSON.parse(info); document.getElementById('device-info').innerText = '平台: ' + data.platform; }); }, 1000); </script> </body></html> `; // 4. 开始异步操作链 scope.delay(1000) // 关键延时:等待Activity和WebView初始化完成 .then((s, _) => { return controller.loadDataWithBaseURL(s, "https://js2native.test", html, null, null, "https://js2native.test"); }) .then((s, _) => { // 等待页面加载和JS中的setTimeout执行 return s.delay(2000); }) .then((s, _) => { return controller.getTextContent(s, "//*[@id='device-info']"); }) .then((s, infoText) => { $console.log("页面显示的设备信息:", infoText); $console.assertTrue(infoText.includes("Android"), "JS调用脚本验证失败"); $console.info("--- 示例 3.2: 成功 ---"); return s.resolve(null); }) .onComplete(() => bridge.unregisterHandler("getDeviceInfo")) .onError(e => $console.error("--- 示例 3.2: 失败 ---", e.stackTraceToString()));
-- ---------------------------------------------------- -- 示例 3.2: JS调用脚本 (完整代码) -- ---------------------------------------------------- _console:info("\n--- 开始示例 3.2: JS调用脚本 ---") -- 1. 基础设置 local scope = _coroutines:newScope(function(it) it:setDispatcher(function(it) return it:getIO() end) end) local bridge = _webView:getBridge() local controller = bridge:getController() _activity:start() -- 2. 同步注册处理器 bridge:registerHandler("getDeviceInfo", function(params) _console:log("JS调用了 getDeviceInfo, 参数:", params) return '{"platform": "Android"}' end) -- 3. 准备HTML local html = [[ <html><body> <div id="device-info"></div> <script> setTimeout(function() { window.WebViewJavascriptBridge.callHandler('getDeviceInfo', null, function(info) { var data = JSON.parse(info); document.getElementById('device-info').innerText = '平台: ' + data.platform; }); }, 1000); </script> </body></html> ]] -- 4. 开始异步操作链 scope:delay(1000) -- 关键延时:等待Activity和WebView初始化完成 :_then(function(s, _) return controller:loadDataWithBaseURL(s, "https://js2native.test", html, nil, nil, "https://js2native.test") end) :_then(function(s, _) -- 等待页面加载和JS中的setTimeout执行 return s:delay(2000) end) :_then(function(s, _) return controller:getTextContent(s, "//*[@id='device-info']") end) :_then(function(s, infoText) _console:log("页面显示的设备信息:", infoText) -- [修正] _console:assertTrue(_strings:contains(infoText, "Android"), "JS调用脚本验证失败") _console:info("--- 示例 3.2: 成功 ---") return s:resolve(nil) end) :onComplete(function() bridge:unregisterHandler("getDeviceInfo") end) :onError(function(e) _console:error("--- 示例 3.2: 失败 ---", e:stackTraceToString()) end)
<?php /** @var m8test_java\com\m8test\script\core\api\console\Console $console */ global $console; /** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */ global $coroutines; /** @var m8test_java\com\m8test\script\core\api\ui\webview\WebView $webView */ global $webView; /** @var m8test_java\com\m8test\script\core\api\ui\Activity $activity */ global $activity; /** @var m8test_java\com\m8test\script\core\api\resource\StringResources $strings */ global $strings; // ---------------------------------------------------- // 示例 3.2: JS调用脚本 (完整代码) // ---------------------------------------------------- $console->info(javaString("\n--- 开始示例 3.2: JS调用脚本 ---")); // 1. 基础设置 $scope = $coroutines->newScope(function ($it) { $it->setDispatcher(function ($dispatchers) { return $dispatchers->getScriptMain(); }); }); $bridge = $webView->getBridge(); $controller = $bridge->getController(); $activity->start(); // 2. 同步注册处理器 $bridge->registerHandler(javaString("getDeviceInfo"), function ($params) { global $console; $console->log(javaString("JS调用了 getDeviceInfo, 参数:"), $params); return javaString('{"platform": "Android"}'); }); // 3. 准备HTML $html = <<<HTML <html><body> <div id="device-info"></div> <script> setTimeout(function() { window.WebViewJavascriptBridge.callHandler('getDeviceInfo', null, function(info) { var data = JSON.parse(info); document.getElementById('device-info').innerText = '平台: ' + data.platform; }); }, 1000); </script> </body></html> HTML; // 4. 开始异步操作链 $scope->delay(1000) // 关键延时:等待Activity和WebView初始化完成 ->then(function ($s, $unused) use ($controller, $html) { return $controller->loadDataWithBaseURL($s, javaString("https://js2native.test"), javaString($html), null, null, javaString("https://js2native.test")); }) ->then(function ($s, $unused) { // 等待页面加载和JS中的setTimeout执行 return $s->delay(2000); }) ->then(function ($s, $unused) use ($controller) { return $controller->getTextContent($s, javaString("//*[@id='device-info']")); }) ->then(function ($s, $infoText) { global $console, $strings; $console->log(javaString("页面显示的设备信息:"), $infoText); $console->assertTrue($strings->contains($infoText, javaString("Android")), javaString("JS调用脚本验证失败")); $console->info(javaString("--- 示例 3.2: 成功 ---")); return $s->resolve(null); }) ->onComplete(function () use ($bridge) { $bridge->unregisterHandler(javaString("getDeviceInfo")); }) ->onError(function ($e) { global $console; $console->error(javaString("--- 示例 3.2: 失败 ---"), $e->stackTraceToString()); });
# ---------------------------------------------------- # 示例 3.2: JS调用脚本 (完整代码) # ---------------------------------------------------- # 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _console from m8test_java.com.m8test.script.GlobalVariables import _coroutines from m8test_java.com.m8test.script.GlobalVariables import _webView from m8test_java.com.m8test.script.GlobalVariables import _activity _console.info("\n--- 开始示例 3.2: JS调用脚本 ---") # 1. 基础设置 # 【已修正】: 使用 getScriptMain() scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda d: d.getScriptMain())) bridge = _webView.getBridge() controller = bridge.getController() _activity.start() # 2. 同步注册处理器 bridge.registerHandler("getDeviceInfo", lambda params: ( _console.log("JS调用了 getDeviceInfo, 参数:", str(params)), '{"platform": "Android"}' )[-1]) # 3. 准备HTML html = """ <html><body> <div id="device-info"></div> <script> setTimeout(function() { window.WebViewJavascriptBridge.callHandler('getDeviceInfo', null, function(info) { var data = JSON.parse(info); document.getElementById('device-info').innerText = '平台: ' + data.platform; }); }, 1000); </script> </body></html> """ # 4. 开始异步操作链 scope.delay(1000).then(lambda s, _: controller.loadDataWithBaseURL(s, "https://js2native.test", html, None, None, "https://js2native.test") ).then(lambda s, _: # 等待页面加载和JS中的setTimeout执行 s.delay(2000) ).then(lambda s, _: controller.getTextContent(s, "//*[@id='device-info']") ).then(lambda s, infoText: ( _console.log("页面显示的设备信息:", str(infoText)), _console.assertTrue("Android" in str(infoText), "JS调用脚本验证失败"), _console.info("--- 示例 3.2: 成功 ---"), s.resolve(None) )[-1]).onComplete(lambda: bridge.unregisterHandler("getDeviceInfo") ).onError(lambda e: _console.error("--- 示例 3.2: 失败 ---", e.stackTraceToString()) )
# encoding: utf-8 # ---------------------------------------------------- # 示例 3.2: JS调用脚本 (完整代码) # ---------------------------------------------------- $console.info("\n--- 开始示例 3.2: JS调用脚本 ---") # 1. 基础设置 scope = $coroutines.newScope { |it| it.setDispatcher { |d| d.getIO() } } bridge = $webView.getBridge() controller = bridge.getController() $activity.start() # 2. 同步注册处理器 bridge.registerHandler("getDeviceInfo") { |params| $console.log("JS调用了 getDeviceInfo, 参数:", params) '{"platform": "Android"}' } # 3. 准备HTML html = <<-HTML <html><body> <div id="device-info"></div> <script> setTimeout(function() { window.WebViewJavascriptBridge.callHandler('getDeviceInfo', null, function(info) { var data = JSON.parse(info); document.getElementById('device-info').innerText = '平台: ' + data.platform; }); }, 1000); </script> </body></html> HTML # 4. 开始异步操作链 scope.delay(1000). # 关键延时:等待Activity和WebView初始化完成 then { |s, _| controller.loadDataWithBaseURL(s, "https://js2native.test", html, nil, nil, "https://js2native.test") }. then { |s, _| # 等待页面加载和JS中的setTimeout执行 s.delay(2000) }. then { |s, _| controller.getTextContent(s, "//*[@id='device-info']") }. then { |s, info_text| $console.log("页面显示的设备信息:", info_text) $console.assertTrue(info_text.include?("Android"), "JS调用脚本验证失败") $console.info("--- 示例 3.2: 成功 ---") s.resolve(nil) }. onComplete { bridge.unregisterHandler("getDeviceInfo") }. onError { |e| $console.error("--- 示例 3.2: 失败 ---", e.to_s) }

直接执行JavaScript代码

import com.m8test.script.GlobalVariables.* // ---------------------------------------------------- // 示例 3.3: 直接执行JS (完整代码) // ---------------------------------------------------- _console.info("\n--- 开始示例 3.3: 直接执行JS ---") // 1. 基础设置 val scope = _coroutines.newScope { setDispatcher { it.getIO() } } val bridge = _webView.getBridge() val controller = bridge.getController() _activity.start() // 2. 准备HTML和JS脚本 val html = """<html><body><h1 id="title">旧标题</h1></body></html>""" val script = "document.getElementById('title').innerText = '新标题';" // 3. 开始异步操作链 scope.delay(1000) // 关键延时:等待Activity和WebView初始化完成 .then { s, _ -> controller.loadDataWithBaseURL(s, "https://eval.test", html, null, null, "https://eval.test") } .then { s, _ -> _console.log("页面加载指令已发出,等待渲染完成...") s.delay(1000) } .then { s, _ -> bridge.evaluateJsString(script, true, null) s.delay(500) // 等待JS执行完毕 } .then { s, _ -> controller.getTextContent(s, "//*[@id='title']") } .then { s, newTitle -> _console.log("执行JS后的标题:", newTitle) _console.assertTrue(newTitle == "新标题", "evaluateJsString 验证失败") _console.info("--- 示例 3.3: 成功 ---") s.resolve(null) } .onError { e -> _console.error("--- 示例 3.3: 失败 ---", e.stackTraceToString()) }
// ---------------------------------------------------- // 示例 3.3: 直接执行JS (完整代码) // ---------------------------------------------------- $console.info("\n--- 开始示例 3.3: 直接执行JS ---") // 1. 基础设置 def scope = $coroutines.newScope { it.setDispatcher { it.getIO() } } def bridge = $webView.getBridge() def controller = bridge.getController() $activity.start() // 2. 准备HTML和JS脚本 def html = """<html><body><h1 id="title">旧标题</h1></body></html>""" def script = "document.getElementById('title').innerText = '新标题';" // 3. 开始异步操作链 scope.delay(1000) // 关键延时:等待Activity和WebView初始化完成 .then { s, _ -> return controller.loadDataWithBaseURL(s, "https://eval.test", html, null, null, "https://eval.test") } .then { s, _ -> $console.log("页面加载指令已发出,等待渲染完成...") return s.delay(1000) } .then { s, _ -> bridge.evaluateJsString(script, true, null) return s.delay(500) // 等待JS执行完毕 } .then { s, _ -> return controller.getTextContent(s, "//*[@id='title']") } .then { s, newTitle -> $console.log("执行JS后的标题:", newTitle) $console.assertTrue(newTitle == "新标题", "evaluateJsString 验证失败") $console.info("--- 示例 3.3: 成功 ---") return s.resolve(null) } .onError { e -> $console.error("--- 示例 3.3: 失败 ---", e.stackTraceToString()) }
// ---------------------------------------------------- // 示例 3.3: 直接执行JS (完整代码) // ---------------------------------------------------- $console.info("\n--- 开始示例 3.3: 直接执行JS ---"); // 1. 基础设置 const scope = $coroutines.newScope(it => it.setDispatcher(it => it.getIO())); const bridge = $webView.getBridge(); const controller = bridge.getController(); $activity.start(); // 2. 准备HTML和JS脚本 const html = `<html><body><h1 id="title">旧标题</h1></body></html>`; const script = "document.getElementById('title').innerText = '新标题';"; // 3. 开始异步操作链 scope.delay(1000) // 关键延时:等待Activity和WebView初始化完成 .then((s, _) => { return controller.loadDataWithBaseURL(s, "https://eval.test", html, null, null, "https://eval.test"); }) .then((s, _) => { $console.log("页面加载指令已发出,等待渲染完成..."); return s.delay(1000); }) .then((s, _) => { bridge.evaluateJsString(script, true, null); return s.delay(500); // 等待JS执行完毕 }) .then((s, _) => { return controller.getTextContent(s, "//*[@id='title']"); }) .then((s, newTitle) => { $console.log("执行JS后的标题:", newTitle); $console.assertTrue(newTitle == "新标题", "evaluateJsString 验证失败"); $console.info("--- 示例 3.3: 成功 ---"); return s.resolve(null); }) .onError(e => $console.error("--- 示例 3.3: 失败 ---", e.stackTraceToString()));
-- ---------------------------------------------------- -- 示例 3.3: 直接执行JS (完整代码) -- ---------------------------------------------------- _console:info("\n--- 开始示例 3.3: 直接执行JS ---") -- 1. 基础设置 local scope = _coroutines:newScope(function(it) it:setDispatcher(function(it) return it:getIO() end) end) local bridge = _webView:getBridge() local controller = bridge:getController() _activity:start() -- 2. 准备HTML和JS脚本 local html = [[<html><body><h1 id="title">旧标题</h1></body></html>]] local script = "document.getElementById('title').innerText = '新标题';" -- 3. 开始异步操作链 scope:delay(1000) -- 关键延时:等待Activity和WebView初始化完成 :_then(function(s, _) return controller:loadDataWithBaseURL(s, "https://eval.test", html, nil, nil, "https://eval.test") end) :_then(function(s, _) _console:log("页面加载指令已发出,等待渲染完成...") return s:delay(1000) end) :_then(function(s, _) bridge:evaluateJsString(script, true, nil) return s:delay(500) -- 等待JS执行完毕 end) :_then(function(s, _) return controller:getTextContent(s, "//*[@id='title']") end) :_then(function(s, newTitle) _console:log("执行JS后的标题:", newTitle) _console:assertTrue(newTitle == "新标题", "evaluateJsString 验证失败") _console:info("--- 示例 3.3: 成功 ---") return s:resolve(nil) end) :onError(function(e) _console:error("--- 示例 3.3: 失败 ---", e:stackTraceToString()) end)
<?php /** @var m8test_java\com\m8test\script\core\api\console\Console $console */ global $console; /** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */ global $coroutines; /** @var m8test_java\com\m8test\script\core\api\ui\webview\WebView $webView */ global $webView; /** @var m8test_java\com\m8test\script\core\api\ui\Activity $activity */ global $activity; // ---------------------------------------------------- // 示例 3.3: 直接执行JS (完整代码) // ---------------------------------------------------- $console->info(javaString("\n--- 开始示例 3.3: 直接执行JS ---")); // 1. 基础设置 $scope = $coroutines->newScope(function ($it) { $it->setDispatcher(function ($dispatchers) { return $dispatchers->getScriptMain(); }); }); $bridge = $webView->getBridge(); $controller = $bridge->getController(); $activity->start(); // 2. 准备HTML和JS脚本 $html = "<html><body><h1 id=\"title\">旧标题</h1></body></html>"; $script = "document.getElementById('title').innerText = '新标题';"; // 3. 开始异步操作链 $scope->delay(1000) // 关键延时:等待Activity和WebView初始化完成 ->then(function ($s, $unused) use ($controller, $html) { return $controller->loadDataWithBaseURL($s, javaString("https://eval.test"), javaString($html), null, null, javaString("https://eval.test")); }) ->then(function ($s, $unused) { global $console; $console->log(javaString("页面加载指令已发出,等待渲染完成...")); return $s->delay(1000); }) ->then(function ($s, $unused) use ($bridge, $script) { $bridge->evaluateJsString(javaString($script), true, null); return $s->delay(500); // 等待JS执行完毕 }) ->then(function ($s, $unused) use ($controller) { return $controller->getTextContent($s, javaString("//*[@id='title']")); }) ->then(function ($s, $newTitle) { global $console; $console->log(javaString("执行JS后的标题:"), $newTitle); $console->assertTrue($newTitle == javaString("新标题"), javaString("evaluateJsString 验证失败")); $console->info(javaString("--- 示例 3.3: 成功 ---")); return $s->resolve(null); }) ->onError(function ($e) { global $console; $console->error(javaString("--- 示例 3.3: 失败 ---"), $e->stackTraceToString()); });
# ---------------------------------------------------- # 示例 3.3: 直接执行JS (完整代码) # ---------------------------------------------------- # 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _console from m8test_java.com.m8test.script.GlobalVariables import _coroutines from m8test_java.com.m8test.script.GlobalVariables import _webView from m8test_java.com.m8test.script.GlobalVariables import _activity _console.info("\n--- 开始示例 3.3: 直接执行JS ---") # 1. 基础设置 # 【已修正】: 使用 getScriptMain() scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda d: d.getScriptMain())) bridge = _webView.getBridge() controller = bridge.getController() _activity.start() # 2. 准备HTML和JS脚本 html = """<html><body><h1 id="title">旧标题</h1></body></html>""" script = "document.getElementById('title').innerText = '新标题';" # 3. 开始异步操作链 scope.delay(1000).then(lambda s, _: controller.loadDataWithBaseURL(s, "https://eval.test", html, None, None, "https://eval.test") ).then(lambda s, _: ( _console.log("页面加载指令已发出,等待渲染完成..."), s.delay(1000) )[-1]).then(lambda s, _: ( bridge.evaluateJsString(script, True, None), s.delay(500) # 等待JS执行完毕 )[-1]).then(lambda s, _: controller.getTextContent(s, "//*[@id='title']") ).then(lambda s, newTitle: ( _console.log("执行JS后的标题:", str(newTitle)), _console.assertTrue(newTitle == "新标题", "evaluateJsString 验证失败"), _console.info("--- 示例 3.3: 成功 ---"), s.resolve(None) )[-1]).onError(lambda e: _console.error("--- 示例 3.3: 失败 ---", e.stackTraceToString()) )
# encoding: utf-8 # ---------------------------------------------------- # 示例 3.3: 直接执行JS (完整代码) # ---------------------------------------------------- $console.info("\n--- 开始示例 3.3: 直接执行JS ---") # 1. 基础设置 scope = $coroutines.newScope { |it| it.setDispatcher { |d| d.getIO() } } bridge = $webView.getBridge() controller = bridge.getController() $activity.start() # 2. 准备HTML和JS脚本 html = %Q{<html><body><h1 id="title">旧标题</h1></body></html>} script = "document.getElementById('title').innerText = '新标题';" # 3. 开始异步操作链 scope.delay(1000). # 关键延时:等待Activity和WebView初始化完成 then { |s, _| controller.loadDataWithBaseURL(s, "https://eval.test", html, nil, nil, "https://eval.test") }. then { |s, _| $console.log("页面加载指令已发出,等待渲染完成...") s.delay(1000) }. then { |s, _| bridge.evaluateJsString(script, true, nil) s.delay(500) # 等待JS执行完毕 }. then { |s, _| controller.getTextContent(s, "//*[@id='title']") }. then { |s, new_title| $console.log("执行JS后的标题:", new_title) $console.assertTrue(new_title == "新标题", "evaluateJsString 验证失败") $console.info("--- 示例 3.3: 成功 ---") s.resolve(nil) }. onError { |e| $console.error("--- 示例 3.3: 失败 ---", e.to_s) }
09 December 2025