locked
camera stream stop after send image by camera input file webview RRS feed

  • Question

  • User366506 posted

    i have app for video call, in app i am using webview for video call between two users. 2 users can aslo share file with each other via from gallery or camera. Now the issue i am facing when both users are in between call and one user send image from camera, the camera that is already running for video get stopped. These are errors i am getting

    07-02 14:47:06.115 I/CameraManagerGlobal( 3656): Camera 1 facing CAMERA_FACING_FRONT state now CAMERA_STATE_IDLE for client com.kihmobile.kih API Level 2
    07-02 14:47:06.175 I/CameraManagerGlobal( 3656): Camera 1 facing CAMERA_FACING_FRONT state now CAMERA_STATE_CLOSED for client com.kihmobile.kih API Level 2
    07-02 14:47:06.182 E/CameraCaptureSession( 3656): Session 0: Exception while stopping repeating: 
    07-02 14:47:06.182 E/CameraCaptureSession( 3656): android.hardware.camera2.CameraAccessException: CAMERA_DISCONNECTED (2): cancelRequest:473: Camera device no longer alive
    07-02 14:47:06.182 E/CameraCaptureSession( 3656):   at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:1127)
    07-02 14:47:06.182 E/CameraCaptureSession( 3656):   at android.hardware.camera2.impl.ICameraDeviceUserWrapper.cancelRequest(ICameraDeviceUserWrapper.java:97)
    07-02 14:47:06.182 E/CameraCaptureSession( 3656):   at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:1151)
    07-02 14:47:06.182 E/CameraCaptureSession( 3656):   at android.hardware.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:526)
    07-02 14:47:06.182 E/CameraCaptureSession( 3656):   at 
    

    android.hardware.camera2.impl.CameraCaptureSessionImpl$2.onDisconnected(CameraCaptureSessionImpl.java:737)

    this is my webview code in xamarin

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Android.Annotation;
    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Provider;
    using Android.Runtime;
    using Android.Support.V4.Content;
    using Android.Views;
    using Android.Webkit;
    using Android.Widget;
    using Java.Interop;
    using Java.IO;
    using OnlineKIHStore.Droid;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    [assembly: ExportRenderer(typeof(OnlineKIHStore.MyWebView), typeof(MyWebViewRenderer))]
    
    namespace OnlineKIHStore.Droid
    {
        public class MyWebViewRenderer : WebViewRenderer
        {
            MainActivity mContext;
            public MyWebViewRenderer(Context context) : base(context)
            {
                this.mContext = context as MainActivity;
            }
            protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
            {
                base.OnElementChanged(e);
    
                var oldWebView = e.OldElement as MyWebView;
                if (oldWebView != null)
                    oldWebView.EvaluateJavascript = null;
    
                var newWebView = e.NewElement as MyWebView;
                if (newWebView != null)
                    newWebView.EvaluateJavascript = async (js) =>
                    {
    
                        ManualResetEvent reset = new ManualResetEvent(false);
                        var response = "";
                        Device.BeginInvokeOnMainThread(() =>
                        {
                           // System.Diagnostics.Debug.WriteLine("Javascript Send: " + js);
    
                            Control?.EvaluateJavascript(js, new JavascriptCallback((r) => { response = r; reset.Set(); }));
    
                        });
                        await Task.Run(() => { reset.WaitOne(); });
                        if (response == "null")
                            response = string.Empty;
    
                        return response;
                    };
    
                if (Control != null && e.NewElement != null)
                {
                    InitializeCommands((MyWebView)e.NewElement);
                    //SetupControl();
                }
                Control.Settings.JavaScriptEnabled = true;
                Control.Settings.MediaPlaybackRequiresUserGesture = false;
                Control.ClearCache(true);
                Control.SetWebViewClient(new WebViewClientAuthentication());
                Control.SetWebChromeClient(new MyWebClient(mContext));
                Control.Settings.DomStorageEnabled = true;
                Control.Settings.AllowUniversalAccessFromFileURLs = true;
                Control.Settings.AllowFileAccess = true;
                global::Android.Webkit.WebView.SetWebContentsDebuggingEnabled(true);
    
    
    
    
    
    
    
            }
            private void InitializeCommands(MyWebView element)
            {
    
                element.RefreshCommand = new Command(() =>
                {
                    Control?.Reload();
                });
    
                element.GoBackCommand = new Command(() =>
                {
                    var ctrl = Control;
                    if (ctrl == null)
                        return;
    
                    if (ctrl.CanGoBack())
                        ctrl.GoBack();
                });
    
                element.CanGoBackFunction = () =>
                {
                    var ctrl = Control;
                    if (ctrl == null)
                        return false;
    
                    return ctrl.CanGoBack();
                };
    
                // This allows you to show a file chooser dialog from the WebView
    
            }
            public class WebViewClientAuthentication : WebViewClient
            {
                public override void OnReceivedSslError(Android.Webkit.WebView view, SslErrorHandler handler, Android.Net.Http.SslError error)
                {
                    handler.Proceed();
                }
            }
    
            public class MyWebClient : WebChromeClient
            {
                private static int filechooser = 1;
                private IValueCallback message;
                MainActivity mContext;
                private static int cameraCode=11;
    
                public static Android.Net.Uri myImageUri { get; private set; }
    
                public MyWebClient(MainActivity context)
                {
                    this.mContext = context;
                }
                private Android.Net.Uri getFileUri()
                {
                    Android.Net.Uri imageUri = null;
                    string path = getFilePath();
                    File file = new File(path);
                    if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
                    {
                        try
                        {
                            imageUri = FileProvider.GetUriForFile(this.mContext, $"{mContext.ApplicationInfo.PackageName}.fileprovider", file);
                        }
                        catch (Exception e)
                        {
    
                        }
    
                    }
                    else
                    {
                        imageUri = Android.Net.Uri.FromFile(file);
                    }
                    return imageUri;
                }
    
                private string getFilePath()
                {
                    File externalDataDir = Android.OS.Environment
                            .GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim);
                    File cameraDataDir = new File(externalDataDir.AbsolutePath
                            + File.Separator + "Images");
                    cameraDataDir.Mkdirs();
                    string mCameraFilePath = cameraDataDir.AbsolutePath
                            + File.Separator + "send_new_image.jpg";
    
                    return mCameraFilePath;
                }
                [Export]
                [JavascriptInterface]
                private Intent createCameraIntent()
                {
                    Intent cameraIntent = new Intent(MediaStore.ActionImageCapture);
    
                    //Intent cameraIntent = new Intent(MediaStore.ActionImageCapture);
                   myImageUri = getFileUri();
                    //cameraIntent.PutExtra(MediaStore.Images.Media.InterfaceConsts.Orientation, 0);
                    //cameraIntent.PutExtra(MediaStore.ExtraOutput, myImageUri);
                    return cameraIntent;
                }
                public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
    
                {
                    //    AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this.mContext);
    
                    //    using (dialogBuilder = new AlertDialog.Builder(this.mContext))
                    //    {
                    //        dialogBuilder.SetTitle("Upload Image");
                    //        dialogBuilder.SetPositiveButton("Choose from Library", delegate
                    //        {
                    //            Intent chooserIntent = fileChooserParams.CreateIntent();
                    //            chooserIntent.SetType("image/*");
                    //            this.mContext.StartActivity(Intent.CreateChooser(chooserIntent, "Select Picture"), 1, OnActivityResult);
                    //        }
    
                    //        dialogBuilder.SetNegativeButton("Cancel", delegate
                    //        {
                    //            dialogBuilder.Dispose();
                    //        });
                    //    }
                    AlertDialog.Builder alertDiag = new AlertDialog.Builder(this.mContext);
                    alertDiag.SetTitle("Confirm delete");
                    alertDiag.SetCancelable(false);
                    alertDiag.SetMessage("Once deleted the move cannot be undone");
                    alertDiag.SetPositiveButton("Gallery", (senderAlert, args) =>
                    {
                        this.message = filePathCallback;
                        Intent chooserIntent = fileChooserParams.CreateIntent();
                        chooserIntent.AddCategory(Intent.CategoryOpenable);
    
                        this.mContext.StartActivity(Intent.CreateChooser(chooserIntent, "File Chooser"), filechooser, this.OnActivityResult);
    
    
                    });
                    alertDiag.SetNegativeButton("Camera", (senderAlert, args) =>
                    {
                        this.message = filePathCallback;
                        mContext.StartActivity(createCameraIntent(), cameraCode, this.OnActivityResult);
    
                    });
                    Dialog diag = alertDiag.Create();
                    diag.Show();
    
    
    
                    //this.message = filePathCallback;
                    //Intent chooserIntent = fileChooserParams.CreateIntent();
                    //chooserIntent.AddCategory(Intent.CategoryOpenable);
    
                    //this.mContext.StartActivity(Intent.CreateChooser(chooserIntent, "File Chooser"), filechooser, this.OnActivityResult);
                    return true;
                }
                private void OnActivityResult(int requestCode, Result resultCode, Intent data)
                {
    
                    if (resultCode != Android.App.Result.Ok)
                    {
                        this.message.OnReceiveValue(null);
    
                        return;
                    }
                    //if (data != null)
                    //{
                        if (requestCode == MyWebClient.cameraCode)
                        {
                            if (null == this.message)
                            {
                                return;
                            }
    
                            try
                            {
                                Android.Net.Uri[] uris = new Android.Net.Uri[1];
                                uris[0] = MyWebClient.myImageUri;
                                this.message.OnReceiveValue(uris);
                            }
                            catch (Exception ex)
                            {
    
                                throw ex;
                            }
                            this.message = null;
                        }
    
                       else if (requestCode == filechooser)
                        {
                            if (null == this.message)
                            {
                                return;
                            }
    
                            try
                            {
                                this.message.OnReceiveValue(WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
    
                            }
                            catch (Exception)
                            {
    
                                throw;
                            }
                            this.message = null;
                        }
                    //}
                }
                [TargetApi(Value = 21)]
                public override void OnPermissionRequest(PermissionRequest request)
                {
    
                    mContext.RunOnUiThread(() =>
                    {
                        request.Grant(request.GetResources());
    
                    });
    
                }
            }
            internal class JavascriptCallback : Java.Lang.Object, IValueCallback
            {
                public JavascriptCallback(Action<string> callback)
                {
                    _callback = callback;
                }
    
                private Action<string> _callback;
                public void OnReceiveValue(Java.Lang.Object value)
                {
                    //System.Diagnostics.Debug.WriteLine("Javascript Return: " + Convert.ToString(value));
                    _callback?.Invoke(Convert.ToString(value));
                }
            }
    
        }
    }
    

    i just want to know how i can resume camera in video call after user send image from camera using input file...?

    here are some picture how app looks like this is running video call between two users and both users camera are open

    android user where he can chat and send file via gallery or camera

    now here when android user click on camera, camera does open to capture image, but camera that is already running for video call get stop

    Thursday, July 2, 2020 10:11 AM

All replies

  • User382871 posted

    The video call and taking photos use the same flash component. When opening the camera, the video call will be closed automatically. The two functions couldn't be used at the same.

    You could detect the sharing the photo method to recall each other. But it'll better to make the taking photo button disabled when the video call is working.

    Thursday, July 2, 2020 3:44 PM
  • User366506 posted

    but when i run this on google chrom and share file via camera video call doesnt stop

    Thursday, July 2, 2020 4:04 PM
  • User382871 posted

    android.hardware.camera2.impl.CameraCaptureSessionImpl$2.onDisconnected The related link about the error, hope it'll help you. https://stackoverflow.com/questions/40353706/lacking-privileges-to-access-camera-service-in-android-6-0

    Friday, July 3, 2020 2:57 PM