簡體   English   中英

Xamarin WebView 下載不適用於 Mp4Upload

[英]Xamarin WebView download doesn't work for 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 測試了上面的代碼,以下載一個可以正常工作的 random.gitignore 文件。

如果我手動單擊下載以及使用 cefsharp 使用ChromiumWebBrowser.ExecuteScriptAsync()以編程方式單擊下載,則 mp4Upload 鏈接也適用於 chrome。

有誰知道如何解決這個問題?

它並不像看起來那么簡單,尤其是對於在_blank目標中打開的下載。 這是我在一個項目中使用的代碼:

  1. 設置您的 webview 以支持下載:
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. 將此用作您的 webview 下載監聽器
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();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM