Roland Horváth
Roland Horváth

Reputation: 3

Xamarin android webview dont open camera

I am really beginner in xamarin. I need an app, what is load a website in webview. The site need file uploading <input type="file" accept="image/*" />. In mobile browser it is perfect, can open camera or choose from storage. IOS webview working too, I gave permission and it is OK. But in android, I tried a lot of code, but the best result a filechooser without camera, and it doesn’t even load the image I select from storage. Can anyone help, what is the problem? My current code:

public class MainActivity : AppCompatActivity
    {
    private static IValueCallback mUploadMessage;
    private static int FILECHOOSER_RESULTCODE = 1;
    public static  IValueCallback mUMA; 
    public static int FCR = 1;  

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.activity_main);

        var web = this.FindViewById<WebView>(Resource.Id.wv);
        web.Settings.JavaScriptEnabled = true;
        web.SetWebChromeClient(new myWebChromeClient(this));
        web.LoadUrl....
    }
    protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
    {
        if (requestCode == FILECHOOSER_RESULTCODE)
        {
            if (null == mUploadMessage) return;
            Android.Net.Uri result = intent == null || resultCode != Result.Ok ? null : intent.Data;
            mUploadMessage.OnReceiveValue(result);
            mUploadMessage = null;
        }
    }
    public class myWebChromeClient : WebChromeClient
    {
        Activity mActivity = null;
        public myWebChromeClient(Activity activity)
        {
            mActivity = activity;
        }
        public override bool OnShowFileChooser(WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
        {
            if (MainActivity.mUMA != null)
            {
                mUMA.OnReceiveValue(null);
            }
            mUMA = filePathCallback;
            Intent captureIntent = fileChooserParams.CreateIntent();
            Intent contentSelectionIntent = new Intent(Intent.ActionGetContent);
            contentSelectionIntent.AddCategory(Intent.CategoryOpenable);
            contentSelectionIntent.SetType("*/*");
            Intent[] intentArray;
            if (captureIntent != null)
            {
                intentArray = new Intent[] { captureIntent };
            }
            else
            {
                intentArray = new Intent[0];
            }

            Intent chooserIntent = new Intent(Intent.ActionChooser);
            chooserIntent.PutExtra(Intent.ExtraIntent, contentSelectionIntent);
            chooserIntent.PutExtra(Intent.ExtraTitle, "Image Chooser");
            chooserIntent.PutExtra(Intent.ExtraInitialIntents, intentArray);
            mActivity.StartActivityForResult(chooserIntent, FCR);
            return base.OnShowFileChooser(webView, filePathCallback, fileChooserParams);
        }
    }
}

Upvotes: 0

Views: 2227

Answers (1)

Leon Lu
Leon Lu

Reputation: 9264

I write a demo to open the camera by Input button in HTML page, I used local HTML page to make a test, here is running GIF.

enter image description here

Here is my code in MainActivity.cs.

using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Runtime;
using Android.Widget;
using Android.Webkit;
using Android.Content;
using Java.IO;
using Android.Net;
using Android.Support.V4.Content;
using Android;
using Android.Content.PM;

