bitpay / cordova-plugin-qrscanner

A fast, energy efficient, highly-configurable QR code scanner for Cordova apps and the browser.
MIT License
568 stars 772 forks source link

QRScanner.scan() only fire once to subscriber #109

Closed nguyenpc closed 6 years ago

nguyenpc commented 6 years ago

I'm writing an application to regconize a user from JSON text inside QR code. In my application, I want QRScanner keep scanning and emiting result to subscriber if received result is not a valid json (or json structure is not valid). Following is my scan function

this.qrScanner.prepare()
      .then((status: QRScannerStatus) => {
        if (status.authorized) {
          // camera permission was granted
          // start scanning
          this.scannerSubscription = this.qrScanner.scan().subscribe((text: string) => {
           // code in this block will be fired only once
            console.log('Scanned something', text);
            try {
              let user = JSON.parse(text);
              this.navCtrl.setRoot(ResultPage, { user: user });
               this.qrScanner.hide(); // hide camera preview
              this.scannerSubscription.unsubscribe(); // stop scanning
            } catch (error) {
              // keep scanning
            }
          });
          // show camera preview
          this.qrScanner.show();
          // wait for user to scan something, then the observable callback will be called
        } else if (status.denied) {
          // camera permission was permanently denied
          // you must use QRScanner.openSettings() method to guide the user to the settings page
          // then they can grant the permission from there
        } else {
          // permission was denied, but not permanently. You can ask for permission again at a later time.
        }
      })

But I only got result for first scan even I haven't unsubscribe the Scan observable yet.

viniciusz42 commented 6 years ago

Hello nguyenpc, your code seems to be coming from ionic. Could you inform the path of your import? How did you accomplished that?

Stukongeluk commented 6 years ago

I think this is an observable subscribe issue. Correct me if i'm wrong but when an error is triggered, the subscription won't listen anymore, even if you catch it. Still trying to find a fix for it though

yanglongji commented 6 years ago

I don't think it's the subscribe issue. 'cause this was mentioned in readme.md below:

Once a valid code is detected, it's contents are passed to the callback, and scanning is toggled off.

I want to scan serveral times too until I get the one needed

nguyenpc commented 6 years ago

I do agree with @Stukongeluk, it seems that the scannerSubscription unsubcribe automatically after detecting QR code.

Stukongeluk commented 6 years ago

It looks like this repo isn't maintained any more.. but I fixed it a long time ago by reinitialising the scanner again after it failed. I don't have access to the codebase in which I fixed this anymore.

bitjson commented 6 years ago

I think this is an issue for https://github.com/ionic-team/ionic-native.

I'm going to close this for now, but please feel free to open a new issue or PR if something still needs to change in this library.

vincicat commented 5 years ago

ionic-native 5.x (Ionic 4 family) changed the API into promise based so that is fixed.

FYI, for all the subscription issue with ionic-native 4.x (Ionic 3) QR scanner (e.g. UI blocking), convert the scan() function to a promise based scan() function in your provider/component/page code may help:

  scan(): Promise<any> {
    return new Promise(resolve => {
      console.log('Scanning...');
      let scanSub = this.qrScanner.scan().subscribe((text: string) => {
        console.debug('Scan success', text);
        scanSub.unsubscribe(); // stop scanning
        return resolve(text);
      });
    });
  }

ref

Eraledm commented 4 years ago

For a "stream" of QR data what I did was the following approach

scanSubscription: Subscription;
scan() {
    this.scanSubscription = this.qrScanner.scan()
      .subscribe((text: string) => {
        this.onScan(text);
        this.scanSubscription.unsubscribe();
        this.scan();
      });
  });
}
onScan(text: string) {
  console.log("Got: ", text);
}

I hope this helps