Last updated:
0 purchases
flutter webview kit
flutter_webview_kit #
[toc]
# app
flutter create tsbaseuidemo
# package
flutter create --template=package flutter_baseui_kit
flutter create --template=package tsdemo_baseui
copied to clipboard
一、JS #
二、JS注入方法 #
可实现在原有网页上增加按钮,点击按钮后执行JS代码
// 使用方法1: 在网页上添加按钮
controller.injectedJs()
// 使用方法2: 在原生上添加按钮
AddJSChannel_InjectedJS.testJSInjectedButton
AddJSChannel_InjectedJS.testJSRunButton()
copied to clipboard
方法1的示例:
Future<bool> injectedJs_demo() async {
String addPosition = 'top';
String execJSMethod = "testInjectedMethod_showJsonWithCallbackMethod";
Map<String, dynamic> execJSParams = {
// "callbackMethod": "alert",
"callbackMethod": "h5CallBridgeAction_showAppToast",
"message": "这是测试运行注入的js",
"dialogSubjectId": "1234567890",
"dialogType": "user",
};
return injectedJs(
execJSMethod: execJSMethod,
execJSParams: execJSParams,
execJSCallBackMapGetHandle: () {
var sendMessage = {
"h5Title": "这是h5内部返回的标题1",
"h5Message": "这是h5内部返回的描述信息2",
"message": "这是h5内部返回的描述信息message3",
};
return sendMessage;
},
injectedUIPosition: addPosition,
);
}
copied to clipboard
方法2的示例:
Container(
color: Colors.amber,
height: 2 * 40 + 10,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AddJSChannel_InjectedJS.testJSInjectedButton(
execJSMethod: execJSMethod,
webViewControllerGetBlock: () => _controller,
),
AddJSChannel_InjectedJS.testJSRunButton(
execJSMethod: execJSMethod,
execJSParams: execJSParams,
hasInjectedJS: hasInjectedJS,
webViewControllerGetBlock: () => _controller,
),
],
),
)
copied to clipboard
三、原理 #
1、注入点击按钮 #
1、创建要注入的元素/区域
String injectedUIHtml = """
// 创建一个新的按钮元素
var newButton = document.createElement("button");
// 设置按钮的样式
newButton.style.height = '200px';
newButton.style.width = '320px'; // 可以根据需要设置宽度
newButton.style.backgroundColor = '#4CAF50'; // 设置背景颜色
newButton.style.color = 'white'; // 设置文字颜色
newButton.style.border = 'none'; // 去除边框
newButton.style.cursor = 'pointer'; // 鼠标悬停时显示指针
// 设置按钮的文本
newButton.textContent = '点击我';
""";
copied to clipboard
设置按钮文本和点击事件
详见:下文【2、注入按钮要执行的js方法】中的【将注入的事件绑定到注入的按钮的点击事件上】
copied to clipboard
2、注入位置 top(默认) \ bottom \ overlay
injectedUIHtml += """
if (`\${myContentPosition}` == 'bottom') {
// 将按钮添加到body中,可以根据需要添加到其他位置
document.body.appendChild(newButton);
} else if (`\${myContentPosition}` == 'overlay') {
newButton.style.position = 'fixed'; // 固定位置,不随页面滚动
newButton.style.top = '0'; // 定位到页面顶部
newButton.style.left = '0'; // 定位到页面左侧
newButton.style.zIndex = '1000'; // 确保按钮在页面最上层
newButton.innerHTML = '<div style="padding: 20px; text-align: center;">点击我啊</div>';
document.body.insertAdjacentElement('afterbegin', newButton);
} else {
// 将按钮添加到body的第一个子元素,使其成为页面内容的顶部
document.body.insertBefore(newButton, document.body.firstChild);
}
""";
copied to clipboard
3、注入时机 onload / now
injectedUIHtml += """
if (injectedTime == 'onload') {
injectedUIHtml = """
window.addEventListener('load', function() {
$injectedUIHtml
});
""";
}
""";
return runJavaScript(injectedUIHtml);
copied to clipboard
如此,页面上就有有一个注入进去的按钮。
2、注入按钮要执行的js方法 #
1、注入按钮要执行的js方法及让js调用app方法的核心如下:
"""
window[`\${injectedJSMethod}`] = function(json) {
console.log(`正在执行:\${injectedJSMethod}`)
......xxx......
var funName = callbackMethod;
var sendMessage = sendMessageString;
try {
eval(funName).postMessage(sendMessage);
} catch (err) {
var evalErrorMessage = `【执行错误如下】\n方法:\${funName} \n原因:\${err}`;
console.log(evalErrorMessage);
alert(evalErrorMessage);
}
};
""";
copied to clipboard
完整如下:
Future<bool> _injectedJavaScript({
required String jsMethod,
Map<String, dynamic> Function()? execJSCallBackMapGetHandle,
}) async {
String? execJSCallBackJson;
if (execJSCallBackMapGetHandle != null) {
Map<String, dynamic> execJSCallBackMap = execJSCallBackMapGetHandle();
execJSCallBackJson = json.encode(execJSCallBackMap);
}
String addJavaScript = """
// 测试方法带回调
// 方法一:
// window.testInjectedMethod_showJsonWithCallbackMethod = function(json) {
// 方法二:使用变量。📢:注意js中使用 外部变量 和 使用内部变量 的写法区别
// var injectedJSMethod = "testInjectedMethod_showJsonWithCallbackMethod"
var injectedJSMethod = `$jsMethod`;
window[`\${injectedJSMethod}`] = function(json) {
console.log(`正在执行:\${injectedJSMethod}`)
var arguments = JSON.parse(json);
var callbackMethod = arguments['callbackMethod'];
if (callbackMethod === undefined || callbackMethod === null) {
var errorMessage = "缺少 callbackMethod 参数";
alert(errorMessage);
return;
}
delete arguments.callbackMethod; // 删除键为 'callbackMethod' 的属性
var execMessage = `正在执行app调用h5,并返回回调:`
execMessage += `\n执行js方法:\${injectedJSMethod}`
execMessage += `\n执行js参数:\${JSON.stringify(arguments)}`
execMessage += `\n回调方法:\${callbackMethod}`
var sendMessageString = `$execJSCallBackJson`;
if (sendMessageString === undefined || sendMessageString === null) {
sendMessageString = "";
}
execMessage += `\n回调值:\${sendMessageString}`
console.log(execMessage)
alert(execMessage);
var funName = callbackMethod;
var sendMessage = sendMessageString;
try {
eval(funName).postMessage(sendMessage);
} catch (err) {
var evalErrorMessage = `【执行错误如下】\n方法:\${funName} \n原因:\${err}`;
console.log(evalErrorMessage);
alert(evalErrorMessage);
}
};
""";
await runJavaScript(addJavaScript);
return true;
}
copied to clipboard
3、将注入的事件绑定到注入的按钮的点击事件上,设置按钮文本和点击事件 #
injectedUIHtml += """
var jsMethod2 = `$execJSMethod`
newButton.textContent = `点击我\n执行\${jsMethod2}`;
// 添加点击事件处理器
newButton.onclick = function() {
// 原始代码
// window.testInjectedMethod_showJsonWithCallbackMethod(JSON.stringify({
// "callbackMethod": "h5CallBridgeAction_showAppToast",
// "message": "这是测试运行注入的js",
// }));
// 外部变量代码
var jsMethod = `$execJSMethod`
var sendMessageString = `$execJSJsonParams`; // 外部的map无法传到内部,需要转为string
// alert(`按钮被点击了!\${sendMessageString}`);
window[`\${jsMethod}`](sendMessageString);
};
""";
copied to clipboard
End #
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.