JodusNodus / react-qr-reader

React component for reading QR codes from webcam.
https://jodusnodus.github.io/react-qr-reader
MIT License
1.13k stars 407 forks source link

Component Does Not Prompt User For Camera Access #79

Open gregphillips03 opened 6 years ago

gregphillips03 commented 6 years ago

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 commented 6 years ago

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

davidtaboas commented 6 years ago

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

alexhochreiter commented 6 years ago

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

gregphillips03 commented 6 years ago

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 commented 6 years ago

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>
    )
  }
}
alexhochreiter commented 6 years ago

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)

brendansiow commented 6 years ago

any update on how to get access in IOS safari?

alexhochreiter commented 6 years ago

@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.

mbalesni commented 5 years ago

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

Ferigit commented 4 years ago

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

arielclement commented 7 months ago

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