mebjas / html5-qrcode

A cross platform HTML5 QR code reader. See end to end implementation at: https://scanapp.org
https://qrcode.minhazav.dev
Apache License 2.0
5.09k stars 978 forks source link

Problem with electron #79

Closed Laure444 closed 4 years ago

Laure444 commented 4 years ago

Hello, I'm making an app with electron. I would like to use QR code to allow the user to go to the next step. I’m currently on my PC but the application is supposed to be a .exe on a Windows tablet.

Here is a simplified version of my code :

<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0,user-scalable=yes">
  <title>MyApp</title>
</head>
<body body>
  <div id="QRCode" style="width: 50%;">
    <div style="width: 90%," id="reader"></div>
  </div>
  <script src="app.js"></script>
  <script src="../html5-qrcode-1.1.0/minified/html5-qrcode.min.js"></script>
  <script>
    function onScanSuccess(qrCodeMessage) {
      // handle on success condition with the decoded message
    }
    var html5QrcodeScanner = new Html5QrcodeScanner(
      "reader", { fps: 10, qrbox: 250 });
    html5QrcodeScanner.render(onScanSuccess);
  </script>
</body>
</html>

The app is launched by main.js :

const electron = require('electron')
const app = electron.app
const BrowserWindow = electron.BrowserWindow
let mainWindow
function createWindow () {
  mainWindow = new BrowserWindow({fullscreen: true})
  mainWindow.loadURL(`file://${__dirname}/src/exemple.html`) 
  mainWindow.on('closed', function () {
    mainWindow = null
  })
}
app.on('ready', createWindow)
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
app.on('activate', function () {
  if (mainWindow === null) {
    createWindow()
  }
})

When I Launch this app (If you install electron and the program of mebjas this should work as well) I got this : image It's what I want yay ! If I chose to use a file, everythings work : image image But if I chose "request camera permission it kind of work but the camera don't appear and I have an error when I click on "Stop Scanning" : image It tell me TypeError: g._element.append is not a function But the webcam is on (I mean the light on the webcam is on) If I put line 1761 (g._element.append(d),) in commentary (//) I have : image And in the console : image If I do the same with line 1732 (j.append(k),) I just have the message "[Html5Qrcode] config.qrboxsize is greater than video height. Shading will be ignored" But in the corner I now have "scanning" image I know putting in commentary isn't a solution but I tried, just in case ^^'

When I try the example on the website It works without any problems, so I don't think the problem come from my webcam.

But I wonder if the problem could come from the fact that I don't use a browser or if it's because of electron (but I'm not sure how it could impact this) Thanks to anybody how take the time to thinks about my problem :)

mebjas commented 4 years ago

@Laure444 That's interesting - I tested your code and it seems to work for me. One thing I'd suggest is trying out the latest code - v1.1.7 as it looks you are using older v1.1.0.

image

However, please note that I tested this on Mac, and had to grant the permissions. I am not super sure about windows but can you test and get back?

Laure444 commented 4 years ago

Okay, thanks for your answer I downloaded the file html5-qrcode-1.1..7.zip and I extracted it in my project I changed my html code for :

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0,user-scalable=yes">
  <title>MyApp</title>
</head>

<body>
  <div style="width: 500px" id="reader"></div>
  <script src="../html5-qrcode-1.1.7/minified/html5-qrcode.min.js"></script>
  <script>
    function onScanSuccess(qrCodeMessage) {
      // handle on success condition with the decoded message
    }
    var html5QrcodeScanner = new Html5QrcodeScanner(
      "reader", { fps: 10, qrbox: 250 });
    html5QrcodeScanner.render(onScanSuccess);
  </script>
</body>

But I still get the same error :'( I tried downloading only html5-qrcode.min.js and changing my code with : <script src="./html5-qrcode.min.js"></script> But I get the same problem same with : <script src="https://github.com/mebjas/html5-qrcode/releases/download/V1.1.7/html5-qrcode.min.js"></script>

I tried to use the not minified version by using : <script src="../html5-qrcode-1.1.7/html5-qrcode.js"></script> But now I have in the program console : image I don't know what to do about that ^^'

I tried making this a .exe with electron-packager but I still have the same message. Do you think it is because I'm on windows ? If that's the case why the program on your website work for me ? What else can I try ? Thanks for your time

Edit : I just noticed that it never ask me for the permission should I also have one ? On the website it asks ... But if I refuse to grant the permission to the website, the error message is different. When I go in my computer's parameters I can see that my application is allowed to use te webcam, so I'm not sure the problem come from here

mebjas commented 4 years ago

I tried to use the not minified version by using :

But now I have in the program console :

I don't know what to do about that ^^'

This is because the non minified version is based on ECMA and not all JS framework supports that, I assume electron doesn't. You should continue to use minified version.

On further digging it looks like you might want to look into systemPreferences.getMediaAccessStatus(mediaType) - https://www.electronjs.org/docs/api/system-preferences#systempreferencesgetmediaaccessstatusmediatype-windows-macos

This user consent was not required on macOS 10.13 High Sierra or lower so this method will always return granted. macOS 10.14 Mojave or higher requires consent for microphone and camera access. macOS 10.15 Catalina or higher requires consent for screen access.

Windows 10 has a global setting controlling microphone and camera access for all win32 applications. It will always return granted for screen and for all media types on older versions of Windows.

This might also be relevant: https://github.com/electron/electron/issues/12010, can you share which version of electron are you using?

Laure444 commented 4 years ago

Thanks I will look into that, I use electron 1.4.13 maybe it's a bit too old ...

Laure444 commented 4 years ago

I recived the tablet and it still say the same messsage Iupdated electron to v9.1.2 but I still get the same error Do you have an idea of where the problem could come ?

Laure444 commented 4 years ago

Hello, I have find this module That allow me to use camera. It is working And I was wondering if there would be a way to replace the camera of your code by this one ? I did npm install webcamjs --save And I added in my html :

      <div id="camdemo" style="width: 320px; height: 240px; text-align: center; margin: 0 auto;"></div>
      <br>
      <div style="text-align:center;">
        <input type="button" id="start" value="Start / Shut down camera" />
      </div>

And in my js :

// A flag to know when start or stop the camera
var enabled = false;
// Use require to add webcamjs
var WebCamera = require("webcamjs");
document.getElementById("start").addEventListener('click',function(){
   if(!enabled){ // Start the camera !
     enabled = true;
     WebCamera.attach('#camdemo');
     console.log("The camera has been started");
   }else{ // Disable the camera !
     enabled = false;
     WebCamera.reset();
    console.log("The camera has been disabled");
   }
},false);

Is there a way to replace the camera of your code by this one ?

DO I have to do npm install somethings ?

mebjas commented 4 years ago

@Laure444 It'd wouldn't be straight forward to integrate WebcamJs into this library. However, if the WebcamJs is able to work on Windows + Electron then something must be missing in this library code that is preventing it from running. I'll do further investigations.

mebjas commented 4 years ago

Can you run following code and see if you get something in the console

navigator.mediaDevices.getUserMedia(
    { audio: false, video: true })
    .then(stream => {
        navigator.mediaDevices.enumerateDevices()
            .then(devices => {
                console.log("devices found success", devices);
            })
            .catch(error => {
                console.log("devices found error", error);
            });
    })
    .catch(error => {
        console.log("getUserMedia error", error);
    });

If this gives error can you try with this as well

navigator.mediaDevices.webkitGetUserMedia(
    { audio: false, video: true })
    .then(stream => {
        navigator.mediaDevices.enumerateDevices()
            .then(devices => {
                console.log("devices found success", devices);
            })
            .catch(error => {
                console.log("devices found error", error);
            });
    })
    .catch(error => {
        console.log("getUserMedia error", error);
    });

I do not have a windows system with me to try this out.

Laure444 commented 4 years ago

Thanks :) I tested your first code by puting it in my html :

<body>
   <div style="width: 500px" id="reader"></div>
   <script src="./html5-qrcode.min.js"></script>
   <script>
    function onScanSuccess(qrCodeMessage) {
      // handle on success condition with the decoded message
    }
    var html5QrcodeScanner = new Html5QrcodeScanner("reader", { fps: 10, qrbox: 250 });
    html5QrcodeScanner.render(onScanSuccess);

    navigator.mediaDevices.getUserMedia(
      { audio: false, video: true })
      .then(stream => {
          navigator.mediaDevices.enumerateDevices()
          .then(devices => {
            console.log("devices found success", devices);
          })
          .catch(error => {
            console.log("devices found error", error);
          });
      })
      .catch(error => {
        console.log("getUserMedia error", error);
      });
  </script>
</body>

And it work, I get in the console :

image I think this video input is the one we're looking for ?

Just in case that might be usful I tried the second code and I get that in the console : image There are lot of informations given but I'm unsuse to understand what we're looking for ? image There are a few place where there is : Exception: TypeError: Illegal invocation at MediaDeviceInfo.remoteFunction (<anonymous>:3:14) I couldn't find on the web what could be this remoteFunction but with such a name, I would understant it have a problem with groupId, but why deviceId ? I don't think this have a link with my problem but it makes me a bit curious ^^ Did this informations gave you an idea of what is wrong ? Thanks for your time :)

