react-qr-reader icon indicating copy to clipboard operation
react-qr-reader copied to clipboard

Component Does Not Prompt User For Camera Access

Open gregphillips03 opened this issue 6 years ago • 11 comments

I don't see a trigger to prompt the user to allow access to the camera. Is this handled by react-qr-reader itself, or externally?

The reader will render without an issue, but the stream to the input device never fires off, nor is the user asked if they would like to allow the site to access it.

gregphillips03 avatar Jun 17 '18 04:06 gregphillips03

I've tried this using: Google Chrome: Version 64.0.3282.119 (Official Build) (64-bit), on Windows 7 Google Chrome 67.03396.87 on Android 8.0.0; SM-G965U Build/R16NW Chromium 66.0.3359.181 on Ubuntu, running 18.04 (64-bit)

This is what occurs:

capture

gregphillips03 avatar Jun 17 '18 04:06 gregphillips03

@JodusNodus I have the same issue both Safari Browser (iOS) and a PWA.

davidtaboas avatar Jun 26 '18 11:06 davidtaboas

I just tried the demo with Chrome on Fedora 28 where it worked as expected. On the other side, it does not work on my MacBook Pro as it seems that OSX disables the internal webcam once the lid is closed (surprise!). This simple snippet clarified for me that it was not this lib's fault at all.

navigator.getUserMedia({ video: true, audio: true }, () => console.log('ok'), err => console.error(err))

@davidtaboas AFAIK iOS does not support getUserMedia() even though caniuse states otherwise. I will try to confirm this however, once my test iphone charged a bit. EDIT: Just could confirm it on iOS 10.3.3 EDIT2: https://test.webrtc.org/ is also dead on iOS

alexhochreiter avatar Jun 27 '18 23:06 alexhochreiter

I did a bit more digging into this an found part of the issue. Looks like a HTTPS connection is expected by something running underneath. When in development, you need to explicitly set the HTTPS environment variable (or actually create and export it if it doesn't already exist). This solved the issue when using:

Google Chrome: Version 64.0.3282.119 (Official Build) (64-bit), on Windows 7

But didn't affect the app running mobile on:

Google Chrome 67.03396.87 on Android 8.0.0; SM-G965U Build/R16NW

I can see Chrome accessing the camera via a notification in the OS, but the video stream never propagates.

gregphillips03 avatar Jun 28 '18 18:06 gregphillips03

When rendered, this code works in Google Chrome: Version 64.0.3282.119 (Official Build) (64-bit), on Windows 7, but not on my Android:

import React, { Component } from 'react'
import QrReader from 'react-qr-reader'

export default class Test extends Component {
  constructor(props){
    super(props)
    this.state = {
      delay: 300,
      result: 'No result',
    }
    this.handleScan = this.handleScan.bind(this)
  }

  componentDidMount()
  {
    if(navigator.getUserMedia){
      navigator.getUserMedia(
      {
        video: true
      }, 
      function(localMediaStream){}, 
      function(err){
        alert('The following error occurred when trying to access the camera: ' + err); 
      }
    );
    } else {
      alert('Sorry, browser does not support camera access');
    }
  }

  handleScan(data)
  {
    if(data){
      this.setState({
        result: data,
      })
    }
  }

  handleError(err)
  {
    console.error(err)
  }

  render()
  {
    return(
      <div>
        <QrReader
          delay={this.state.delay}
          onError={this.handleError}
          onScan={this.handleScan}
          style={{ width: '100%' }}
          ref={(stream)=> {this.videoStream = stream}}
          />
        <p>{this.state.result}</p>
      </div>
    )
  }
}

gregphillips03 avatar Jun 28 '18 18:06 gregphillips03

Just tested the demo on Google Chrome 67.0.3396.87 on Android 6.0 and Android 8.1.0 (real devices, not simulated) - worked as expected. I can only remember it very blurry, but i think you have to release the localMediaStream that you received in your componentDidMount method somehow, or this lib wont be able to fetch the stream, as there can only be one instance of a stream from a device at the same time. Probably something like: localMediaStream.getTracks()[0].stop() (but that's just copy pasted from some stackoverflow answer)

alexhochreiter avatar Jun 29 '18 19:06 alexhochreiter

any update on how to get access in IOS safari?

brendansiow avatar Jun 30 '18 03:06 brendansiow

@walaoehh It's actually pretty easy. The solution lies in the nature of Apple's way to implement things: Don't, unless it makes people pay. So to use it, you gotta pay Apple 100$/year and end up making a native app (something like WebRTC for React-Native). Thanks Apple.

alexhochreiter avatar Jul 01 '18 05:07 alexhochreiter

@walaoehh Works for me on Safari, iOS 12.1.1. Doesn't work in Chrome, as expected.

mbalesni avatar Jan 01 '19 23:01 mbalesni

it works on safari and chrome browser but does not work on add to home mode, does anybody have got this propblem?!

Ferigit avatar Jan 05 '20 07:01 Ferigit

I tested it on my android device and unfortunately the problem still remains, any update from the maintainer about this perhaps?

arielclement avatar Feb 06 '24 02:02 arielclement