6

I have a webview in my Android app. From the webview, I am able to access default camera on the phone. The following code works fine.

webview.setWebChromeClient(new WebChromeClient(){
    // Need to accept permissions to use the camera
    @Override
    public void onPermissionRequest(final PermissionRequest request) {
        L.d("onPermissionRequest");
        request.grant(request.getResources());
    }
});

My issue is to access an external USB camera from this webview. Above permission opens up the default camera in the webview.

I haven't been able to find any documentation which even says this thing is possible. Is it because of some security issue ?

Vikas
  • 3,935
  • 1
  • 30
  • 37
  • voted to close this (but not my down-vote), because it's too broad and probably does not have an actual relation to a `WebView`. see the documentation: https://developer.android.com/reference/android/hardware/usb/UsbConstants.html#USB_CLASS_VIDEO – Martin Zeitler Aug 30 '18 at 09:03
  • I am just asking if its possible or not. – Vikas Sep 05 '18 at 11:14
  • @Vikas see my answer it's clear your doubts. – InsaneCat Sep 05 '18 at 11:20
  • Or the external camera is picked up by Android and you just need to specify which camera to use. https://stackoverflow.com/a/42399845/2444099 https://www.html5rocks.com/en/tutorials/getusermedia/intro/ – Eugen Pechanec Sep 06 '18 at 19:24
  • 1
    Try to access the camera from a regular view/activity, and, if possible, create an intent for said activity that you can call from the webview. – Fco P. Sep 10 '18 at 19:54
  • 1
    The above commend sounds for me what you are searching for. I think your problem needs to be solved natively (in android) and provided by some kind of intent. Frameworks like React-Native get 100% onto the native system by interpreting JavaScript directly. Maybe you can look into the code base an find some way how to 'copy' the communication layer between native and webview. – Jonathan Stellwag Sep 11 '18 at 20:16

1 Answers1

2

You may have an issue with the USB camera driver and the camera selection rather than with permissions.

  1. USB Camera Drivers

The first step is to make sure that your USB camera is being detected and is working on your device. You didn't indicate whether you had confirmed this or not. My understanding is that android.hardware.camera2 support for USB cameras is still rather poor. If your camera is supported then hopefully it will enumerate along with the rest of the cameras. In my test with Android 8.1.0 the USB camera I attached was not enumerated with CameraManager, while it was with the library below.

The USB Camera library https://github.com/saki4510t/UVCCamera is frequently used to provide broader support for USB cameras, but from my limited experience with the library it writes to a TextureView and so will probably not play nicely with WebRTC in a WebView. In a very cursory investigation I did not see WebView hooks that would support connecting an external video source.

  1. Camera Selection

You mentioned that your test always used the default camera so it sounds like you might not be actively enumerating and selecting the target camera. WebRTC camera selection can be performed in Javascript using the navigator.mediaDevices interface. For example,

function chooseDevice(videoInDevices) {
    // return selected device
}

// Filter devices so we only consider video sources
function filterForVideoInputs(devices) {
    return devices.filter(d => d.kind === 'videoinput');
}

// Simply pull out deviceId from selected device struct
function getDeviceId(deviceInfo) {
    return deviceInfo.deviceId;
}

// Request video stream from selected deviceId
function requestDevice(deviceId) {
    return navigator.mediaDevices.getUserMedia({
        video: {
            deviceId: {
                exact: deviceId
            }
        }
    });
}

// Connect stream from getUserMedia to HTML5 video element
function startStream(stream) {
    let video = document.querySelector('video');
    video.srcObject = stream;
    video.onloadedmetadata = function () {
        video.play();
    }
}

navigator.mediaDevices.enumerateDevices()
    .then(filterForVideoInputs)
    .then(chooseDevice)
    .then(getDeviceId)
    .then(requestDevice)
    .then(startStream)
    .catch(err => console.log(err));

Since your permissions were sufficient for the internal camera, they should as far as I understand also be sufficient for a USB camera.

Note, as you may know, the documentation has a warning about not blinding granting Webkit permission. When you move toward production remember to replace

request.grant(request.getResources())

perhaps with something more like this

if (isRequestOriginOrWhateverApproved(request)) {
    request.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE});
}
user650881
  • 1,832
  • 17
  • 23
  • This is not the full story! There's actually an issue with Webview + USB (External Camera API) in Android 9+ on some devices. This is what I have inferred and since it is a fairly new problem and an uncommon one, along with it being pretty complicated to solve I haven't come across any solution. I am reviewing Chromium source. On our device we have a `CSI` camera and a USB Hub for other devices. The same Webview code that works for CSI camera (Internal) is not working for USB Cameras (External). We believe it's a problem with access permissions in the linux or system side. – BLH Apr 01 '21 at 21:55
  • Here's a link to check how to implement USB camera (external) in Android 9+ https://groups.google.com/g/android-platform/c/Qx1P0I17uzs At the bottom of the discussion I explain all the information I have – BLH Apr 01 '21 at 21:55