UWP - 加入 Windows Runtime Component 到 JavaScript context

在 WebView 里面让 Javascript 与 App 交互已经是很平常的事情了,为什么要特别写这篇。 因为发现除了 window.external.notify 允许从网页送入消息到 App 之外,还可以加入自定义的 component 到网页里让 Javascript 使用。 这篇将介绍怎么实践。


根据 WebView class 的介绍,在 Windows 10 开始允许利用 AddWebAllowedobject method 去引用建立好的 Windows Runtime component 到 WebView 的 Javascript context 之中,让 Javascript 有能力存取 native 的 properties, methods, events。

那我们来看要做些什么才能完成这样的功能

1. 建立 Universal Windows Platform 与 Windows Runtime component ,再将 Component 的项目加入到 App 的参考之中;

2. 为 component 项目中的 class 加入 AllowForWeb 的 attribute;

Allow​For​Web​Attribute Class 允许让开发者公开 native 对象变成类似 global parameter 的内容放在 WebView 的 top-level。

由于声明 AllowForWeb 的类是受到保护的,所以需要是 sealed 的 class。 如下的程序:


[AllowForWeb]
public sealed class JavaScriptExternalObject
{
    /// 
    /// 提供给外部使用时收听的事件
    /// 
    public event EventHandler FromJavaScriptMessage;
        
    /// 
    /// 提供给 JavaScript 调用方法
    /// 
    public void onopenNativeShareDialog(string json)
    {
            FromJavaScriptMessage?.Invoke(null, json);
    }
}

3. 在 WebView 的 NavigationStarting 事件发生时为每个新进入的网页加入 JavaScriptExternalObject; 利用 AddWebAllowedobject 将 native Windows Runtime Component 声明的类加入到 Webview 之中,如下:


public sealed partial class MainPage : Page
{
    private JavaScriptExternalObject javascriptExternalObject;

    public MainPage()
    {
        javascriptExternalObject = new JavaScriptExternalObject();
        javascriptExternalObject.FromJavaScriptMessage += JavascriptExternalObject_FromJavaScriptMessage;
        this.InitializeComponent();
    }

    private void WebView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
    {
        // 定义公开的名称为: external
        // JavaScriptExternalObject: 为 Javascript 里面可以利用 external.{JavaScriptExternalObject 里面的内容}
        sender.AddWebAllowedobject("external", javascriptExternalObject);
    }

    private async void JavascriptExternalObject_FromJavaScriptMessage(object sender, string e)
    {
        // 接受来自 JavasScript 的消息
        await this.dispatcher.RunAsync(Windows.UI.Core.CoredispatcherPriority.normal, async () =>
        {
            var dialog = new MessageDialog(e);
            await dialog.ShowAsync();
        });
    }
}

[注意]

如果注册 external 的话,WebView 会自动覆写原本 external 的 methods,所以 window.external.notify 也就无法使用了 (ScriptyNotify event 不会被触发)。

需要自行在加入 notify method 到自定义的 JavaScriptExternalObject class 里面才能使用哦

4. WebView 载入 html 内容,并且测试内容

html 内文如下:




    
    JavaScriptInvokeNativeSample
    

<body>
    


XAML 内文如下:



执行结果:

详细的范例可参考 How to interoperate JS with native in WebView of Universal Windows Platform(UWP)。

[补充]

  1. 如果是自己开发或是受信任的网站,可以在 Package.appxmanifest 加入 ApplicationContentUriRules 的声明,让 Javasscript 可与 Windows RuntimeAPI 交互;
  2. 在 Win10 支持 WebView.Settings 可以设定 JavaScript 与 IndexedDB 是否启用;
  3. WebView 支持 CaptureSelectedContentToDataPackageAsync 把 WebView 内容分享给其他 app,变成 DataPackage。因为是异步的 method 要记得处理 deferral 去保护 DataRequested 事件能执行完毕;
  4. 可利用 CapturePreviewToStreamAsync 将现在 WebView 的内容变成一张图片
  5. 认 WebView 在 Desktop device family 是运行在 UI Thread,而其他 device family 则不是;可以设定 WebView.DefaultExecutionMode 让认的 UI thread 负责控制 WebView;

======

简单笔记一下有这样的用法,希望对大家在撰写与网页交互时也可以加入这样的弹性。

References:

  • Web​View Class
  • How to interoperate JS with native in WebView of Universal Windows Platform(UWP)
  • Using JavaScript frameworks from your C#/UWP application
  • App Lifecycle - Keep Apps Alive with Background Tasks and Extended Execution
  • Create and consume an app service
  • Create and register an out-of-process background task
  • Hacking UWP WebView Part2


原文:大专栏  UWP - 加入 Windows Runtime Component 到 JavaScript context



相关文章

Windows2012R2备用域控搭建 前置操作 域控主域控的主dns:自...
主域控角色迁移和夺取(转载) 转载自:http://yupeizhi.blo...
Windows2012R2 NTP时间同步 Windows2012R2里没有了internet时...
Windows注册表操作基础代码 Windows下对注册表进行操作使用的...
黑客常用WinAPI函数整理之前的博客写了很多关于Windows编程的...
一个简单的Windows Socket可复用框架说起网络编程,无非是建...