Xamarin WebView 下载不适用于 Mp4Upload



我有一个小的Xamarin表单应用程序,我想用它从mp4Upload下载文件。这是通过将mp4Upload url加载到WebView上,然后使用WebView.EvaluateJavascriptAsync()以编程方式单击下载按钮来完成的。

问题是它不会触发下载。

public class AndroidWebView : WebViewRenderer
{
public AndroidWebView(Context ctx) : base(ctx)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Settings.UserAgentString = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.4) Gecko/20100101 Firefox/4.0";
}
Control.Download += DownloadEvent;
}
private void DownloadEvent(object sender, Android.Webkit.DownloadEventArgs e)
{
string url = e.Url;
DownloadManager.Request request = new DownloadManager.Request(Android.Net.Uri.Parse(url));
request.SetNotificationVisibility(DownloadVisibility.VisibleNotifyCompleted);
request.SetDestinationInExternalPublicDir(Android.OS.Environment.DirectoryDownloads, "CPPPrimer");
DownloadManager dm = (DownloadManager)Android.App.Application.Context.GetSystemService("download");
dm.Enqueue(request);
Toast.MakeText(Android.App.Application.Context, e.Url, ToastLength.Long).Show();
}
}

我用github url测试了上面的代码,下载了一个随机的.gitignore文件,效果很好。

如果我手动单击下载,mp4Upload链接也可以在chrome中工作,也可以使用cefsharp使用ChromiumWebBrowser.ExecuteScriptAsync()以编程方式单击下载来处理winforms。

有人知道如何解决这个问题吗?

它并不像看上去那么简单,尤其是对于在_blank目标中打开的下载。这是我在一个项目中使用的代码:

  1. 设置您的网络视图以支持下载:
using Xamarin.Forms;
using Android.Webkit;
using Android.Content;
using System.Threading.Tasks;
using Xamarin.Forms.Platform.Android;
// In your android webview renderer
protected override void OnElementChanged(ElementChangedEventArgs<XamWebView> e)
{
base.OnElementChanged(e);
if (this.Control != null)
{
var xamWebView = (AppWebView)e.NewElement;
this.AllowFileDownloads(this.Control, xamWebView);
}
}
private void AllowFileDownloads(DroidWebView webView, AppWebView customWebView)
{
webView.Settings.SetSupportMultipleWindows(false);
var downloadListener = new WebViewDownloadListener(this.Context);
webView.SetDownloadListener(downloadListener);
}
  1. 将其用作Web视图下载侦听器
using System;
using Android.App;
using Android.Widget;
using Android.Webkit;
using Android.Content;
using Xamarin.Essentials;
public class WebViewDownloadListener : Java.Lang.Object, IDownloadListener
{
private Context AppContext { get; }
public event Action<string> OnDownloadStarted;
private DownloadManager DownloadManager => DownloadManager.FromContext(this.AppContext);
public WebViewDownloadListener(Context appContext)
{
this.AppContext = appContext;
this.AppContext.RegisterReceiver(new OnDownloadCompleteOpenFileInDefaultApp(), new IntentFilter(DownloadManager.ActionDownloadCom
}
public void OnDownloadStart(string url, string userAgent, string contentDisposition, string mimetype, long contentLength)
{
this.OnDownloadStarted?.Invoke(url);
var downloadRequest = BuildDownloadRequest(url, userAgent, contentDisposition, mimetype);
AppErrorHandler.ExecuteSafely(async () =>
{
if (ShouldAskPermissionToSaveFile)
{
var permission = await Permissions.RequestAsync<Permissions.StorageWrite>();
if (permission == PermissionStatus.Granted)
this.EnqueueDownloadRequest(downloadRequest);
}
else
this.EnqueueDownloadRequest(downloadRequest);
});
}
private static bool ShouldAskPermissionToSaveFile => Android.OS.Build.VERSION.SdkInt <= Android.OS.BuildVersionCodes.P;
private void EnqueueDownloadRequest(DownloadManager.Request downloadRequest)
{
this.DownloadManager.Enqueue(downloadRequest);
Toast.MakeText(this.AppContext, "Downloading File", ToastLength.Long).Show();
}
private static DownloadManager.Request BuildDownloadRequest(string url, string userAgent, string contentDisposition, string mimetype)
{
var request = new DownloadManager.Request(Android.Net.Uri.Parse(url));
request.SetMimeType(mimetype);
request.SetDescription("Downloading file...");
request.AddRequestHeader("User-Agent", userAgent);
request.AddRequestHeader("cookie", CookieManager.Instance.GetCookie(url));
request.SetNotificationVisibility(DownloadVisibility.VisibleNotifyCompleted);
request.SetDestinationInExternalPublicDir(
Android.OS.Environment.DirectoryDownloads, 
URLUtil.GuessFileName(url, contentDisposition, mimetype)
);
return request;
}
}
  1. 最后,这是您的下载广播接收器
using Java.IO;
using Android.App;
using Android.Widget;
using Android.Content;
using Android.Database;
using AndroidX.Core.Content;
public class OnDownloadCompleteOpenFileInDefaultApp : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (DownloadManager.ActionDownloadComplete.Equals(intent.Action))
{
ICursor cursor = GetDbCursorForDownloadedFile(context, intent);
if (cursor.MoveToFirst())
{
var (downloadStatus, downloadUri, mimeType) = ExtractDataFromCursor(cursor);
if (downloadStatus == (int)DownloadStatus.Successful && downloadUri != null)
{
var fileUri = GetFileUri(context, downloadUri);
var openFileIntent = CreateOpenFileIntent(mimeType, fileUri);
LaunchOpenFileIntent(context, openFileIntent);
}
}
cursor.Close();
}
}
private static ICursor GetDbCursorForDownloadedFile(Context context, Intent intent)
{
var downloadManager = DownloadManager.FromContext(context);
var downloadId = intent.GetLongExtra(DownloadManager.ExtraDownloadId, 0);
var query = new DownloadManager.Query();
query.SetFilterById(downloadId);
var cursor = downloadManager.InvokeQuery(query);
return cursor;
}
private static (int status, string downloadUri, string mimeType) ExtractDataFromCursor(ICursor cursor) =
(
cursor.GetInt(cursor.GetColumnIndex(DownloadManager.ColumnStatus)),
cursor.GetString(cursor.GetColumnIndex(DownloadManager.ColumnLocalUri)),
cursor.GetString(cursor.GetColumnIndex(DownloadManager.ColumnMediaType))
);
private static Android.Net.Uri GetFileUri(Context context, string downloadUri)
{
var fileUri = Android.Net.Uri.Parse(downloadUri);
if (ContentResolver.SchemeFile.Equals(fileUri.Scheme))
{
// FileUri - Convert it to contentUri.
File file = new File(fileUri.Path);
fileUri = FileProvider.GetUriForFile(context, $"{context.PackageName}.fileprovider", file);
}
return fileUri;
}
private static Intent CreateOpenFileIntent(string mimeType, Android.Net.Uri fileUri)
{
Intent openAttachmentIntent = new Intent(Intent.ActionView);
openAttachmentIntent.SetDataAndType(fileUri, mimeType);
openAttachmentIntent.SetFlags(ActivityFlags.GrantReadUriPermission);
return openAttachmentIntent;
}
private static void LaunchOpenFileIntent(Context context, Intent openAttachmentIntent)
{
try
{
context.StartActivity(openAttachmentIntent);
}
catch (ActivityNotFoundException)
{
Toast.MakeText(context, "Could not open file.", ToastLength.Long).Show();
}
}
}

相关内容

最新更新