Typescript/Angular2 getUserMedia is not defined

6.9k views Asked by At

I have an Ionic 2 App which uses QuaggaJS Github to Stream the Camera to my View (Div Container) like Snapchat to scan QR Codes. In the browser, it all works like a charm but, the moment it gets built as APK or IPA file I'm getting the Error:

chromium: [INFO:CONSOLE(76955)] "Error: getUserMedia is not defined"

I used ADB and a Virutal Android Device to get the logcat output. Important Info: Yes I have Camera Permission!

Just in case you cant visualize what I'm talking about ,here is a Screenshot of my Page View: Screenshot of Scanner

And this is my Typescript code:

import { Component, OnInit } from '@angular/core';
import { IonicPage, NavController, NavParams, MenuController } from 'ionic-angular';
import Quagga from 'quagga';
declare var Quagga:any;

@Component({
  selector: 'page-scanner',
  templateUrl: 'scanner.html',
})
export class Scanner implements OnInit {

  constructor(public navCtrl: NavController,
    public navParams: NavParams,
    public menu: MenuController) {
  }
   ngOnInit() {
     //WARNING:
     //Error: Types of property 'lift' are incompatible -> means
     //that the used typescript version is too high. Works with: 2.3.4 atm

     Quagga.init({
         inputStream : {
             name : "Live",
             type : "LiveStream",
             constraints: {
               width:  window.innerWidth,
               height: window.innerHeight,
               facingMode: "environment"
             },
             area: {
                top: "0%",
                right: "0%",
                left: "0%",
                bottom: "0%"
            },
            // Or '#yourElement' (optional)
           target: document.querySelector('#scanner')
         },
         locator: {
           patchSize: "medium",
           halfSample: true
         },
         numOfWorkers: (navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 4),
         decoder : {
          //Change Reader for the right Codes
          readers: [ "code_128_reader",
                     "ean_reader",
                     "ean_8_reader",
                     "code_39_reader",
                     "code_39_vin_reader",
                     "codabar_reader",
                     "upc_reader",
                     "upc_e_reader",
                     "i2of5_reader" ],
         },
         locate: true
       }, function(err) {
           if (err) {
               console.log(err);
               return
           }
           console.log("Initialization finished. Ready to start");
           Quagga.start();
       });
       // Make sure, QuaggaJS draws frames an lines around possible
        // barcodes on the live stream
        Quagga.onProcessed(function(result) {
            var drawingCtx = Quagga.canvas.ctx.overlay,
                drawingCanvas = Quagga.canvas.dom.overlay;

            if (result) {
                if (result.boxes) {
                    drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
                    result.boxes.filter(function (box) {
                        return box !== result.box;
                    }).forEach(function (box) {
                        Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "green", lineWidth: 2});
                    });
                }

                if (result.box) {
                    Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2});
                }

                if (result.codeResult && result.codeResult.code) {
                    Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
                }
            }
        });
      // Once a barcode had been read successfully, stop quagga and
      // close the modal after a second to let the user notice where
      // the barcode had actually been found.
      Quagga.onDetected(function(result) {
        if (result.codeResult.code){
        // Was passieren soll wenn ein Code gescannt wurde
        //  $('#scanner_input').val(result.codeResult.code);
        }
      });
   }
   ionViewWillLeave(){
     Quagga.stop();
   }
}
2

There are 2 answers

1
AudioBubble On BEST ANSWER

Well this may be the dumpest answer I have ever written, but I sloved my problem by myself. Sometimes the easiest things are the reasons of weird errors.

Well as it states here getUserMedia() is aviable on Android 5.0+, but I worked the whole time on Android 4.4.2 Device. After an Update all worked fine.

This release introduces the PermissionRequest class, which allows your app to grant the WebView permission to access protected resources like the camera and microphone, through web APIs such as getUserMedia(). Your app must have the appropriate Android permissions for these resources in order to grant the permissions to the WebView.

I've never had 3 days as much wasted as with this error. Cheers

4
JGFMK On

From here it states:

1) Important: Accessing getUserMedia requires a secure origin in most browsers, meaning that http:// can only be used on localhost. All other hostnames need to be served via https://. You can find more information in the Chrome M47 WebRTC Release Notes.

Feature-detection of getUserMedia

2) Every browser seems to differently implement the mediaDevices.getUserMedia API. Therefore it's highly recommended to include webrtc-adapter in your project.

Here's how you can test your browser's capabilities:

3) if (navigator.mediaDevices && typeof navigator.mediaDevices.getUserMedia === 'function') { // safely access navigator.mediaDevices.getUserMedia } The above condition evaluates to:

Browser result
Edge true
Chrome true
Firefox true
IE 11 false
Safari iOS false

So can you:

  1. Confirm whether you are using https
  2. You have included webrtc-adapter
  3. Whether Android passes the condition check.

Link for others on MediaDevices.getUserMedia from MDN