0

I have an app, that opens a webview to a website of mine. This website opens the rear camera to take a picture. I can get it done until there, but by default the camera selected is not the preferred one. In my Samsung S10, the camera opened is the wide angle, which is very inconvenient.

How could I select the best camera? Does anybody know a workaround?

In the desktop or mobile chrome I get the labels when executing navigator.mediaDevices.enumerateDevices() but in the webview are empty.

This is my webrtc function:

await this.stopTracksCamera();
      let idealDevideId = undefined;
      await navigator.mediaDevices.getUserMedia({ video: true }).then(async stream => {
        this.tempStream = stream;
      });
idealDevideId = await this.scanDevices();
await this.stopTracksCamera();
      await navigator.mediaDevices.getUserMedia(constraints).then(stream => {
        this.videoDom.srcObject = stream;
...

And my app webview settings:

WebView web = (WebView) findViewById(R.id.silt_web);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            web.setWebContentsDebuggingEnabled(true);
        }
        WebSettings webSettings = web.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        webSettings.setAllowFileAccessFromFileURLs(true);
        webSettings.setAllowUniversalAccessFromFileURLs(true);
        webSettings.setPluginState(WebSettings.PluginState.ON);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            webSettings.setMediaPlaybackRequiresUserGesture(false);
        }

        web.setWebViewClient(new WebViewClient());

        web.setWebChromeClient(new WebChromeClient() {
    @Override
            public void onPermissionRequest(final PermissionRequest request) {
                Log.d(TAG, "onPermissionRequest");
                MainActivity.this.runOnUiThread(new Runnable() {
                    @TargetApi(Build.VERSION_CODES.M)
                    @Override
                    public void run() {
                        Log.d(TAG, request.getOrigin().toString());
                        /*if(request.getOrigin().toString().equals("file:///")) {*/
                            Log.d(TAG, "GRANTED");
                            request.grant(request.getResources());
                        /*} else {
                            Log.d(TAG, "DENIED");
                            request.deny();
                        }*/
                    }
                });
            }
...
Marc Pérez
  • 293
  • 3
  • 9

2 Answers2

2

There is a bug report for this in chromium. https://bugs.chromium.org/p/chromium/issues/detail?id=669492

The status says - WontFix (Closed)

May be its because of privacy issues.

Karthik
  • 2,282
  • 2
  • 22
  • 23
  • 1
    Thanks! I already saw the post... :( I was asking because maybe someone found a workaround to select the best camera without knowing the label. – Marc Pérez Mar 10 '20 at 08:20
  • I don't think there are any workarounds, even it is there it will be fixed as privacy is becoming very important in these cases. – Karthik Mar 10 '20 at 09:05
  • I don't think privacy should be a concern here, I'm only trying to determine which camera of the ones I have acces should I choose. It's just info about a device... I already have access to the device. – Marc Pérez Mar 11 '20 at 13:38
0

Looks like this problem is still relevant.

As a workaround, you can get labels from MediaStreamTrack.label.

The downside is: you must obtain a stream from each device to get access to tracks. This takes some time, cameras can produce clicking sounds and motorized sensor will pop-up (if any).

Sample code:

const devices = await navigator.mediaDevices.enumerateDevices();

const newDevices = [];    
for (const device of devices) {
  let constraints;
  if (device.kind === "audioinput") {
      constraints = {audio: {deviceId: {exact: device.deviceId}}};
    } else if (device.kind === "videoinput") {
      constraints = {video: {deviceId: {exact: device.deviceId}}};
    } else {
      continue;
    }
  const stream = await navigator.mediaDevices.getUserMedia(constraints);
  const track = stream.getTracks()[0];

  newDevices.push({
    deviceId: device.deviceId,
    groupId: device.groupId,
    kind: device.kind,
    label: track.label,
    originalDevice: device
  });

  // release stream
  stream.getTracks().forEach(t => {
    t.stop();
  });
}

console.log(newDevices);

Be sure you've already granted camera and microphone permissions before running this.

P.S. Also, if you are looking just for a rear camera, not device lables, there is now a constraint for that