首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Flutter Webview与Javascript的双向通信

Flutter Webview与Javascript的双向通信
EN

Stack Overflow用户
提问于 2018-12-09 13:28:15
回答 6查看 35.2K关注 0票数 29

我有一个html文件,我正在使用flutter_webview_plugin在Flutter webview中加载它。我正在使用evalJavascript来调用javascript代码中的函数,即flutter(dart)->js。然而,我也需要一些方法来将一些东西传回flutter(dart)层,即js->flutter(dart)。

我已经尝试使用- webkit.messageHandlers.native - window.native来支持这两个平台(Android,iOS),检查它们在JS中是否可用。但是,这些都是未定义的。使用以下代码在JS中获取本机处理程序的实例。

代码语言:javascript
运行
复制
typeof webkit !== 'undefined' ? webkit.messageHandlers.native : 
window.native;

即使我使用它获取实例并发布消息,也不确定如何在flutter(dart)层中处理它。我可能需要使用平台通道。我不确定我是否走对了方向。

有什么方法可以让我做到这一点吗?我已经评估了interactive_webview插件。它在Android上运行得很好。但是,它有迅速的版本问题,不想继续下去。

任何帮助都将不胜感激。

EN

回答 6

Stack Overflow用户

发布于 2019-03-12 13:54:22

这是一个从Javascript代码到flutter的通信示例。

在Flutter中构建WebView,如下所示:

代码语言:javascript
运行
复制
WebView(
              initialUrl: url,
              javascriptMode: JavascriptMode.unrestricted,
              javascriptChannels: Set.from([
                JavascriptChannel(
                    name: 'Print',
                    onMessageReceived: (JavascriptMessage message) {
                      //This is where you receive message from 
                      //javascript code and handle in Flutter/Dart
                      //like here, the message is just being printed
                      //in Run/LogCat window of android studio
                      print(message.message);
                    })
              ]),
              onWebViewCreated: (WebViewController w) {
                webViewController = w;
              },
            )

在你的HTMLfile中:

代码语言:javascript
运行
复制
<script type='text/javascript'>
    Print.postMessage('Hello World being called from Javascript code');
</script>

当您运行这段代码时,您应该能够在android studio的LogCat/Run窗口中看到日志"Hello World in from Javascript code“。

票数 43
EN

Stack Overflow用户

发布于 2019-11-28 05:18:54

您可以尝试我的插件编辑( flutter_inappbrowser :它已重命名为flutter_inappwebview),并使用addJavaScriptHandler({@required String handlerName, @required JavaScriptHandlerCallback callback})方法(请参阅更多here)。

下面给出了一个示例。在颤动方面:

代码语言:javascript
运行
复制
...

child: InAppWebView(
  initialFile: "assets/index.html",
  initialHeaders: {},
  initialOptions: InAppWebViewWidgetOptions(
    inAppWebViewOptions: InAppWebViewOptions(
        debuggingEnabled: true,
    )
  ),
  onWebViewCreated: (InAppWebViewController controller) {
    webView = controller;

    controller.addJavaScriptHandler(handlerName: "mySum", callback: (args) {
      // Here you receive all the arguments from the JavaScript side 
      // that is a List<dynamic>
      print("From the JavaScript side:");
      print(args);
      return args.reduce((curr, next) => curr + next);
    });
  },
  onLoadStart: (InAppWebViewController controller, String url) {

  },
  onLoadStop: (InAppWebViewController controller, String url) {

  },
  onConsoleMessage: (InAppWebViewController controller, ConsoleMessage consoleMessage) {
    print("console message: ${consoleMessage.message}");
  },
),

...

在assets端(例如,JavaScript文件夹中的本地文件assets/index.html ):

代码语言:javascript
运行
复制
<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Flutter InAppBrowser</title>

        ...

    </head>
    <body>

        ...

        <script>
           // In order to call window.flutter_inappwebview.callHandler(handlerName <String>, ...args) 
           // properly, you need to wait and listen the JavaScript event flutterInAppWebViewPlatformReady. 
           // This event will be dispatched as soon as the platform (Android or iOS) is ready to handle the callHandler method. 
           window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
             // call flutter handler with name 'mySum' and pass one or more arguments
             window.flutter_inappwebview.callHandler('mySum', 12, 2, 50).then(function(result) {
               // get result from Flutter side. It will be the number 64.
               console.log(result);
             });
           });
        </script>
    </body>
