有没有办法在 .NET 6 MAUI 中创建 shell 应用程序和 web 视图之间的双向通信?

Posted

技术标签:

【中文标题】有没有办法在 .NET 6 MAUI 中创建 shell 应用程序和 web 视图之间的双向通信?【英文标题】:Is there a way to create bi-directional communication between a shell app and a webview in .NET 6 MAUI? 【发布时间】:2021-10-21 05:09:52 【问题描述】:

最近我的任务是在 .NET MAUI 中创建 shell 应用程序和网页之间的双向互操作桥。没有找到解决这个问题的任何方法,我想到了在 Xamarin.Forms 中创建它,因为 MAUI 是它的延续。

创建此应用后,我尝试使用 Microsoft 在 dotnet/maui github wiki 上的说明将其转换为 MAUI。

我现在遇到的主要问题是我一直在 androidWebViewRendererWebViewClientJava.Lang.Object 能够向 WebView 发送和接收 javascript

public class ExtendedWebViewRenderer : WebViewRenderer
    
        private const String JavascriptFunction = "function invokeCSharpAction(data)jsBridge.invokeAction(data);";

        public ExtendedWebViewRenderer(Context context) : base(context)
        
        

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        
            base.OnElementChanged(e);

            if (e.OldElement != null)
            
                Control.RemoveJavascriptInterface("jsBridge");
                ((ExtendedWebView)Element).Cleanup();
            
            if (e.NewElement != null)
            
                Control.SetWebViewClient(new JavascriptWebViewClient($"javascript: JavascriptFunction"));
                Control.AddJavascriptInterface(new JsBridge(this), "jsBridge");
            
        
    

public class JavascriptWebViewClient : WebViewClient
    
        private readonly String _javascript;

        public JavascriptWebViewClient(String javascript)
        
            _javascript = javascript;
        

        public override void OnPageFinished(WebView view, String url)
        
            base.OnPageFinished(view, url);
            view.EvaluateJavascript(_javascript, null);
        
    

public class JsBridge : Java.Lang.Object
    
        private readonly WeakReference<ExtendedWebViewRenderer> _extendedWebViewMainRenderer;

        public JsBridge(ExtendedWebViewRenderer extendedRenderer)
        
            _extendedWebViewMainRenderer = new WeakReference<ExtendedWebViewRenderer>(extendedRenderer);
        

        [JavascriptInterface]
        [Export("invokeAction")]
        public void InvokeAction(String data)
        
            if (_extendedWebViewMainRenderer != null && _extendedWebViewMainRenderer.TryGetTarget(out var extendedRenderer))
            
                ((ExtendedWebView)extendedRenderer.Element).InvokeAction(data);
            
        
    

这三个要么现在不可用,要么不会在 MAUI 中实现,因为很多平台相关的代码现在已经自动化了。这给我留下了一个问题,我似乎无法弄清楚如何更改我当前的代码以在 MAUI 中完成同样的事情。

鉴于目前 MAUI 还没有完全发布,我想知道这目前是不可能的,还是有一些解决方法可以使它成为可能。

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

MAUI 的默认 WebView 具有 EvalEvaluateJavaScriptAsync 函数以从 C# 调用 JavaScript 代码:

Eval 只是执行脚本 string 你以一种即发即弃的方式传递。 EvaluateJavaScriptAsync 需要等待,但还会返回一个 string,其中包含脚本返回的数据的字符串化结果。

如果您想使用回调/桥接方法自动接收来自 JavaScript 端的数据,而无需来自应用程序的 C# 端的任何输入,则必须扩展默认的每平台渲染器以添加该功能。好消息是,Customizing a WebView 上有一个关于如何为 Xamarin 表单执行此操作的官方教程,它几乎可以直接移植到 .NET MAUI - 您只需 change how renderers are registered。

【讨论】:

对,但现在的问题是这似乎只是一种方式,除非首先向 webview 触发 javascript。我还需要能够从 Webview 接收数据,而无需先向其触发 javascript,例如,网页上的文本字段中的一些文本将使用网页上的按钮发送到 shell 应用程序。使用上面的代码,当网页本身发生某个事件(例如单击按钮)时,它将调用 C# 代码。 @HallowedFlux 刚刚更新了答案,提供了有关如何通过回调/桥注册从 JavaScript 接收数据的更多信息。 在 Maui WebView 增强问题中执行 JS 的能力在这里:github.com/dotnet/maui/issues/4215

以上是关于有没有办法在 .NET 6 MAUI 中创建 shell 应用程序和 web 视图之间的双向通信?的主要内容,如果未能解决你的问题,请参考以下文章

(01).NET MAUI实战 建项目

在 .net 核心控制台应用程序中创建一个 websocket 服务器

如何在 numpy 中创建布尔数组

使用 kcadm.sh 在 Keycloak 中创建协议映射器

.NET MAUI 预览版 6 发布

如何在 .Net 6 中创建测试服务器? [复制]