Laure444 commented 4 years ago

Hello, I was wondering if there is a way to make the "chose a file" the default selected option ? With this I would have to open the camera application to take a picture and then put it here. It's not the best option but I think it would work . Thanks

mebjas commented 4 years ago

@Laure444 - That options works only for Android and IOS isn't it? Does that work for windows as well?

Laure444 commented 4 years ago

@mebjas The "choose file" option works perfectly. I tried on the tablet, when I use the "chose file" version after taking a picture with the camera application it works

Laure444 commented 4 years ago

I did this, it allow the user to automaticaly use the "chose file" option, it's not what I really wanted but it works :

  function autoPassageEnSelectFile() {
    console.log("passage auto en select file")
    document.getElementById("reader__dashboard_section_swaplink").click();
    document.getElementById("reader__dashboard_section_swaplink").style.display = "none";
  }

I still hope it could be possible to use directly the camera option

mebjas commented 4 years ago

@Laure444

Sorry for delayed updates on this issue, I finally have access to a windows system and will try to get this issue fixed asap.

mebjas commented 4 years ago

I just tested this on Windows 10, electron 10.1.1 and it works just fine on that

image

image

Are you still having this issue?

mebjas commented 4 years ago

Here's the code sample

<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0,user-scalable=yes">
  <title>MyApp</title>
</head>
<body body>
  <div id="QRCode">
    <div id="reader"></div>
  </div>
  <script src="app.js"></script>
  <script src="./html5.qrcode.js"></script>
  <script>
    function onScanSuccess(qrCodeMessage) {
      // handle on success condition with the decoded message
    }
    var html5QrcodeScanner = new Html5QrcodeScanner(
      "reader", { fps: 10, qrbox: 250 });
    html5QrcodeScanner.render(onScanSuccess);
  </script>
</body>
</html>

And the js code

const {app, BrowserWindow} = require('electron')
const path = require('path')

function createWindow () {
  const mainWindow = new BrowserWindow({
    width: 400,
    height: 300,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
mebjas commented 4 years ago

I am closing this bug as not reproducible - please update or reopen this bug if you are still facing this issue.