</html>

在Android Studio日志中,您将获得:

代码语言:javascript
运行
复制
I/flutter (20436): From JavaScript side:
I/flutter (20436): [12, 2, 50]
I/flutter (20436): console message: 64
票数 15
EN

Stack Overflow用户

发布于 2020-10-17 22:48:59

我想告诉你如何从flutter WebView向JS发送消息:

  1. 在JS代码中,您需要绑定需要触发到window

的函数

代码语言:javascript
运行
复制
const function = () => alert('hello from JS');
window.function = function;

在WebView小部件实现的代码中,需要像下面这样声明

  1. 的WebView方法

代码语言:javascript
运行
复制
WebView(
  onWebViewCreated: (WebViewController controller) {},
  initialUrl: 'https://url.com',
  javascriptMode: JavascriptMode.unrestricted,
)

类小部件声明var _webViewController;中的

代码语言:javascript
运行
复制
class App extends State<MyApp> {
  final _webViewController;
}

onWebViewCreated中的

  1. 将此代码写入

代码语言:javascript
运行
复制
onWebViewCreated: (WebViewController controller) {
    _webViewController = controller;
},

然后,您可以像这样运行代码:

代码语言:javascript
运行
复制
class App extends StatelessWidget {
  var _webViewController;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        body: WebView(
          onWebViewCreated: (WebViewController controller) {
            _webViewController = controller;
          },
          initialUrl: 'https://url.com',
          javascriptMode: JavascriptMode.unrestricted,
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            // When you click at this button youll run js code and youll see alert
            _webViewController
                .evaluateJavascript('window.function ()');
          },
          child: Icon(Icons.add),
          backgroundColor: Colors.green,
        ),
      ),
    );
  }
}

但是,如果我们想把这个_webViewController实例分享给像drawer这样的小部件,该怎么办呢?

在本例中,我决定实现Singleton pattern并将_webViewController实例存储在其中。

所以

单例类

代码语言:javascript
运行
复制
class Singleton {
  WebViewController webViewController;

  static final Singleton _singleton = new Singleton._internal();

  static Singleton get instance => _singleton;

  factory Singleton(WebViewController webViewController) {
    _singleton.webViewController = webViewController;
    return _singleton;
  }

  Singleton._internal();
}

然后

代码语言:javascript
运行
复制
onWebViewCreated: (WebViewController controller) {
  var singleton = new Singleton(controller);
},

最后,在我们的抽屉小部件中(在这里你可以使用任何你想要的小部件)

代码语言:javascript
运行
复制
class EndDrawer extends StatelessWidget {
  final singleton = Singleton.instance;

  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          SizedBox(
              width: 200,
              child: FlatButton(
                onPressed: () {
                  singleton.webViewController.evaluateJavascript('window.function()');
                  Navigator.pop(context); // exit drawer
                },
                child: Row(
                  children: <Widget>[
                    Icon(
                      Icons.exit_to_app,
                      color: Colors.redAccent,
                    ),
                    SizedBox(
                      width: 30,
                    ),
                    Text(
                      'Exit',
                      style: TextStyle(color: Colors.blueAccent, fontSize: 20),
                    ),
                  ],
                ),
              )),
        ],
      ),
    );
  }
}

如果你想从JS代码接收消息到你的flutter应用,你需要:

在您的js代码中使用

代码语言:javascript
运行
复制
window.CHANNEL_NAME.postMessage('Hello from JS');

你的flutter代码中的

当您运行JavascriptChannel(名称:'CHANNEL_NAME',...)

flutter绑定到你的窗口,用你在构造函数中写的名字WebView新的MessageChannel (在这个例子中是CHANNEL_NAME)

因此,当我们呼叫window.CHANNEL_NAME.postMessage('Hello from JS');时,会收到一条我们发送给的消息

代码语言:javascript
运行
复制
WebView(
   javascriptChannels: [
     JavascriptChannel(name: 'CHANNEL_NAME', onMessageReceived: (message) {
       print(message.message);
       })
   ].toSet(),
  initialUrl: 'https://url.com',
)

所以我们到了这里。

我是flutter代码的新手

因此,如果你对此有更好的体验,你可以写评论来帮助其他人!

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53689662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档