在 Xamarin Android App 中使用 webview 上传文件

Posted

技术标签:

【中文标题】在 Xamarin Android App 中使用 webview 上传文件【英文标题】:Uploading files using a webview in Xamarin Android App 【发布时间】:2018-01-07 08:36:41 【问题描述】:

我正在开发一个简单的 xamarin android 应用程序,它允许显示响应式网站并接收推送通知。

Webview 似乎对 Xamarin 有一些限制,因此我基于以下 cmets (https://forums.xamarin.com/discussion/3259/cannot-override-webviewclient-class-for-file-upload-support) 使用了以下解决方法 (https://github.com/GabLeRoux/xamarin-android-webview-upload) 以使 html 上传按钮按预期工作。

一切顺利,直到我将推送通知从 GCM 迁移到 FCM。之后webview,重新开始工作。

基本上,html 上传按钮不会打开文件选择器对话框,也不会引发任何错误。它什么都不做。

以下是我在网络活动中使用的代码。

我正在使用 Xamarin.Android 7.3 和 VS 2015。

欢迎任何帮助。

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

    

【问题讨论】:

工作解决方案 github.com/milano95a/xamarin_android_webview_file_upload 【参考方案1】:

步骤 1

文件上传将起作用,我们需要在 android manifest 中授予读/写权限。 在 Main Activity.cs 中

第二步

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;

第三步

添加 ExtendedChromeClient,cs 继承自: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;
        
    

【讨论】:

老兄,我一直在努力让它永远工作,非常感谢! ...如果我能给你加 100,我会 =]

以上是关于在 Xamarin Android App 中使用 webview 上传文件的主要内容,如果未能解决你的问题,请参考以下文章

在xamarin上写好的android程序可以直接用在iOS上吗?

Xamarin做过哪些app?

App Center 应用内更新未显示在 Xamarin Android 应用中

在 Xamarin 表单中使用效果的 Android 工具栏中心

如何使用 Xamarin Visual Studio 2015 构建 Android App Bundle?

如何在 Xamarin(iOS 和 Android)应用程序中使用 Windows 命名空间?