如何在 Windows 10 UWP 上使用 ms-appdata Javascript notify()
How to Javascript notify() with ms-appdata on Windows 10 UWP
由于文件写入安全问题,我们已尝试将我们的应用程序从使用 ms-appx-web: 切换到使用 ms-appdata:。但它立即失败,因为我们依赖于 window.external.notify() ,它与 ms-appx-web: 一起工作正常,但似乎与 ms-appdata: 无操作。作为测试,我们将以下 html 加载到 WebView 对象中:
<html>
<head>
<script>
function demofunc( str ) {
document.getElementById("demo").innerHTML += str;
window.external.notify( str );
}
</script>
</head>
<body onLoad="demofunc('demofunc()');">
demo <body>
<div id="demo"></div>
</body>
</html>
它应该产生这样的结果:
demo <body>
demofunc()
但是,不会产生任何类型的弹出消息。为什么?很明显,正在调用 demofunc() 方法以在演示 div 中添加第二行输出,但 window.external.notify() 不会生成弹出消息。是否有关于 notify() 和 ms-appdata:?
的特殊规则
更新 - 问题 类似并且适用于 ms-appx-web: 但不适用于 ms-appdata:。该问题捕获 ScriptNotify(),然后使用 Windows.UI.Popups.MessageDialog 弹出一个对话框。使用 ms-appx-web:调用 ScriptNotify() 但使用 ms-appdata:不调用 ScriptNotify()。那是我们的问题,没有出现弹出窗口。
But it immediately fails because we rely on window.external.notify() which works fine with ms-appx-web: but seems to behave as a no-op with ms-appdata:.
对于您的场景,请使用方案 ms-local-stream:///
,而不是 ms-appdata:///
。我已经测试了 ms-local-stream:///
方案,它运行良好。
要使用 NavigateToLocalStreamUri
方法,您必须传入一个 IUriToStreamResolver 实现,它将 URI 模式转换为内容流。请参考以下代码。
StreamUriWinRTResolver
public sealed class StreamUriWinRTResolver : IUriToStreamResolver
{
/// <summary>
/// The entry point for resolving a Uri to a stream.
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri)
{
if (uri == null)
{
throw new Exception();
}
string path = uri.AbsolutePath;
// Because of the signature of this method, it can't use await, so we
// call into a separate helper method that can use the C# await pattern.
return getContent(path).AsAsyncOperation();
}
/// <summary>
/// Helper that maps the path to package content and resolves the Uri
/// Uses the C# await pattern to coordinate async operations
/// </summary>
private async Task<IInputStream> getContent(string path)
{
// We use a package folder as the source, but the same principle should apply
// when supplying content from other locations
try
{
Uri localUri = new Uri("ms-appdata:///local" + path);
StorageFile f = await StorageFile.GetFileFromApplicationUriAsync(localUri);
IRandomAccessStream stream = await f.OpenAsync(FileAccessMode.Read);
return stream.GetInputStreamAt(0);
}
catch (Exception) { throw new Exception("Invalid path"); }
}
}
主页
public MainPage()
{
this.InitializeComponent();
MyWebView.ScriptNotify += MyWebView_ScriptNotify;
Uri url = MyWebView.BuildLocalStreamUri("MyTag", "/Test/HomePage.html");
StreamUriWinRTResolver myResolver = new StreamUriWinRTResolver();
MyWebView.NavigateToLocalStreamUri(url, myResolver);
}
我已经将 code sample 上传到 github。请检查。
由于文件写入安全问题,我们已尝试将我们的应用程序从使用 ms-appx-web: 切换到使用 ms-appdata:。但它立即失败,因为我们依赖于 window.external.notify() ,它与 ms-appx-web: 一起工作正常,但似乎与 ms-appdata: 无操作。作为测试,我们将以下 html 加载到 WebView 对象中:
<html>
<head>
<script>
function demofunc( str ) {
document.getElementById("demo").innerHTML += str;
window.external.notify( str );
}
</script>
</head>
<body onLoad="demofunc('demofunc()');">
demo <body>
<div id="demo"></div>
</body>
</html>
它应该产生这样的结果:
demo <body>
demofunc()
但是,不会产生任何类型的弹出消息。为什么?很明显,正在调用 demofunc() 方法以在演示 div 中添加第二行输出,但 window.external.notify() 不会生成弹出消息。是否有关于 notify() 和 ms-appdata:?
的特殊规则更新 - 问题
But it immediately fails because we rely on window.external.notify() which works fine with ms-appx-web: but seems to behave as a no-op with ms-appdata:.
对于您的场景,请使用方案 ms-local-stream:///
,而不是 ms-appdata:///
。我已经测试了 ms-local-stream:///
方案,它运行良好。
要使用 NavigateToLocalStreamUri
方法,您必须传入一个 IUriToStreamResolver 实现,它将 URI 模式转换为内容流。请参考以下代码。
StreamUriWinRTResolver
public sealed class StreamUriWinRTResolver : IUriToStreamResolver
{
/// <summary>
/// The entry point for resolving a Uri to a stream.
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri)
{
if (uri == null)
{
throw new Exception();
}
string path = uri.AbsolutePath;
// Because of the signature of this method, it can't use await, so we
// call into a separate helper method that can use the C# await pattern.
return getContent(path).AsAsyncOperation();
}
/// <summary>
/// Helper that maps the path to package content and resolves the Uri
/// Uses the C# await pattern to coordinate async operations
/// </summary>
private async Task<IInputStream> getContent(string path)
{
// We use a package folder as the source, but the same principle should apply
// when supplying content from other locations
try
{
Uri localUri = new Uri("ms-appdata:///local" + path);
StorageFile f = await StorageFile.GetFileFromApplicationUriAsync(localUri);
IRandomAccessStream stream = await f.OpenAsync(FileAccessMode.Read);
return stream.GetInputStreamAt(0);
}
catch (Exception) { throw new Exception("Invalid path"); }
}
}
主页
public MainPage()
{
this.InitializeComponent();
MyWebView.ScriptNotify += MyWebView_ScriptNotify;
Uri url = MyWebView.BuildLocalStreamUri("MyTag", "/Test/HomePage.html");
StreamUriWinRTResolver myResolver = new StreamUriWinRTResolver();
MyWebView.NavigateToLocalStreamUri(url, myResolver);
}
我已经将 code sample 上传到 github。请检查。