angular2-qrscanner icon indicating copy to clipboard operation
angular2-qrscanner copied to clipboard

Selecting back camera on iOS and Chrome/Android does not work

Open DavyDeDurpel opened this issue 6 years ago • 5 comments

The current logic to switch camera's on mobile devices works very well for Android but not for iOS. The reason is that Safari only supports the 'new' way of switching camera's on mobile devices.

I have a nice workaround that works with this library. Below is an example way of selecting another camera. The magic is inside the facingMode constraint. 'setStream' is private in the library so I'm casting to to circumvent this restriction. Sorry for this hack ;-)

I guess it would be fairly easy to integrate this logic into this library.

changeDevice(event: MatSelectChange) {
    const device = this.availableVideoDevices.filter(device => device.deviceId === event.value)[0];
    if (navigator.platform && (navigator.platform.toLowerCase().includes('ipad') || navigator.platform.toLowerCase().includes('iphone'))) {
      if (device.label.toLowerCase().includes('back')) {
        navigator.mediaDevices.getUserMedia({ audio: false, video: { facingMode: { exact: "environment" } } }).then(stream => {
          (<any>this.qrScannerComponent).setStream(stream);
        });
      } else {
        navigator.mediaDevices.getUserMedia({ audio: false, video: { facingMode: "user" }}).then(stream => {
          (<any>this.qrScannerComponent).setStream(stream);
        });
      }
    } else {
      this.qrScannerComponent.chooseCamera.next(device);
    }

DavyDeDurpel avatar Sep 26 '18 11:09 DavyDeDurpel

I had a hell of time to figure out how to enable the back camera by default in Chrome on Android. The problem is that you need to request permissions, but by default Chrome only gives permission for the front camera.

The solution is very easy but you got to know it...

This is what works:

navigator.mediaDevices.getUserMedia({ audio: true, video: { facingMode: "environment" }}).then(value => {
this.qrScannerComponent.chooseCamera.next(<the MediaDeviceInfo of your back camera>);
}

Switching to front camera afterwords will still work though.

DavyDeDurpel avatar Sep 28 '18 07:09 DavyDeDurpel

I found out why on iPhone I still get a black screen. You will need to add following when creating the video element: videoElement.setAttribute('playsinline', 'true')

It's only need for iPhone but other devices will just ignore the attribute

DavyDeDurpel avatar Sep 28 '18 10:09 DavyDeDurpel

I found out why on iPhone I still get a black screen. You will need to add following when creating the video element: videoElement.setAttribute('playsinline', 'true')

It's only need for iPhone but other devices will just ignore the attribute

Hello! I'm using the example from the readme and I also got the black screen on iOS. Could you please explain me where I need to add the setAttribute? Thanks a lot!

sboeyen avatar Oct 26 '18 16:10 sboeyen

Something like this inside your component should work:

@ViewChild(QrScannerComponent) qrScannerComponent: QrScannerComponent;

ngOnInit() {
  this.qrScannerComponent.videoElement.setAttribute('playsinline', 'true');
}

DavyDeDurpel avatar Oct 29 '18 04:10 DavyDeDurpel

I am trying this also, I am able to set default camera as back. It only works when I use front camera. Its really not usable in front cam.

iamsank8 avatar Dec 11 '19 11:12 iamsank8