You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter WebView触发JS函数异常:插件3转4后无法回调网页

WebView 4.x 向网页传递消息失败问题解决

我正尝试将WebView插件从3版本升级至4版本,但在向网页传递消息时遇到问题。以下是用于触发网页中receivePhoto()函数的_pickfile()函数代码——终端能打印出生成的jsCode,但始终无法触发网页的receivePhoto():

void _pickfile() async {
  final pickedFile = await ImagePicker().pickImage(source: ImageSource.camera);
  if (pickedFile != null) {
    final bytes = await pickedFile.readAsBytes();
    final base64 = base64Encode(bytes);
    final jsCode = "receivePhoto('$base64');";
    await WebViewController().runJavaScript(jsCode);
    print(jsCode);//this print works
  } else {
    // User canceled the picker
  }
}

核心页面代码如下:

class WebViewApp extends StatefulWidget {
  const WebViewApp({Key? key}) : super(key: key);
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}

class _WebViewAppState extends State<WebViewApp> {
  WebViewController controller = WebViewController()
    ..enableZoom(false)
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..addJavaScriptChannel('FileInputChannel', onMessageReceived: (message) async {
      if (message.message == 'pickFile') {
        _pickfile();
      }
    })
    ..loadRequest(
      Uri.parse("https://youtube.com"),
    );

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: WebViewWidget(controller: controller),
      ),
    );
  }
}

问题原因

_pickfile()中调用WebViewController().runJavaScript(jsCode)时,创建了一个全新的WebViewController实例,这个实例和当前页面显示的WebView没有任何关联,所以执行的JS代码不会作用在目标网页上。

修复方案

直接使用State类中已初始化的controller成员变量来执行JS代码,修改后的_pickfile()函数如下:

void _pickfile() async {
  final pickedFile = await ImagePicker().pickImage(source: ImageSource.camera);
  if (pickedFile != null) {
    final bytes = await pickedFile.readAsBytes();
    final base64 = base64Encode(bytes);
    // 使用类成员变量controller,而非新建实例
    final jsCode = "receivePhoto('$base64');";
    await controller.runJavaScript(jsCode);
    print(jsCode);
  } else {
    // User canceled the picker
  }
}

额外注意事项

  1. 确保网页中的receivePhoto函数是全局可访问的,可以在网页控制台手动执行receivePhoto('test')验证函数是否存在
  2. 由于base64字符串可能包含单引号等特殊字符,直接拼接会导致JS语法错误,建议使用jsonEncode做转义处理:
    import 'dart:convert';
    
    // ...
    final jsCode = "receivePhoto(${jsonEncode(base64)});";
    

内容的提问来源于stack exchange,提问作者daphneyong11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 17:17:24