question

rickruhl-4179 avatar image
0 Votes"
rickruhl-4179 asked RobCaplan edited

camera not showing in webview on the andriod

We have been trying to make the camera work on the app under android. Camera works find under IOS

Manifest:

 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.webcamtest" android:installLocation="auto">
     <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
     <application android:label="webcamtest.Android" android:theme="@style/MainTheme"></application>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
     <uses-permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT" />
     <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
     <uses-permission android:name="android.permission.LOCATION_HARDWARE" />
 </manifest>

utils.cs

 using Plugin.Permissions;
 using Plugin.Permissions.Abstractions;
 using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Threading.Tasks;
 using Xamarin.Forms;
    
 namespace webcamtest
 {
     public static class Utils
     {
         public static async Task<PermissionStatus> CheckPermissions(Permission permission)
         {
             var permissionStatus = await CrossPermissions.Current.CheckPermissionStatusAsync<CameraPermission>();
             bool request = false;
             if (permissionStatus == PermissionStatus.Denied)
             {
                 if (Device.RuntimePlatform == Device.iOS)
                 {
    
                     var title = $"{permission} Permission";
                     var question = $"To use this plugin the {permission} permission is required. Please go into Settings and turn on {permission} for the app.";
                     var positive = "Settings";
                     var negative = "Maybe Later";
                     var task = Application.Current?.MainPage?.DisplayAlert(title, question, positive, negative);
                     if (task == null)
                         return permissionStatus;
    
                     var result = await task;
                     if (result)
                     {
                         CrossPermissions.Current.OpenAppSettings();
                     }
    
                     return permissionStatus;
                 }
    
                 request = true;
    
             }
    
             if (request || permissionStatus != PermissionStatus.Granted)
             {
                 var newStatus = await CrossPermissions.Current.CheckPermissionStatusAsync<CameraPermission>();
    
                 if (newStatus == PermissionStatus.Granted)
                 {
                     return permissionStatus;
                 }
    
                 permissionStatus = newStatus;
    
                 if (newStatus != PermissionStatus.Granted)
                 {
                     permissionStatus = newStatus;
                     var title = $"{permission} Permission";
                     var question = $"To use the plugin the {permission} permission is required.";
                     var positive = "Settings";
                     var negative = "Maybe Later";
                     var task = App.Current?.MainPage?.DisplayAlert(title, question, positive, negative);
                     if (task == null)
                         return permissionStatus;
    
                     var result = await task;
                     if (result)
                     {
                         CrossPermissions.Current.OpenAppSettings();
                     }
                     return permissionStatus;
                 }
             }
    
             return permissionStatus;
         }
     }
 }

mainpage.cs


 using Plugin.Permissions;
 using Plugin.Permissions.Abstractions;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Xamarin.Forms;
 using webcamtest;
    
 namespace webcamtest
 {
     public partial class MainPage : ContentPage
     {
         public MainPage()
         {
             InitializeComponent();
    
           //  wv.Source = "https://collage.exteres.com/index.php?rooftop_id=1810&seed=924&type=c&contact_id=197251&version=2.072.161&fbclid=IwAR3QEU4eIo561fAWAWtq1794NjzghaUk2mJIEb9ZPm5jTDtBOeqZOT3wa88";
          //   wv.RegisterAction(DisplayDataFromJavascript);
         }
    
    
         protected override void OnAppearing()
         {
             base.OnAppearing();
             RunTimePermission();
         }
    
         public async void RunTimePermission()
         {
             var status = PermissionStatus.Unknown;
    
    
             await CrossPermissions.Current.RequestPermissionAsync<CameraPermission>();
    
             if (status != PermissionStatus.Granted)
             {
    
                 status = await Utils.CheckPermissions(Permission.Camera);
             }
    
         }
    
     }
 }
    
      
 mainpage.xaml

 <?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:controls2="clr-namespace:webcamtest"
              x:Class="webcamtest.MainPage">
    
     <StackLayout>
         <WebView x:Name="wv" HeightRequest="1000" WidthRequest="400" Source="https://collage.exteres.com/index_debug.php?rooftop_id=1810&amp;seed=924&amp;type=c&amp;contact_id=197251&amp;version=2.072.161&amp;fbclid=IwAR3QEU4eIo561fAWAWtq1794NjzghaUk2mJIEb9ZPm5jTDtBOeqZOT3wa8"></WebView>
     </StackLayout>
    
 </ContentPage>