namespace MyWebviewDemo
{
    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true,LaunchMode =Android.Content.PM.LaunchMode.SingleTop)]
    public class MainActivity : AppCompatActivity
    {
        private static IValueCallback mUploadMessage;
        private static int FILECHOOSER_RESULTCODE = 1;
        public static IValueCallback mUMA;
        public static int FCR = 1;
        public static IValueCallback mUploadCallbackAboveL;
        public static int PHOTO_REQUEST=10023;
        public static Uri imageUri;
       public static MainActivity Instance;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);
            WebView webView1 = FindViewById<WebView>(Resource.Id.webView1);
            webView1.Settings.JavaScriptEnabled = true;
            webView1.Settings.UseWideViewPort=true;
            webView1.Settings.LoadWithOverviewMode=true;
            webView1.Settings.DomStorageEnabled=true;
            webView1.Settings.DefaultTextEncodingName="UTF-8";
            webView1.SetWebViewClient(new MyWebViewClient(this));
            webView1.SetWebChromeClient(new myWebChromeClient(this));
            webView1.LoadUrl("file:///android_asset/index.html");
            Instance = this;
 if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) != (int)Permission.Granted)
            {
                RequestPermissions(new string[] { Manifest.Permission.Camera }, 0);
            }


            //开启存储权限
            if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != (int)Permission.Granted)
            {
                RequestPermissions(new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage }, 0);
            }




        }
        protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
        {
            if (requestCode == FILECHOOSER_RESULTCODE)
            {
                if (null == mUploadMessage) return;
                Android.Net.Uri result = intent == null || resultCode != Result.Ok ? null : intent.Data;
                mUploadMessage.OnReceiveValue(result);
                mUploadMessage = null;
            }else if (requestCode== PHOTO_REQUEST)
            {
                Uri result = intent == null || resultCode != Result.Ok ? null : intent.Data;

                if (mUploadCallbackAboveL != null)
                {
                    onActivityResultAboveL(requestCode, resultCode, intent);
                }
                else if (mUploadMessage != null)
                {
                    mUploadMessage.OnReceiveValue(result);
                    mUploadMessage = null;
                }

                //mUploadMessage.OnReceiveValue(result);
                //mUploadMessage = null;
            }
        }
        private void onActivityResultAboveL(int requestCode, Result resultCode, Intent data)
        {
            if (requestCode != PHOTO_REQUEST || mUploadCallbackAboveL == null)
            {
                return;
            }
            Uri[] results = null;
            if (resultCode == Result.Ok)
            {
                results = new Uri[] { imageUri };
                results[0] = MainActivity.imageUri;
                //if (data == null)
                //{
                //    results = new Uri[] { imageUri };
                //}
                //else
                //{
                //    results[0] = MainActivity.imageUri;
                //    //get the data
                //    string dataString = data.DataString;
                //    ClipData clipData = data.ClipData;
                //    if (clipData != null)
                //    {
                //        results = new Uri[clipData.ItemCount];
                //        for (int i = 0; i < clipData.ItemCount; i++)
                //        {
                //            ClipData.Item item = clipData.GetItemAt(i);
                //            results[i] = item.Uri;
                //        }
                //    }

                //    if (dataString != null)
                //        results = new Uri[] { Uri.Parse(dataString) };
                //}
            }
            mUploadCallbackAboveL.OnReceiveValue(results);
            mUploadCallbackAboveL = null;
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    internal class MyWebViewClient : WebViewClient
    {
        private MainActivity mainActivity;

        public MyWebViewClient(MainActivity mainActivity)
        {
            this.mainActivity = mainActivity;
        }
    }

    public class myWebChromeClient : WebChromeClient
    {
        Activity mActivity = null;
        public myWebChromeClient(Activity activity)
        {
            mActivity = activity;
        }
        public override bool OnShowFileChooser(WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
        {
            MainActivity.mUploadCallbackAboveL = filePathCallback;
            TakePhoto();
            //if (MainActivity.mUMA != null)
            //{
            //    MainActivity.mUMA.OnReceiveValue(null);
            //}
            //MainActivity.mUMA = filePathCallback;
            //Intent captureIntent = fileChooserParams.CreateIntent();
            //Intent contentSelectionIntent = new Intent(Intent.ActionGetContent);
            //contentSelectionIntent.AddCategory(Intent.CategoryOpenable);
            //contentSelectionIntent.SetType("*/*");
            //Intent[] intentArray;
            //if (captureIntent != null)
            //{
            //    intentArray = new Intent[] { captureIntent };
            //}
            //else
            //{
            //    intentArray = new Intent[0];
            //}

            //Intent chooserIntent = new Intent(Intent.ActionChooser);
            //chooserIntent.PutExtra(Intent.ExtraIntent, contentSelectionIntent);
            //chooserIntent.PutExtra(Intent.ExtraTitle, "Image Chooser");
            //chooserIntent.PutExtra(Intent.ExtraInitialIntents, intentArray);
            //mActivity.StartActivityForResult(chooserIntent, MainActivity.FCR);
            return true;
        }

        private void TakePhoto()
        {
            File fileUri = new File(Environment.ExternalStorageDirectory.Path);
            //MainActivity.imageUri = Uri.FromFile(fileUri);
            if (Build.VERSION.SdkInt >=Android.OS.BuildVersionCodes.N)
            {
                if (!fileUri.Exists())
                {
                    fileUri.Mkdir();
                }
                File file = new File(fileUri, SystemClock.CurrentThreadTimeMillis()+".jpg");
                MainActivity.imageUri = FileProvider.GetUriForFile(mActivity, "com.companyname.mywebviewdemo" + ".fileprovider", file);//通过FileProvider创建一个content类型的Uri
            }
            PhotoUtils.TakePicture(MainActivity.Instance, MainActivity.imageUri, MainActivity.PHOTO_REQUEST);
        }

    }
}

Here is my Util.cs to take a camera.

 public static void TakePicture(Activity activity, Android.Net.Uri imageUri, int requestCode)
        {
           
            Intent intentCamera = new Intent();
          
            intentCamera.SetAction(MediaStore.ActionImageCapture);
            

           // intentCamera.PutExtra(MediaStore.ExtraOutput, imageUri);
            if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.N)
            {

                intentCamera.AddFlags(ActivityFlags.GrantReadUriPermission); 
            }
            if (activity != null)
            {
                activity.StartActivityForResult(intentCamera, requestCode);
            }
        }

I update my demo to github, you can downdload it and test it.

https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/MyWebviewDemo.zip

Upvotes: 1

Related Questions