Barccode scanner only scans once in 1.0.0-beta.14

Hi Everyone,

I just updated to ionic 1.0.0-beta.14 and my scanner stopped working reliably. It scans correctly once and then goes into some sort of locked state. The same behavior occurs on Android and iOS so it appears to be related to the plugin itself.

It worked correctly in 1.0.0-beta13.

Here is my environment info:

OS: Mac OS X Yosemite
Node Version: v0.12.0
Cordova CLI: 4.2.0
Ionic Version: 1.0.0-beta.14
Ionic CLI Version: 1.3.8
Xcode version: Xcode 6.1.1 Build version 6A2008a 
ios-sim version: 3.1.1 

These are the plugins:

$ ionic plugin
com.ionic.keyboard 1.0.3 "Keyboard"
com.phonegap.plugins.barcodescanner 2.0.1 "BarcodeScanner"
nl.x-services.plugins.socialsharing 4.3.13 "SocialSharing"
org.apache.cordova.console 0.2.12 "Console"
org.apache.cordova.device 0.2.13 "Device"
org.apache.cordova.inappbrowser 0.5.4 "InAppBrowser"
org.apache.cordova.network-information 0.2.14 "Network Information"
org.apache.cordova.splashscreen 0.3.5 "Splashscreen"
org.apache.cordova.statusbar 0.1.9 "StatusBar"

Here is my service:

.service('barcodeScannerService', function($q) {
    this.scan = function() {
        // The plugin operates asynchronously so a promise
        // must be used to display the results correctly.
        var deferred = $q.defer();
        var scanner = cordova.require("cordova/plugin/BarcodeScanner");
        scanner.scan(
            function(result) { 
                deferred.resolve({'error':false, 'result': result});
            },
            function(error) {
                deferred.resolve({'error':true, 'result': error.toString()});
            });
        return deferred.promise;
    };
})

Here is my controller:

.controller('ScanCtrl', function($scope, $state,
                                 barcodeScannerService,
                                 appDataService) {
    // Scan a bar code and send the data to the server to get detailed
    // information about it.
    barcodeScannerService.scan().then(
        function(result) {
            // Success.
            // Got the bar code.
            // result.format:  UPC_A or others.
            // {"format":"UPC_A", "text":"028000214807", "cancelled": false}
            var format = result.result.format;
            var text = result.result.text;
            var cancelled = result.result.cancelled;
            if (cancelled) {
                // Need the timeout to avoid a strange, infinite loop.
                setTimeout(function(){$state.go('tab.scan-cancelled')}, 200);
            }
            else if (format == 'UPC_A' || format == 'UPC_E' || format == 'EAN_8' || format == 'EAN_13') {
                appDataService.m_upc_code = text;
                appDataService.m_upc_format = format.replace('-', '_');
                $state.go('tab.scan-results');
            }
            else {
                appDataService.m_upc_code = text;
                appDataService.m_upc_format = format.replace('-', '_');
                $state.go('tab.scan-failed-bad-code-type');
            }
        },
        function(result) {
            // Error.
            appDataService.m_upc_code = result.error;
            $state.go('tab.scan-failed-bad-scan');
        },
        function(result) {
            // Notification
                appDataService.m_upc_code = result.error;
            $state.go('tab.scan-failed');
        }
    );
})

I also made some minor modifications to CDVBarcodeScanner.mm for iOS to fix the cancel button problem but since the plugin fails on both Android and iOS, this is most likely not the culprit. However the diffs are shown for completeness.

$ diff -u CDVBarcodeScanner.mm.{new,old}
--- CDVBarcodeScanner.mm.new    2015-02-08 14:01:33.000000000 -0800
+++ CDVBarcodeScanner.mm.old    2015-02-09 17:03:16.000000000 -0800
@@ -289,11 +289,8 @@
 
 //--------------------------------------------------------------------------
 - (void)barcodeScanSucceeded:(NSString*)text format:(NSString*)format {
-  dispatch_sync(
-    dispatch_get_main_queue(), ^{
-      [self barcodeScanDone];
-      [self.plugin returnSuccess:text format:format cancelled:FALSE flipped:FALSE callback:self.callback];
-  });
+    [self barcodeScanDone];
+    [self.plugin returnSuccess:text format:format cancelled:FALSE flipped:FALSE callback:self.callback];
 }
 
 //--------------------------------------------------------------------------
@@ -357,7 +354,7 @@
     output.alwaysDiscardsLateVideoFrames = YES;
     output.videoSettings = videoOutputSettings;
     
-    [output setSampleBufferDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)];
+    [output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
     
     if (![captureSession canSetSessionPreset:AVCaptureSessionPresetMedium]) {
         return @"unable to preset medium quality video capture";

Any insights would be greatly appreciated.

Thanks,

Joe

Probably unrelated, but I was having problems with the barcode scanner returning the wrong info (with an earlier version of ionic), but just on Android. Adding the following code fixed it.

            // this "unclogs" the Android event pipeline. Otherwise have issues, like getting the 
            // results of the previous scan, instead of the current one. 
            // https://github.com/wildabeast/BarcodeScanner/issues/107
            // https://github.com/zeroasterisk/MeteorRider/issues/16
            if (device.platform === 'Android') {
                checkMessageInterval = setInterval(function () {
                    cordova.exec(null, null, '', '', [])
                }, 200);
            }                

            cordova.plugins.barcodeScanner.scan(
                function (res) {
                ...

Thank you for sharing this. It is an intriguing insight.

I tried it but it didn’t help fix the 1.1-0.beta14 problem.

I am having a similar issue and would be interested in the response to this question.

I had to downgrade ionic to beta.13:

ionic lib -v 1.0.0-beta.13 update