Forum Xamarin.Forms

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Android Camera WebView Image Upload ERR_FILE_NOT_FOUND

I am working on a simple app that views a webpage that has an area for a user to take pictures and upload them to the site.
I found some examples that look like this

 public class CustomWebViewRenderer : WebViewRenderer
    {
        Activity mContext;
        private static int FILECHOOSER_RESULTCODE = 1;
        public CustomWebViewRenderer(Context context) : base(context)
        {
            mContext = context as Activity;
        }
        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            try
            {
                base.OnElementChanged(e);

                var chromeClient = new FileChooserWebChromeClient((uploadMsg, acceptType, capture) => {
                    MainActivity.UploadMessage = uploadMsg;

                    // Create MyAppFolder at SD card for saving our images
                    File imageStorageDir = new File(Android.OS.Environment.GetExternalStoragePublicDirectory(
                            Android.OS.Environment.DirectoryPictures), "MyAppFolder");

                    if (!imageStorageDir.Exists())
                    {
                        imageStorageDir.Mkdirs();
                    }

                    // Create camera captured image file path and name, add ticks to make it unique 
                    var file = new File(imageStorageDir + File.Separator + "IMG_"
                        + DateTime.Now.Ticks + ".jpg");

                    MainActivity.mCapturedImageURI = Android.Net.Uri.FromFile(file);

                    // Create camera capture image intent and add it to the chooser
                    var captureIntent = new Intent(MediaStore.ActionImageCapture);
                    captureIntent.PutExtra(MediaStore.ExtraOutput, MainActivity.mCapturedImageURI);

                    var i = new Intent(Intent.ActionGetContent);
                    i.AddCategory(Intent.CategoryOpenable);
                    i.SetType("image/*");

                    var chooserIntent = Intent.CreateChooser(i, "Choose image");
                    chooserIntent.PutExtra(Intent.ExtraInitialIntents, new Intent[] { captureIntent });

                    (mContext).StartActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
                });

                Control.SetWebChromeClient(chromeClient);
            }
            catch (Exception ex)
            {
                var j = ex;                
            }            
        }
    }

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

        public FileChooserWebChromeClient(Action<IValueCallback, Java.Lang.String, Java.Lang.String> callBack)
        {
            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
        public override Boolean OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback uploadMsg, WebChromeClient.FileChooserParams fileChooserParams)
        {
            try
            {
                callback(uploadMsg, null, null);
            }
            catch (Exception ex)
            {
                var j = ex;
            }
            return true;
        }
    }

Added this to the MainActivity

public static Android.Webkit.IValueCallback UploadMessage;
private static int FILECHOOSER_RESULTCODE = 1;
public static Android.Net.Uri mCapturedImageURI;
protected override void OnActivityResult(int requestCode, Result resultCode, Android.Content.Intent data)
        {
            if (requestCode == FILECHOOSER_RESULTCODE)
            {
                if (null == UploadMessage)
                    return;

                Java.Lang.Object result;

                if (data != null && data.Data != null)
                    result = data.Data;
                else
                    result = mCapturedImageURI;

                UploadMessage.OnReceiveValue(new Android.Net.Uri[] { (Android.Net.Uri)result });
                UploadMessage = null;
            }
            else
                base.OnActivityResult(requestCode, resultCode, data);
        }

This works fine on older versions of Android but when I loaded it up on Android 8, I get the message "ERR_FILE_NOT_FOUND" from the website.
I feel like I'm close, but missing something small to make this work.

Best Answer

