使用范围存储将文件加载到 webView
Load file into webView with scoped storage
我通过自定义 webview 在我的应用程序中显示 pdf 文件和图像,它显示了一个位于我的应用程序资产文件夹中的 html 小站点。这个“主页”通过获取参数获取要显示的文件。要显示的文件位于我的私人应用程序文档文件夹中。
在我必须将目标 API 级别 30 或更高级别(强制使用范围存储)之前,这工作得很好。现在“主页”无法访问私人文档文件夹中的文件(访问冲突)。
我想知道是否有办法仍然使用这种方法,通过启用了范围存储的 webview 在您的应用程序中显示 pdf 文件和图像。
以下是其当前实施方式的详细信息:
在自定义 webview 的 android 渲染器的 OnElementChanged 方法中(使用 Uri 属性 扩展 Xamarin.Forms.WebView)我设置了 Android webView( control),然后加载uri到图片首页或pdf.js webviewer,在uri中获取参数中的文件(图片或pdf):
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var customWebView = Element as CustomWebView;
Control.Settings.AllowUniversalAccessFromFileURLs = true;
Control.Settings.SetSupportZoom(true);
Control.Settings.BuiltInZoomControls = true;
Control.Settings.DisplayZoomControls = true;
int width = MainApplication.intWidth;
string PathCopy = customWebView.Uri;
customWebView.Uri = customWebView.Uri.Replace(" ", "%20");
string Extension = Path.GetExtension(WebUtility.UrlEncode(customWebView.Uri)).ToUpper();
switch (Extension)
{
case ".PDF": Control.LoadUrl(string.Format("file:///android_asset/pdfjs/web/viewer.html?file={0}", WebUtility.UrlEncode(customWebView.Uri))); break;
default: Control.LoadUrl(string.Format("file:///android_asset/ImageHomepage/ImageHomepage.html?pfad={0}&width={1}", customWebView.Uri, width)); break;
}
}
}
对于 pdf 文件,我使用 pdf.js(如本例所示:https://github.com/xamarin/docs-archive/tree/master/Recipes/xamarin-forms/Controls/display-pdf),对于图像,我使用 html 这个小网站:
<head>
<script>
function getURLParameter(name)
{
var value = decodeURIComponent((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, ""])[1]);
return (value !== 'null') ? value : false;
}
</script>
</head>
<body>
<script language = "Javascript" type="text/javascript">
<!--
var param = getURLParameter('pfad');
var width = getURLParameter('width');
document.write('<img src="');document.write(param); document.write('" width="'); document.write(width); document.write('" style="width:100%" >');
//-->
</script>
</body>
要显示的文件是从我的网络服务下载并存储在我的“PrivateDocumentsFolder”中,声明如下:
public static string PrivateFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
public static string PrivateDocumentsFolder = Path.Combine(PrivateFolder, "Dokumente");
所以文件存储在:/data/user/0/myPackageName/files/Dokumente,这是我在访问 [=38] 的 FilesDir 属性 时也得到的私人文件夹=]上下文对象。
将 requestLegacyExternalStorage 设置为 true 的目标 API 29 使用此方法。使用 Xamarin.Essentials Launcher 打开文件可以启用分区存储,但我想继续在我的应用程序中而不是在外部应用程序中显示文件。
如何在 API 级别 >29 并启用分区存储的情况下使用此方法?
如果我理解正确,使用 Environment.SpecialFolder.MyDocuments 应该是正确的方法,因为它在我的应用程序私有范围内,从我的应用程序内部访问这些文件应该没有问题。
首先,您授予读写存储权限了吗?该文件位于应用程序的私人文件夹中。一般情况下,app可以直接访问。
此外,如果用户更新到API 30,您可以使用preserveLegacyExternalStorage=true
和android:requestLegacyExternalStorage=true
来保留和使用旧的存储模型。
最后,您可以添加一些 WebView 设置的更改。如:
Control.Settings.AllowFileAccess = true;
对于api29,默认值为true。而 api 30 是假的。
可以查看官方文档:
https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess(boolean)
我通过自定义 webview 在我的应用程序中显示 pdf 文件和图像,它显示了一个位于我的应用程序资产文件夹中的 html 小站点。这个“主页”通过获取参数获取要显示的文件。要显示的文件位于我的私人应用程序文档文件夹中。 在我必须将目标 API 级别 30 或更高级别(强制使用范围存储)之前,这工作得很好。现在“主页”无法访问私人文档文件夹中的文件(访问冲突)。 我想知道是否有办法仍然使用这种方法,通过启用了范围存储的 webview 在您的应用程序中显示 pdf 文件和图像。
以下是其当前实施方式的详细信息:
在自定义 webview 的 android 渲染器的 OnElementChanged 方法中(使用 Uri 属性 扩展 Xamarin.Forms.WebView)我设置了 Android webView( control),然后加载uri到图片首页或pdf.js webviewer,在uri中获取参数中的文件(图片或pdf):
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var customWebView = Element as CustomWebView;
Control.Settings.AllowUniversalAccessFromFileURLs = true;
Control.Settings.SetSupportZoom(true);
Control.Settings.BuiltInZoomControls = true;
Control.Settings.DisplayZoomControls = true;
int width = MainApplication.intWidth;
string PathCopy = customWebView.Uri;
customWebView.Uri = customWebView.Uri.Replace(" ", "%20");
string Extension = Path.GetExtension(WebUtility.UrlEncode(customWebView.Uri)).ToUpper();
switch (Extension)
{
case ".PDF": Control.LoadUrl(string.Format("file:///android_asset/pdfjs/web/viewer.html?file={0}", WebUtility.UrlEncode(customWebView.Uri))); break;
default: Control.LoadUrl(string.Format("file:///android_asset/ImageHomepage/ImageHomepage.html?pfad={0}&width={1}", customWebView.Uri, width)); break;
}
}
}
对于 pdf 文件,我使用 pdf.js(如本例所示:https://github.com/xamarin/docs-archive/tree/master/Recipes/xamarin-forms/Controls/display-pdf),对于图像,我使用 html 这个小网站:
<head>
<script>
function getURLParameter(name)
{
var value = decodeURIComponent((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, ""])[1]);
return (value !== 'null') ? value : false;
}
</script>
</head>
<body>
<script language = "Javascript" type="text/javascript">
<!--
var param = getURLParameter('pfad');
var width = getURLParameter('width');
document.write('<img src="');document.write(param); document.write('" width="'); document.write(width); document.write('" style="width:100%" >');
//-->
</script>
</body>
要显示的文件是从我的网络服务下载并存储在我的“PrivateDocumentsFolder”中,声明如下:
public static string PrivateFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
public static string PrivateDocumentsFolder = Path.Combine(PrivateFolder, "Dokumente");
所以文件存储在:/data/user/0/myPackageName/files/Dokumente,这是我在访问 [=38] 的 FilesDir 属性 时也得到的私人文件夹=]上下文对象。
将 requestLegacyExternalStorage 设置为 true 的目标 API 29 使用此方法。使用 Xamarin.Essentials Launcher 打开文件可以启用分区存储,但我想继续在我的应用程序中而不是在外部应用程序中显示文件。
如何在 API 级别 >29 并启用分区存储的情况下使用此方法? 如果我理解正确,使用 Environment.SpecialFolder.MyDocuments 应该是正确的方法,因为它在我的应用程序私有范围内,从我的应用程序内部访问这些文件应该没有问题。
首先,您授予读写存储权限了吗?该文件位于应用程序的私人文件夹中。一般情况下,app可以直接访问。
此外,如果用户更新到API 30,您可以使用preserveLegacyExternalStorage=true
和android:requestLegacyExternalStorage=true
来保留和使用旧的存储模型。
最后,您可以添加一些 WebView 设置的更改。如:
Control.Settings.AllowFileAccess = true;
对于api29,默认值为true。而 api 30 是假的。
可以查看官方文档: https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess(boolean)