Uploading files using a webview in Xamarin Android

2019-07-19 12:46发布

I'm working on a simple xamarin android app, that allows to display a responsive web site, and receive push notifications.

Webview seems to have some limitations on Xamarin, so I used the following workaround (https://github.com/GabLeRoux/xamarin-android-webview-upload) based on the following comments (https://forums.xamarin.com/discussion/3259/cannot-override-webviewclient-class-for-file-upload-support) in order to get html upload button work as expected.

Everything goes well, until I migrate push notifications from GCM to FCM. After that the webview, returns to work as the beginning.

Basically, the html upload button does not open a file chooser dialog, and don't raise any error. It simply does nothing.

Following is the code I'm using on the web activity.

I'm using Xamarin.Android 7.3, and VS 2015.

Any help is welcome.

using System;
using Android.Runtime;
using Android.Views;
using Android.App;
using Android.Content;
using Android.OS;

using Android.Webkit;
using Android.Widget;



namespace sigese
{
    [Activity(Label = "WebActivity")]
    public class WebActivity : Activity
    {


        IValueCallback mUploadMessage;
        private static int FILECHOOSER_RESULTCODE = 1;
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.WebLayout);

            ActionBar.Hide();

            var username = Intent.GetStringExtra("username");
            var password = Intent.GetStringExtra("password");

            var chrome = new FileChooserWebChromeClient((uploadMsg, acceptType, capture) => {
                mUploadMessage = uploadMsg;
                var i = new Intent(Intent.ActionGetContent);
                i.AddCategory(Intent.CategoryOpenable);
                i.SetType("image/*");
                StartActivityForResult(Intent.CreateChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
            });

            var webview = this.FindViewById<WebView>(Resource.Id.LocalWebView);
            webview.SetWebViewClient(new WebViewClient());
            webview.SetWebChromeClient(chrome);
            webview.Settings.JavaScriptEnabled = true;


           webview.LoadUrl("https://example.com/login.asp?username="+username+"&password="+password);




        }

        protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
        {
            if (requestCode == FILECHOOSER_RESULTCODE)
            {
                if (null == mUploadMessage)
                    return;
                Java.Lang.Object result = intent == null || resultCode != Result.Ok
                    ? null
                    : intent.Data;
                mUploadMessage.OnReceiveValue(result);
                mUploadMessage = null;
            }
        }

        public override void OnBackPressed()
        {
            WebView localWebView = FindViewById<WebView>(Resource.Id.LocalWebView);
            if (localWebView.CanGoBack())
            {
                localWebView.GoBack();
            }
            else
            {
               return;
            }
        }


    }
    partial class FileChooserWebChromeClient : WebChromeClient
    {
        Action<IValueCallback, Java.Lang.String, Java.Lang.String> callback;

        public FileChooserWebChromeClient(Action<IValueCallback, Java.Lang.String, Java.Lang.String> callback)
        {
            this.callback = callback;
        }

        // For Android < 5.0
        [Java.Interop.Export]
        public void openFileChooser(IValueCallback uploadMsg, Java.Lang.String acceptType, Java.Lang.String capture)
        {
            callback(uploadMsg, acceptType, capture);
        }

        // For Android > 5.0

    }
}

1条回答
Juvenile、少年°
2楼-- · 2019-07-19 13:51

Step 1

File upload will work , we need to give Read / Write permission in android manifest. in Main Activity.cs

Step 2

private Action<int, Result, Intent> resultCallbackvalue;

public void StartActivity(Intent intent, int requestCode, Action<int, Result, Intent> resultCallback)
{
    this.resultCallbackvalue = resultCallback;
    StartActivityForResult(intent, requestCode);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    if (this.resultCallbackvalue != null)
{
   this.resultCallbackvalue(requestCode, resultCode, data);
   this.resultCallbackvalue = null;
}

Step 3

Add ExtendedChromeClient,cs Inheriting from : WebChromeClient

private static int filechooser = 1;
private IValueCallback message;
private MainActivity activity = null;

public ExtendedChromeClient(MainActivity context)
{
    this.activity = context;
}

public override bool OnShowFileChooser(WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
{
    this.message = filePathCallback;
    Intent chooserIntent = fileChooserParams.CreateIntent();
    chooserIntent.AddCategory(Intent.CategoryOpenable);
    this.activity.StartActivity(Intent.CreateChooser(chooserIntent, "File Chooser"), filechooser, this.OnActivityResult);
    return true;
}

private void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    if (data != null)
    {
        if (requestCode == filechooser)
        {
            if (null == this.message)
            {`enter code here`
                    return;
            }

            this.message.OnReceiveValue(WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
            this.message = null;
        }
    }
}
查看更多
登录 后发表回答