Answers

  • YelinzhYelinzh Member, Xamarin Team Xamurai

    How did you load the html file? I don't get that from the code. Please check if the loading url is set correctly. You could check the following code:

    public class HybridWebViewRenderer : WebViewRenderer
    {
        ...
        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            try
            {
                base.OnElementChanged(e);
                ...
    
                Control.SetWebChromeClient(chromeClient);
    
                Control.LoadUrl("file:///android_asset/index.html");
            }
            catch (Exception ex)
            {
                var j = ex;
            }
        }
    }
    
  • YellowflagYellowflag Member ✭✭

    I'm loading the website via the WebView in the MainPage.xaml file like this;

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:myScanner"
                 xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
                 NavigationPage.HasNavigationBar="false"
                 xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
                 ios:Page.UseSafeArea="true"
                 x:Class="myScanner.MainPage">
        <ContentPage.Content>
            <AbsoluteLayout>
                <StackLayout BackgroundColor="White"
                             AbsoluteLayout.LayoutBounds=".5,.0,1,.07"
                             AbsoluteLayout.LayoutFlags="All">
                    <Grid Margin="5,5">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="33*" />
                            <ColumnDefinition Width="33*" />
                            <ColumnDefinition Width="33*" />
                        </Grid.ColumnDefinitions>
                        <Image Source="barcode.png" Grid.Row="0" Grid.Column="2" VerticalOptions="Center">
                            <Image.GestureRecognizers>
                                <TapGestureRecognizer Tapped="OnTapGestureRecognizerTapped" />
                            </Image.GestureRecognizers>
                        </Image>                    
                    </Grid>
                </StackLayout>
                <WebView x:Name="myView" Source="https://somewebsite.com/login.aspx" 
                         AbsoluteLayout.LayoutBounds=".5, 1, 1, .93"                     
                         AbsoluteLayout.LayoutFlags="All" />
    
            </AbsoluteLayout>
        </ContentPage.Content>
    
    </ContentPage>
    
  • YelinzhYelinzh Member, Xamarin Team Xamurai

    Does it work fine when using the Xamarin.Forms.WebView to load url directly on Android 8?

  • YellowflagYellowflag Member ✭✭

    I adjusted the last lines of OnElementChanged to

    Control.SetWebChromeClient(chromeClient); Control.LoadUrl("https://somewebsite.com/login.aspx");

    and removed

    Source="https://somewebsite.com/login.aspx"

    from MainPage.xaml

    No change.

    It's like the photo is not being sent to the server.
    After the camera comes up and I take the picture, the file name appears on the webpage beside the file upload control as expected. But upon selecting upload, the response is always "ERR_FILE_NOT_FOUND"

    If I select an existing photo on the device, it works fine.

  • YelinzhYelinzh Member, Xamarin Team Xamurai
    edited July 2020

    After the camera comes up and I take the picture, the file name appears on the webpage beside the file upload control as expected. But upon selecting upload, the response is always "ERR_FILE_NOT_FOUND"

    For the taking camea to upload the file, you could customzie the code for the function.

    public override bool OnShowFileChooser(WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
    {
        //when choose taking phot call the method.
        TakePhoto();
    }
    

    Check the link:
    https://stackoverflow.com/questions/62656020/xamarin-android-webview-dont-open-camera/62674299#62674299

  • YellowflagYellowflag Member ✭✭

    First, Thank you for helping me with this issue. I really appreciate you taking the time.

    I have tried that demo and it doesn't work either. I've pointed it a couple of different sites and am not able to upload photos with it either. Same error message.

    FYI: My testing is done with the Android Emulator that comes with Visual Studio.

  • YelinzhYelinzh Member, Xamarin Team Xamurai
    edited July 2020

    I tested a sample about the function, it works fine with the local html file on Android 8.1. I posted the demo file as the attachment, you could refer to the code.

  • YellowflagYellowflag Member ✭✭

    @YelinZh, thank you, it appears the demo code is for something else.
    There is no camera access or upload button.

  • YellowflagYellowflag Member ✭✭

    @YelinZh, Thank you, I was able to upload direct from the camera to a web page with this version and have it working in my project now.

    Now I would like the option to select photos removed and just display the camera like the other demo here currently works.
    https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/MyWebviewDemo.zip

    Thanks again for your help.

  • TimmyRTimmyR Member

    Thanks @Yellowflag & @Yelinzh
    I was able to modify that code sample to make it work in my solution.
    Works really good, being able to choose camera or saved files.

Sign In or Register to comment.