在 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;
AllowForWebAttribute 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>