如何在运行 Flutter Web 应用程序的本地和本地 webview 之间进行通信?

Posted

技术标签:

【中文标题】如何在运行 Flutter Web 应用程序的本地和本地 webview 之间进行通信?【英文标题】:How to communicate between native and native web view running a flutter's web app? 【发布时间】:2020-07-03 15:13:52 【问题描述】:

android 允许指定一个 javascript 接口作为 webview 和 Android 代码之间的桥梁。同样,ios 提供了 UiWebView stringByEvaluatingJavaScriptFromString 方法,允许与底层 webview 进行通信。

但问题是,一旦我们构建了 Flutter Web 应用程序并说我们将其作为 Web 视图的一部分包含在 android 中,那么每当需要进行通信时,我们都应该在两个 android 中编写一些代码侧和javascript侧手动。

由于编辑从 Flutter Web 应用构建生成的 javascript 代码是不切实际的,我们需要一种方法在 Flutter 端建立一个通信通道,该通道将使用上述相同类型的 javascript 桥接器与本机端通信。这将类似于直接在原生端使用 Flutter 应用时的方法通道。

那么我们如何从 Flutter 内部注入或添加我们的自定义 javascript 代码,以便在编译 js 文件时添加它?

【问题讨论】:

你见过this吗? This?还是this? @tomerpacific 那些文章是关于在 Flutter 应用程序本身中嵌入 Web 视图的。我问的是在运行颤振应用程序的原生 Android 中使用网络视图。 为什么要一个 android 应用程序在 webview 中运行 Flutter 应用程序?这似乎是一个相当复杂的场景。 【参考方案1】:

你可以在android端创建一个webmessage channel(iOS有一个等效的)。

这里有怎么做的说明:

How Do You Use WebMessagePort As An Alternative to addJavascriptInterface()?

javascript 端的简要设置如下所示 - 您需要在 dart html 中实现它:

const channel = new MessageChannel();
var nativeJsPortOne = channel.port1;
var nativeJsPortTwo = channel.port2;
window.addEventListener('message', function(event) 
    if (event.data != 'capturePort') 
        nativeJsPortOne.postMessage(event.data)
     else if (event.data == 'capturePort') 
        /* The following three lines form Android class 'WebViewCallBackDemo' capture the port and assign it to nativeJsPortTwo
        var destPort = arrayOf(nativeToJsPorts[1])
        nativeToJsPorts[0].setWebMessageCallback(nativeToJs!!)
        WebViewCompat.postWebMessage(webView, WebMessageCompat("capturePort", destPort), Uri.EMPTY) */
        if (event.ports[0] != null) 
            nativeJsPortTwo = event.ports[0]
        
    
, false);

nativeJsPortOne.addEventListener('message', function(event) 
    alert(event.data);
, false);

nativeJsPortTwo.addEventListener('message', function(event) 
    alert(event.data);
, false);
nativeJsPortOne.start();
nativeJsPortTwo.start();

在 Flutter Web 的窗口中使用事件监听器进行监听的类似解决方案如下:

    window.onMessage.listen((onData) 
  print(onData.toString());

  MessageEvent messageEvent = onData;

  for (Property property in properties) 
    if (messageEvent.data["id"] == property.id) 

          );
     else if (messageEvent.data["northEastLng"] != null) 
      print(messageEvent.data["northEastLat"]);

      if (double.parse(messageEvent.data["northEastLat"]) == bounds.northEast.lat && double.parse(messageEvent.data["northEastLng"]) == bounds.northEast.lng)
        return;
      

      LatLng southWest = new LatLng(double.parse(messageEvent.data["southWestLat"]), double.parse(messageEvent.data["southWestLng"]));
      LatLng northEast = new LatLng(double.parse(messageEvent.data["northEastLat"]), double.parse(messageEvent.data["northEastLng"]));
      LatLngBounds incomingBounds = new LatLngBounds(southWest, northEast);
      if (incomingBounds == bounds) 
        return;
      
      bounds = incomingBounds;
      _propertyListPresenter.filterBounds(bounds);
    
  
);

【讨论】:

以上是关于如何在运行 Flutter Web 应用程序的本地和本地 webview 之间进行通信?的主要内容,如果未能解决你的问题,请参考以下文章

在本地管理 Flutter 应用和 Flutter Web 数据

相同的 Flutter Web 构建使用 `dhttp` 在本地运行,但使用 `firebase serve` 或 `firebase deploy` 失败

如何在浏览器本地存储 Flutter Web 应用程序中保存对象列表

如何分别在android和ios上本地运行flutter应用程序?

如何使用 Flutter for Web 从本地文件中读取内容?

如何更改 Flutter Web 应用的默认 Web 服务器 ip(127.0.0.1)