mainactivity.cs

 using System;
    
 using Android.App;
 using Android.Content.PM;
 using Android.Runtime;
 using Android.OS;
    
 namespace webcamtest.Droid
 {
     [Activity(Label = "webcamtest", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
     public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
     {
         protected override void OnCreate(Bundle savedInstanceState)
         {
             base.OnCreate(savedInstanceState);
    
             Xamarin.Essentials.Platform.Init(this, savedInstanceState);
             global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
             global::Android.Webkit.WebView.SetWebContentsDebuggingEnabled(true);
             Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this, savedInstanceState);
             LoadApplication(new App());
         }
         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);
         }
     }
 }


We will get the gallery on the button click, but not the camera.

Any idea?

Rick

dotnet-xamarin
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

camera not showing in webview on the andriod ... We will get the gallery on the button click, but not the camera

Hi, rickruhl. How did you open the camera? Did you use a custom WebView to achieve that? Could you please post the related code about the function code and the button's click event?

If you want to choose a picture in WebView, try to customize the WebChromeClient class to override the OnShowFileChooser method to achieve the function. You could refer to the below related case for the detailed code:
https://docs.microsoft.com/answers/answers/201652/view.html

0 Votes 0 ·

this is what we use to call it. does it look right?


<body>
<input type='file' name='images[]' multiple accept="image/*" capture='camera' />
</body>

0 Votes 0 ·

1 Answer

JarvanZhang-MSFT avatar image
0 Votes"
JarvanZhang-MSFT answered ghamkolrehab-1784 commented

Hello,​

Welcome to our Microsoft Q&A platform!

The html is right. To select a file via the camera, we need to create a custom webView renderer to achieve the function. Here is the sample code, you could refer to:

Custom WebView class

public class CustomWebView : WebView
{
}

Custom WebViewRenderer class

[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespace CustomRenderer.Droid
{
    public class CustomWebViewRenderer : WebViewRenderer
    {
        public CustomWebViewRenderer(Context context) : base(context)
        {
        }
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement != null)
            {
                Control.SetWebChromeClient(new CustomWebChromeClient(MainActivity.Instance));
                Control.LoadUrl($"file:///android_asset/Content/{((HybridWebView)Element).Uri}");
            }
        }
    }
}

Custom WebChromeClient class

public class CustomWebChromeClient : WebChromeClient
{
    Activity mActivity = null;
    public CustomWebChromeClient(Activity activity)
    {
        mActivity = activity;
    }
    public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
    {
        MainActivity.mUploadCallbackAboveL = filePathCallback;

        //TakePhoto();
        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.imageUri = 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.imageUri);

        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 });

        MainActivity.Instance.StartActivityForResult(chooserIntent, MainActivity.PHOTO_REQUEST);
        return true;
    }
}

MainActivity class

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    public static IValueCallback mUploadCallbackAboveL;
    public static Android.Net.Uri imageUri;
    public static MainActivity Instance;
    public static int PHOTO_REQUEST = 10023;
    public static IValueCallback mUploadMessage;
    public static int FILECHOOSER_RESULTCODE = 1;

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        Instance = this;

        if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) != (int)Permission.Granted)
        {
            RequestPermissions(new string[] { Manifest.Permission.Camera }, 0);
        }
        global::Xamarin.Forms.Forms.Init(this, bundle);
        LoadApplication(new App());
    }

    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)
        {
            Android.Net.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;
            }
        }
    }
    private void onActivityResultAboveL(int requestCode, Result resultCode, Intent data)
    {
        if (requestCode != PHOTO_REQUEST || mUploadCallbackAboveL == null)
        {
            return;
        }
        Android.Net.Uri[] results = null;
        if (resultCode == Result.Ok)
        {
            results = new Android.Net.Uri[] { imageUri };
            results[0] = MainActivity.imageUri;
        }
        mUploadCallbackAboveL.OnReceiveValue(results);
        mUploadCallbackAboveL = null;
    }
}



Best Regards,

Jarvan Zhang



If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@rickruhl-4179 May I know whether your issue has been solved or not? If not, please share it in here. We can work together to figure it out.

0 Votes 0 ·

all is good ty.

0 Votes 0 ·