locked
input type="file" doesn't work on Xamarin.Forms Webview (Android) RRS feed

  • Question

  • User130622 posted

    I have a WebView that points to a website, something like this:

    var browser = new WebView { Source = "www.sometlink.com/uploadimage" };

    This is a html page where it allow users to upload some images. The html element is just a simple:

    This works well on iOS, but not on Android. The "Choose File" button does nothing at all (no pop out etc.)

    After doing some extensive research, it appears the problem as described here: http://stackoverflow.com/questions/4944102/android-webview-file-input-field-filechooser-doesnt-show-up

    The suggested solution works if I switch to Xamarin.Android, but how do I duplicate the solution using Xamarin.Forms?

    Monday, March 7, 2016 9:53 PM

Answers

  • User27414 posted

    In your MainActivity where LoadApplication(new App()) is called, you must implement this: private Action<int, Result, Intent> _resultCallback; public void StartActivity(Intent intent, int requestCode, Action<int, Result, Intent> resultCallback) { _resultCallback = resultCallback; StartActivityForResult(intent, requestCode); } protected override void OnActivityResult (int requestCode, Result resultCode, Intent data) { base.OnActivityResult (requestCode, resultCode, data); if (_resultCallback != null) { _resultCallback(requestCode, resultCode, data); _resultCallback = null; } }

    then you subclass Android.Webkit.WebChromeClient where you implement your WebView and in the subclass you implement this:

                private void OnActivityResult(int requestCode, Result resultCode, Intent data)
                {
                    if (data != null)
                    {
                        if (requestCode == FILECHOOSER_RESULTCODE) 
                        {
                            if (null == mUploadMessage || data == null)
                                return;
                            mUploadMessage.OnReceiveValue (WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                            mUploadMessage = null;
                        }
                    }
                }
    
                [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
                public override bool OnShowFileChooser (Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
                {
                    var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
                    mUploadMessage = filePathCallback;
                    Intent chooserIntent = fileChooserParams.CreateIntent ();
                    appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
                    //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
                    return true;
                }
    
    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, March 8, 2016 1:08 PM

All replies

  • User76916 posted

    @Liam123 - it won't work on Windows Mobile either. However at least for Android you have work around potential

    https://stackoverflow.com/questions/5907369/file-upload-in-webview

    Tuesday, March 8, 2016 2:05 AM
  • User27414 posted

    In your MainActivity where LoadApplication(new App()) is called, you must implement this: private Action<int, Result, Intent> _resultCallback; public void StartActivity(Intent intent, int requestCode, Action<int, Result, Intent> resultCallback) { _resultCallback = resultCallback; StartActivityForResult(intent, requestCode); } protected override void OnActivityResult (int requestCode, Result resultCode, Intent data) { base.OnActivityResult (requestCode, resultCode, data); if (_resultCallback != null) { _resultCallback(requestCode, resultCode, data); _resultCallback = null; } }

    then you subclass Android.Webkit.WebChromeClient where you implement your WebView and in the subclass you implement this:

                private void OnActivityResult(int requestCode, Result resultCode, Intent data)
                {
                    if (data != null)
                    {
                        if (requestCode == FILECHOOSER_RESULTCODE) 
                        {
                            if (null == mUploadMessage || data == null)
                                return;
                            mUploadMessage.OnReceiveValue (WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                            mUploadMessage = null;
                        }
                    }
                }
    
                [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
                public override bool OnShowFileChooser (Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
                {
                    var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
                    mUploadMessage = filePathCallback;
                    Intent chooserIntent = fileChooserParams.CreateIntent ();
                    appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
                    //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
                    return true;
                }
    
    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, March 8, 2016 1:08 PM
  • User27414 posted

    This should work on Lollipop+ devices. I am not sure for KitKat.

    Tuesday, March 8, 2016 1:11 PM
  • User338364 posted

    Greg, Can you help me understand where the Android.Webkit.WebChromeClient code , goes. I am using the web view example code and want to implement the file upload in the webPage example.

    I have the StartActivity code in mainActivity.cs but not sure of where and what syntax to use for the subclass.

    Does this in go in webPage.cs ? Thanks in advance for any help

    My MainActivity looks like this

    using System;

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

    using Xamarin.Forms.Platform.Android; using Android.Content.PM;

    namespace WorkingWithWebview.Android { [Activity (Label = "WorkingWithWebview.Android.Android", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity // superclass new in 1.3 { protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle);

            global::Xamarin.Forms.Forms.Init (this, bundle);
    
            LoadApplication (new App ()); // method is new in 1.3
        }
    
        //This enables file uplaod to work in Android 
        private Action<int, Result, Intent> _resultCallback;
        public void StartActivity(Intent intent, int requestCode, Action<int, Result, Intent> resultCallback)
        {
            _resultCallback = resultCallback;
            StartActivityForResult(intent, requestCode);
        }
    
        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);
            if (_resultCallback != null)
            {
                _resultCallback(requestCode, resultCode, data);
                _resultCallback = null;
            }
        }
    
    
    }
    

    }

    Monday, July 24, 2017 1:26 PM
  • User27414 posted

    @ScottNett Your MainActivtiy looks correct. As for the WebChromeClient, you need to create a custom renderer for your webview where you have to create an instance of the subclassed WebChromeClient and set it with the SetWebChromeClient on the webview.

    Here is my complete subclass for the WebChromeClient:

    `public class OHWebChromeClient : global::Android.Webkit.WebChromeClient { private IValueCallback mUploadMessage; private static int FILECHOOSER_RESULTCODE = 1;

        public override bool OnJsAlert (Android.Webkit.WebView view, string url, string message, JsResult result)
        {
            return base.OnJsAlert (view, url, message, result);
        }
    
        public override void OnReceivedTitle (Android.Webkit.WebView view, string title)
        {
            base.OnReceivedTitle (view, title);
        }
        public override bool OnCreateWindow (Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
        {
            return true;
        }
    
        private void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            if (requestCode == FILECHOOSER_RESULTCODE) {
                if (null == mUploadMessage)
                    return;
                mUploadMessage.OnReceiveValue (WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                mUploadMessage = null;
            }
        }
    
        [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
        public override bool OnShowFileChooser (Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
        {
            var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
            mUploadMessage = filePathCallback;
            Intent chooserIntent = fileChooserParams.CreateIntent ();
            appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
            //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
            return true;
        }
    }`
    
    Monday, July 24, 2017 7:50 PM
  • User360528 posted

    I created a Renderer, but the input type = "file" does not work. What are the things I need to fix in the code below?

    [assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))] namespace hausBill.Droid { public class HybridWebViewRenderer : ViewRenderer { Context _context; const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";

        public HybridWebViewRenderer(Context context) : base(context)
        {
            Activity activity = (Activity)context;
            _context = context;
        }
    
        protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
        {
            base.OnElementChanged(e);           
    
            if (Control == null)
            {
                var webView = new Android.Webkit.WebView(_context);
    
                webView.Settings.JavaScriptEnabled = true;
                webView.Settings.AllowFileAccess = true;
                webView.Settings.AllowContentAccess = true;
                webView.SetWebChromeClient(new MyWebChromeClient());
                SetNativeControl(webView);
            }
    
            if (Control != null)
            {
                Control.Settings.DomStorageEnabled = true;
    
           //     Android.Webkit.WebView webView = Control;
            }
    
    
            if (e.OldElement != null)
            {
                Control.RemoveJavascriptInterface("jsBridge");
                var hybridWebView = e.OldElement as HybridWebView;
                hybridWebView.Cleanup();
            }
    
            if (e.NewElement != null)
            {
                Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
                //Control.LoadUrl(Element.Uri);
                //Control.LoadUrl(e.NewElement.Uri);
                //Control.LoadUrl(string.Format("file:///android_asset/Content/{0}", Element.Uri));
                //Control.LoadUrl(string.Format(e.NewElement.Uri, Element.Uri));
                //Control.LoadUrl(string.Format(e.NewElement.Source.GetValue, Element.Uri));
                InjectJS(JavaScriptFunction);
            }
    
            void InjectJS(string script)
            {
                if (Control != null)
                {
                    Control.LoadUrl(string.Format("javascript: {0}", script));
                }
            }
    
        }
    }
    
    public class JSBridge : Java.Lang.Object
    {
        readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;
    
        public JSBridge(HybridWebViewRenderer hybridRenderer)
        {
            hybridWebViewRenderer = new WeakReference<HybridWebViewRenderer>(hybridRenderer);
        }
    
        [JavascriptInterface]
        [Export("invokeAction")]
        public void InvokeAction(string data)
        {
            HybridWebViewRenderer hybridRenderer;
    
            if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
            {
                hybridRenderer.Element.InvokeAction(data);
            }
        }
    }
    
    public class MyWebChromeClient : global::Android.Webkit.WebChromeClient
    {
        private IValueCallback mUploadMessage;
        private static int FILECHOOSER_RESULTCODE = 1;
    
        public override bool OnJsAlert(Android.Webkit.WebView view, string url, string message, JsResult result)
        {
            return base.OnJsAlert(view, url, message, result);
        }
    
        public override void OnReceivedTitle(Android.Webkit.WebView view, string title)
        {
            base.OnReceivedTitle(view, title);
        }
        public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
        {
            return true;
        }
    
        private void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            if (requestCode == FILECHOOSER_RESULTCODE)
            {
                if (null == mUploadMessage)
                    return;
                mUploadMessage.OnReceiveValue(WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                mUploadMessage = null;
            }
        }
    
        [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
        public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
        {
            var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
            mUploadMessage = filePathCallback;
            Intent chooserIntent = fileChooserParams.CreateIntent();
            appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
            //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
            return true;
        }
    }
    

    }

    Monday, October 8, 2018 7:39 PM
  • User360528 posted

    I created a Renderer, but the input type = "file" does not work. What are the things I need to fix in the code below?

    [assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))] namespace hausBill.Droid { public class HybridWebViewRenderer : ViewRenderer { Context _context; const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";

        public HybridWebViewRenderer(Context context) : base(context)
        {
            Activity activity = (Activity)context;
            _context = context;
        }
    
        protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
        {
            base.OnElementChanged(e);           
    
            if (Control == null)
            {
                var webView = new Android.Webkit.WebView(_context);
    
                webView.Settings.JavaScriptEnabled = true;
                webView.Settings.AllowFileAccess = true;
                webView.Settings.AllowContentAccess = true;
                webView.SetWebChromeClient(new MyWebChromeClient());
                SetNativeControl(webView);
            }
    
            if (Control != null)
            {
                Control.Settings.DomStorageEnabled = true;
    
           //     Android.Webkit.WebView webView = Control;
            }
    
    
            if (e.OldElement != null)
            {
                Control.RemoveJavascriptInterface("jsBridge");
                var hybridWebView = e.OldElement as HybridWebView;
                hybridWebView.Cleanup();
            }
    
            if (e.NewElement != null)
            {
                Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
                //Control.LoadUrl(Element.Uri);
                //Control.LoadUrl(e.NewElement.Uri);
                //Control.LoadUrl(string.Format("file:///android_asset/Content/{0}", Element.Uri));
                //Control.LoadUrl(string.Format(e.NewElement.Uri, Element.Uri));
                //Control.LoadUrl(string.Format(e.NewElement.Source.GetValue, Element.Uri));
                InjectJS(JavaScriptFunction);
            }
    
            void InjectJS(string script)
            {
                if (Control != null)
                {
                    Control.LoadUrl(string.Format("javascript: {0}", script));
                }
            }
    
        }
    }
    
    public class JSBridge : Java.Lang.Object
    {
        readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;
    
        public JSBridge(HybridWebViewRenderer hybridRenderer)
        {
            hybridWebViewRenderer = new WeakReference<HybridWebViewRenderer>(hybridRenderer);
        }
    
        [JavascriptInterface]
        [Export("invokeAction")]
        public void InvokeAction(string data)
        {
            HybridWebViewRenderer hybridRenderer;
    
            if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
            {
                hybridRenderer.Element.InvokeAction(data);
            }
        }
    }
    
    public class MyWebChromeClient : global::Android.Webkit.WebChromeClient
    {
        private IValueCallback mUploadMessage;
        private static int FILECHOOSER_RESULTCODE = 1;
    
        public override bool OnJsAlert(Android.Webkit.WebView view, string url, string message, JsResult result)
        {
            return base.OnJsAlert(view, url, message, result);
        }
    
        public override void OnReceivedTitle(Android.Webkit.WebView view, string title)
        {
            base.OnReceivedTitle(view, title);
        }
        public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
        {
            return true;
        }
    
        private void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            if (requestCode == FILECHOOSER_RESULTCODE)
            {
                if (null == mUploadMessage)
                    return;
                mUploadMessage.OnReceiveValue(WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                mUploadMessage = null;
            }
        }
    
        [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
        public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
        {
            var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
            mUploadMessage = filePathCallback;
            Intent chooserIntent = fileChooserParams.CreateIntent();
            appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
            //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
            return true;
        }
    }
    

    }

    Monday, October 8, 2018 7:39 PM
  • User360528 posted

    I created a Renderer, but the input type = "file" does not work. What are the things I need to fix in the code below?

    [assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))] namespace hausBill.Droid { public class HybridWebViewRenderer : ViewRenderer { Context _context; const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";

        public HybridWebViewRenderer(Context context) : base(context)
        {
            Activity activity = (Activity)context;
            _context = context;
        }
    
        protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
        {
            base.OnElementChanged(e);
            System.Diagnostics.Debug.WriteLine("hakcom start");
    
            if (Control == null)
            {
                var webView = new Android.Webkit.WebView(_context);// _context);
                /*
                if (Build.VERSION.SdkInt == BuildVersionCodes.Kitkat)
                {
                    webView.SetLayerType(LayerType.Software, null);
                }
                */
                webView.Settings.JavaScriptEnabled = true;
                webView.Settings.AllowFileAccess = true;
                webView.Settings.AllowContentAccess = true;
                webView.SetWebChromeClient(new MyWebChromeClient());
                SetNativeControl(webView);
            }
    
            if (Control != null)
            {
                Control.Settings.DomStorageEnabled = true;
    
           //     Android.Webkit.WebView webView = Control;
            }
    
    
            if (e.OldElement != null)
            {
                Control.RemoveJavascriptInterface("jsBridge");
                var hybridWebView = e.OldElement as HybridWebView;
                hybridWebView.Cleanup();
            }
    
            if (e.NewElement != null)
            {
                Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
                //Control.LoadUrl(Element.Uri);
                //Control.LoadUrl(e.NewElement.Uri);
                //Control.LoadUrl(string.Format("file:///android_asset/Content/{0}", Element.Uri));
                //Control.LoadUrl(string.Format(e.NewElement.Uri, Element.Uri));
                //Control.LoadUrl(string.Format(e.NewElement.Source.GetValue, Element.Uri));
                InjectJS(JavaScriptFunction);
            }
    
            void InjectJS(string script)
            {
                if (Control != null)
                {
                    Control.LoadUrl(string.Format("javascript: {0}", script));
                }
            }
    
        }
    }
    
    public class JSBridge : Java.Lang.Object
    {
        readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;
    
        public JSBridge(HybridWebViewRenderer hybridRenderer)
        {
            hybridWebViewRenderer = new WeakReference<HybridWebViewRenderer>(hybridRenderer);
        }
    
        [JavascriptInterface]
        [Export("invokeAction")]
        public void InvokeAction(string data)
        {
            HybridWebViewRenderer hybridRenderer;
    
            if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
            {
                hybridRenderer.Element.InvokeAction(data);
            }
        }
    }
    
    public class MyWebChromeClient : global::Android.Webkit.WebChromeClient
    {
        private IValueCallback mUploadMessage;
        private static int FILECHOOSER_RESULTCODE = 1;
    
        public override bool OnJsAlert(Android.Webkit.WebView view, string url, string message, JsResult result)
        {
            return base.OnJsAlert(view, url, message, result);
        }
    
        public override void OnReceivedTitle(Android.Webkit.WebView view, string title)
        {
            base.OnReceivedTitle(view, title);
        }
        public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
        {
            return true;
        }
    
        private void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            if (requestCode == FILECHOOSER_RESULTCODE)
            {
                if (null == mUploadMessage)
                    return;
                mUploadMessage.OnReceiveValue(WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                mUploadMessage = null;
            }
        }
    
        [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
        public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
        {
            var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
            mUploadMessage = filePathCallback;
            Intent chooserIntent = fileChooserParams.CreateIntent();
            appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
            //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
            return true;
        }
    }
    

    }

    Monday, October 8, 2018 7:39 PM
  • User360528 posted

    I created a Renderer, but the input type = "file" does not work. What are the things I need to fix in the code below?

    [assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))] namespace hausBill.Droid { public class HybridWebViewRenderer : ViewRenderer { Context _context; const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";

        public HybridWebViewRenderer(Context context) : base(context)
        {
            Activity activity = (Activity)context;
            _context = context;
        }
    
        protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
        {
            base.OnElementChanged(e);
            System.Diagnostics.Debug.WriteLine("hakcom start");
    
            if (Control == null)
            {
                var webView = new Android.Webkit.WebView(_context);// _context);
                /*
                if (Build.VERSION.SdkInt == BuildVersionCodes.Kitkat)
                {
                    webView.SetLayerType(LayerType.Software, null);
                }
                */
                webView.Settings.JavaScriptEnabled = true;
                webView.Settings.AllowFileAccess = true;
                webView.Settings.AllowContentAccess = true;
                webView.SetWebChromeClient(new MyWebChromeClient());
                SetNativeControl(webView);
            }
    
            if (Control != null)
            {
                Control.Settings.DomStorageEnabled = true;
    
           //     Android.Webkit.WebView webView = Control;
            }
    
    
            if (e.OldElement != null)
            {
                Control.RemoveJavascriptInterface("jsBridge");
                var hybridWebView = e.OldElement as HybridWebView;
                hybridWebView.Cleanup();
            }
    
            if (e.NewElement != null)
            {
                Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
                //Control.LoadUrl(Element.Uri);
                //Control.LoadUrl(e.NewElement.Uri);
                //Control.LoadUrl(string.Format("file:///android_asset/Content/{0}", Element.Uri));
                //Control.LoadUrl(string.Format(e.NewElement.Uri, Element.Uri));
                //Control.LoadUrl(string.Format(e.NewElement.Source.GetValue, Element.Uri));
                InjectJS(JavaScriptFunction);
            }
    
            void InjectJS(string script)
            {
                if (Control != null)
                {
                    Control.LoadUrl(string.Format("javascript: {0}", script));
                }
            }
    
        }
    }
    
    public class JSBridge : Java.Lang.Object
    {
        readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;
    
        public JSBridge(HybridWebViewRenderer hybridRenderer)
        {
            hybridWebViewRenderer = new WeakReference<HybridWebViewRenderer>(hybridRenderer);
        }
    
        [JavascriptInterface]
        [Export("invokeAction")]
        public void InvokeAction(string data)
        {
            HybridWebViewRenderer hybridRenderer;
    
            if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
            {
                hybridRenderer.Element.InvokeAction(data);
            }
        }
    }
    
    public class MyWebChromeClient : global::Android.Webkit.WebChromeClient
    {
        private IValueCallback mUploadMessage;
        private static int FILECHOOSER_RESULTCODE = 1;
    
        public override bool OnJsAlert(Android.Webkit.WebView view, string url, string message, JsResult result)
        {
            return base.OnJsAlert(view, url, message, result);
        }
    
        public override void OnReceivedTitle(Android.Webkit.WebView view, string title)
        {
            base.OnReceivedTitle(view, title);
        }
        public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
        {
            return true;
        }
    
        private void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            if (requestCode == FILECHOOSER_RESULTCODE)
            {
                if (null == mUploadMessage)
                    return;
                mUploadMessage.OnReceiveValue(WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                mUploadMessage = null;
            }
        }
    
        [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
        public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
        {
            var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
            mUploadMessage = filePathCallback;
            Intent chooserIntent = fileChooserParams.CreateIntent();
            appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
            //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
            return true;
        }
    }
    

    }

    Monday, October 8, 2018 7:39 PM
  • User395800 posted

    @Greg767 said: In your MainActivity where LoadApplication(new App()) is called, you must implement this: private Action<int, Result, Intent> _resultCallback; public void StartActivity(Intent intent, int requestCode, Action<int, Result, Intent> resultCallback) { _resultCallback = resultCallback; StartActivityForResult(intent, requestCode); } protected override void OnActivityResult (int requestCode, Result resultCode, Intent data) { base.OnActivityResult (requestCode, resultCode, data); if (_resultCallback != null) { _resultCallback(requestCode, resultCode, data); _resultCallback = null; } }

    then you subclass Android.Webkit.WebChromeClient where you implement your WebView and in the subclass you implement this:

              private void OnActivityResult(int requestCode, Result resultCode, Intent data)
              {
                  if (data != null)
                  {
                      if (requestCode == FILECHOOSER_RESULTCODE) 
                      {
                          if (null == mUploadMessage || data == null)
                              return;
                          mUploadMessage.OnReceiveValue (WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                          mUploadMessage = null;
                      }
                  }
              }
    
              [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
              public override bool OnShowFileChooser (Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
              {
                  var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
                  mUploadMessage = filePathCallback;
                  Intent chooserIntent = fileChooserParams.CreateIntent ();
                  appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
                  //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
                  return true;
              }
    

    I implemented the same.This works perfectly while uploading Single File. But Even After selecting Multiple Files, nothing gets uploaded and I get "No File Choosen" message on the screen. I have also added chooserIntent.PutExtra(Intent.ExtraAllowMultiple,true); , but this doesn't seem to help.

    This is what I get on Screen :

    Tuesday, July 21, 2020 6:56 AM
  • User396455 posted

    @SMXamarin said:

    @Greg767 said: In your MainActivity where LoadApplication(new App()) is called, you must implement this: private Action<int, Result, Intent> _resultCallback; public void StartActivity(Intent intent, int requestCode, Action<int, Result, Intent> resultCallback) { _resultCallback = resultCallback; StartActivityForResult(intent, requestCode); } protected override void OnActivityResult (int requestCode, Result resultCode, Intent data) { base.OnActivityResult (requestCode, resultCode, data); if (_resultCallback != null) { _resultCallback(requestCode, resultCode, data); _resultCallback = null; } }

    then you subclass Android.Webkit.WebChromeClient where you implement your WebView and in the subclass you implement this:

                private void OnActivityResult(int requestCode, Result resultCode, Intent data)
                {
                    if (data != null)
                    {
                        if (requestCode == FILECHOOSER_RESULTCODE) 
                        {
                            if (null == mUploadMessage || data == null)
                                return;
                            mUploadMessage.OnReceiveValue (WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                            mUploadMessage = null;
                        }
                    }
                }
    
                [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
                public override bool OnShowFileChooser (Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
                {
                    var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
                    mUploadMessage = filePathCallback;
                    Intent chooserIntent = fileChooserParams.CreateIntent ();
                    appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
                    //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
                    return true;
                }
    

    I implemented the same.This works perfectly while uploading Single File. But Even After selecting Multiple Files, nothing gets uploaded and I get "No File Choosen" message on the screen. I have also added chooserIntent.PutExtra(Intent.ExtraAllowMultiple,true); , but this doesn't seem to help.

    This is what I get on Screen :

    Can i get your sample project ?

    Thursday, August 27, 2020 1:47 AM
  • User396455 posted

    Can i get sample of it ?

    Wednesday, October 21, 2020 6:54 AM