2

I have created a webview app, where I scan QR Code. Everything works fine on mobile and desktop browser, but in the app I get Unable to access video stream (please make sure you have a webcam enabled).

I am sharing some of the Code below :

Here is the HTML which I am using to scan QR Code :

<div id="loadingMessage">
       Unable to access video stream (please make sure you have a webcam enabled)
</div>
<canvas id="canvas" hidden></canvas>
<div id="output" style="padding-right: 35px;padding-left: 35px;width: fit-content;">
  <div><b> QR Code Data:</b> <span id="outputData"></span></div>
</div>

And the JS :

<script>

var video = document.createElement("video");
var canvasElement = document.getElementById("canvas");
var canvas = canvasElement.getContext("2d");
var loadingMessage = document.getElementById("loadingMessage");
var outputContainer = document.getElementById("output");
var outputData = document.getElementById("outputData");

function drawLine(begin, end, color) {
    canvas.beginPath();
    canvas.moveTo(begin.x, begin.y);
    canvas.lineTo(end.x, end.y);
    canvas.lineWidth = 4;
    canvas.strokeStyle = color;
    canvas.stroke();
}

navigator.mediaDevices.getUserMedia({ video: { facingMode: "user" } }).then(function (stream) {
    video.srcObject = stream;
    video.setAttribute("playsinline", true); 
    video.play();
    requestAnimationFrame(tick);
});

function tick() {
    loadingMessage.innerText = "⌛ Loading video..."
    if (video.readyState === video.HAVE_ENOUGH_DATA) {
        loadingMessage.hidden = true;
        canvasElement.hidden = false;
        outputContainer.hidden = false;

        canvasElement.height = video.videoHeight;
        canvasElement.width = video.videoWidth;
        canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
        var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
        var code = jsQR(imageData.data, imageData.width, imageData.height, {
            inversionAttempts: "dontInvert",
        });
        if (code) {
            drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
            drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
            drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
            drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
            outputData.innerText = code.data;
        }
    }
    requestAnimationFrame(tick);
}

</script>

I am also asking permission to grant Camera Access at Runtime in MainActivity.cs.

Here is the code related to Permission in Xamarin Webview :

class MyWebClient : WebChromeClient
{
    Activity mContext;

    
    public MyWebClient(Activity context)
    {
        this.mContext = context;
    }
    public override void OnPermissionRequest(PermissionRequest request)
    {
        mContext.RunOnUiThread(() => {
            request.Grant(request.GetResources());
        });
    }
}

I have also used the following permissions in Manifest file :

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

I also tried the solution suggested here and here but it didn't work for me.

S M
  • 111
  • 11
  • I hope you get some help - I have the same problem :) – Tony Basallo Dec 30 '20 at 03:17
  • 1
    Have a look at the answer [in this thread](https://stackoverflow.com/questions/59771557/xamarin-requesting-camera-permissions-in-webview) may help. – nevermore Dec 30 '20 at 08:07
  • Thanks @JackHua-MSFT. I did create a Utils.cs file as suggested in the answer. And it did work. But it works occasionally. Out of the 5 times I tested, it worked only 2 times. For the rest 3 I got the same "Unable to acces...." message. – S M Dec 31 '20 at 06:29
  • Did the permission alert show every time? It should work if it work once. – nevermore Dec 31 '20 at 07:41
  • It was differing from device to device. I tested it on devices of different brands Like Samsung, One Plus, MI, VIVO, Motorola, etc. What I observed that it worked fine on MI,VIVO and Motorola. But it didn't on Samsung and One Plus. – S M Jan 06 '21 at 05:53
  • Is there any system permission in the setting need to set in those devices? The codes should be fine. – nevermore Jan 07 '21 at 07:49

1 Answers1

0

Adding MediaPlaybackRequiresUserGesture = false is what did it for me (testing with webrtc). Try it out. I added a portion of my renderer. LMK if you need it all.

 protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
    {
        base.OnElementChanged(e);
        Control.Settings.JavaScriptEnabled = true;
        Control.Settings.MediaPlaybackRequiresUserGesture = false;
        Control.ClearCache(true);
        Control.SetWebChromeClient(new MyWebClient(mContext));
    }
Tony Basallo
  • 3,000
  • 2
  • 29
  • 47
  • Thank You very much for the reply. But I have already added the MediaPlaybackRequiresUserGesture = false in my renderer. Its still not working though. – S M Dec 30 '20 at 05:26