mribbons / cordova-plugin-cipherlab-rs30

Apache Cordova Barcode Scanner Plugin for Cipherlab RS30
MIT License
6 stars 12 forks source link

The app is stopping when the scan initiated. #8

Closed gcivicodev closed 7 years ago

gcivicodev commented 7 years ago

Hi @mribbons

Does this plugin works with latest ionic version? The app is stopping when the scan initiated.

The android version of the device is 4.4.2 KitKat.

My ionic info: global packages:

    @ionic/cli-utils : 1.4.0
    Cordova CLI      : 7.0.1
    Gulp CLI         : not installed globally
    Ionic CLI        : 3.4.0

local packages:

    @ionic/cli-plugin-cordova : 1.4.0
    @ionic/cli-plugin-gulp    : 1.0.1
    @ionic/cli-plugin-ionic1  : 2.0.0
    Cordova Platforms         : android 6.1.2
    Ionic Framework           : ionic1 1.3.3

System:

    Node       : v6.11.0
    OS         : Windows 10
    Xcode      : not installed
    ios-deploy : not installed
    ios-sim    : not installed
    npm        : 5.0.3

This is the code I'm using:

On view:
  <ion-nav-buttons side="right" class="has-header">
    <button id="scan_button" class="button button-royal icon ion-qr-scanner" ng-click="scan()" ng-disabled="canNotUseScanner"> scan</button>
    <img ng-show="imageLoading" src="img/scan_loader.gif" style="width: 35px;">
  </ion-nav-buttons>

On the Controller:

    $scope.scan = function() {
        $ionicPlatform.ready(function() {
            var _scan = true;
            /* The process break here is like cordova.plugins.CipherlabRS30CordovaPlugin in undefined. */
            cordova.plugins.CipherlabRS30CordovaPlugin.requestScan(function () {
                // MDR 30/11/2015 - This is just a placeholder callback. Results will be handled by setReceiveScanCallback() parameter below
            });

            cordova.plugins.CipherlabRS30CordovaPlugin.initialise(function () {

                cordova.plugins.CipherlabRS30CordovaPlugin.setReceiveScanCallback(function (data) {
                    /*get the barcode data ie. 45879hg55\n*/
                    if(_scan) {
                        $scope.registerItemToScanHistory(data);
                        _scan = false;
                    }
                    cordova.plugins.CipherlabRS30CordovaPlugin.destroy(function () { });
                });

            });
        });
    }
gcivicodev commented 7 years ago

Hi @mribbons

The /plugins/android.json looks like this:

{
    "prepare_queue": {
        "installed": [],
        "uninstalled": []
    },
    "config_munge": {
        "files": {}
    },
    "installed_plugins": {
        "cordova-plugin-cipherlab-rs30": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "cordova-plugin-compat": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "cordova-plugin-console": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "cordova-plugin-device": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "cordova-plugin-file": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "cordova-plugin-keyboard": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "cordova-plugin-network-information": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "cordova-plugin-splashscreen": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "cordova-plugin-statusbar": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "cordova-plugin-whitelist": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
        "ionic-plugin-keyboard": {
            "PACKAGE_NAME": "io.ionic.starter"
        }
    },
    "dependent_plugins": {}
}

The /platforms/android/android.json looks like this:

    "config_munge": {
        "files": {
            "res/xml/config.xml": {
                "parents": {
                    "/*": [
                        {
                            "xml": "<feature name=\"CipherlabRS30CordovaPlugin\"><param name=\"android-package\" value=\"au.com.micropacific.cordova.CipherlabRS30Plugin\" /></feature>",
                            "count": 1
                        },
    "installed_plugins": {
        "cordova-plugin-cipherlab-rs30": {
            "PACKAGE_NAME": "io.ionic.starter"
        },
    "modules": [
        {
            "id": "cordova-plugin-cipherlab-rs30.CipherlabRS30CordovaPlugin",
            "file": "plugins/cordova-plugin-cipherlab-rs30/www/CipherlabRS30CordovaPlugin.js",
            "pluginId": "cordova-plugin-cipherlab-rs30",
            "clobbers": [
                "cordova.plugins.CipherlabRS30CordovaPlugin"
            ]
        },
    "plugin_metadata": {
        "cordova-plugin-cipherlab-rs30": "0.0.3",
mribbons commented 7 years ago

Hi @gcivicodev, Welcome back. You are in luck as I now have some devices on hand that I can use to recreate your issue.

I haven't tested with Ionic yet, but in theory it should work.

Can you kindly provide a few more pieces of information:

  1. The logcat which includes the crash, you should see some kind of exception related information. I would like the see the full stack trace.
adb shell logcat > log.txt

Please paste output directly or using Markdown styling. Do not attach screen shots.

  1. The filename of your barcode BarcodeAPI*.jar file - This tells us the version number supported by your device.
  2. The build number of your device. You can find this in Settings->About.
mribbons commented 7 years ago

Hi @gcivicodev, I have successfully used the plugin with Ionic 3, it should definitely work with older versions.

One thing that stands out is that your calls seem to be in the wrong order.

It's possible that $ionicPlatform.ready() wasn't being called as initialise() it should fail before requestScan() if anything is wrong.

Try this code. Note that angular is not my forte and I haven't tested it.

app.controller('myController', function($scope) {
    $scope.scanHistory = [];

    $scope.registerItemToScanHistory = function(data){
        console.log('received a scan: ' + data);
        $scope.scanHistory.push(data);
    }

    cordova.plugins.CipherlabRS30CordovaPlugin.initialise(/* there is no callback here */);

    // this tells the plugin what to do when a barcode is scanned successfully
    // the scan might be triggered by the app, or by the hardware buttons
    cordova.plugins.CipherlabRS30CordovaPlugin.setReceiveScanCallback(function (data) {
        $scope.registerItemToScanHistory(data);
    });

    $scop.scan = function() {
        cordova.plugins.CipherlabRS30CordovaPlugin.requestScan(function () {
                // MDR 30/11/2015 - This is just a placeholder callback. Results will be handled by setReceiveScanCallback() parameter below
        });
    }

    // I'm not sure of the correct angular code for this, cleanUp will be called something different
    $scope.cleanUp = function() {
        cordova.plugins.CipherlabRS30CordovaPlugin.destroy(function () { });
    }
});

If that still doesn't help you then please provide log cat output as well as the other information as per my previous post.

If you are really stuck I would recommend getting going with a bare bones cordova app first. This should rule out any confusion with ionic. Also note that your _scan variable should not be required, as I pointed out on #7.

gcivicodev commented 7 years ago

Hi @mribbons

Thanks a lot. Tomorrow I will continue with this and test your code. I will let you know the result.

gcivicodev commented 7 years ago

Hi @mribbons

Your code works fine with little changes. Thanks for your help.

The Controller

.controller('homeCtrl', ['$rootScope','$scope', '$stateParams','$ionicPlatform','$timeout'
,function ($rootScope,$scope, $stateParams, $ionicPlatform,$timeout) {

    $scope.scanData = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia aspernatur cupiditate rerum ut repellat veniam in placeat sit porro fuga id blanditiis possimus sed molestiae, nesciunt quisquam vel ipsum, sapiente.';

    $scope.registerItemToScanHistory = function(data){
        $scope.scanData = data;
    }

    $ionicPlatform.ready(function() { /* The device must be ready */
        $timeout(function() { /* Force the execution */
            if(window.cordova && window.cordova.plugins && window.cordova.plugins.CipherlabRS30CordovaPlugin) { 
                // this tells the plugin what to do when a barcode is scanned successfully
                // the scan might be triggered by the app, or by the hardware buttons
                cordova.plugins.CipherlabRS30CordovaPlugin.setReceiveScanCallback(function (data) {
                    $scope.registerItemToScanHistory(data);
                });
            }
        },0);
    });

    $scope.scan = function() {
        $ionicPlatform.ready(function() { /* The device must be ready */
            if(window.cordova && window.cordova.plugins && window.cordova.plugins.CipherlabRS30CordovaPlugin) {
                /* Outside of the button behaviour, I can't achieve that the scan initiated.  */
                cordova.plugins.CipherlabRS30CordovaPlugin.initialise(/* there is no callback here */);
                cordova.plugins.CipherlabRS30CordovaPlugin.requestScan(function () {
                        // MDR 30/11/2015 - This is just a placeholder callback. Results will be handled by setReceiveScanCallback() parameter below
                });
            }
        });
    }

    // I'm not sure of the correct angular code for this, cleanUp will be called something different
    $scope.cleanUp = function() {
        $ionicPlatform.ready(function() { /* The device must be ready */
            /* First check if cordova and cordova.plugins exists */
            if(window.cordova && window.cordova.plugins && window.cordova.plugins.CipherlabRS30CordovaPlugin) {
                cordova.plugins.CipherlabRS30CordovaPlugin.destroy(function () { });
            }
        });
    }

    /* In my case, if the app is on background, I do clean up. */
    $ionicPlatform.on('pause', function() {
        $scope.cleanUp();
    });

    /* If the user left the current view, clean up */
    $scope.$on('$ionicView.beforeLeave', function() {
        $scope.cleanUp();
    });

    /* Only on Android, If the user press the hardware back button then I clean up */
    $ionicPlatform.registerBackButtonAction(function() {
        $scope.cleanUp();
    },100);

}])

The view

<ion-view title="Home">
  <ion-content padding="true" class="has-header">
    <button class="button button-positive button-block" ng-click="scan()">Scan</button>
    <p><strong>Scan Data:</strong></p>
    <p>
        {{scanData}}
    </p>
  </ion-content>
</ion-view>

Ionic info

global packages:

    @ionic/cli-utils : 1.4.0
    Cordova CLI      : 7.0.1
    Gulp CLI         : not installed globally
    Ionic CLI        : 3.4.0

local packages:

    @ionic/cli-plugin-cordova : 1.4.0
    @ionic/cli-plugin-gulp    : 1.0.1
    @ionic/cli-plugin-ionic1  : 2.0.0
    Cordova Platforms         : android 6.2.3
    Ionic Framework           : ionic1 1.3.3

System:

    Node       : v6.11.0
    OS         : Windows 10
    Xcode      : not installed
    ios-deploy : not installed
    ios-sim    : not installed
    npm        : 5.0.3
mribbons commented 7 years ago

That's great, 👍

Your code still looks a bit incorrect.

You shouldn't be calling initialise() for every scan request. That might result in duplicate scans, each time the user presses the scan button, a new BroadcastReceiver will be set up.

The correct way to do this in angular would be to implement a cipherlabScanService service wrapper and inject it into your controllers.

https://docs.angularjs.org/guide/services

At worst, just call initialise() right before where you are calling setReceiveScanCallback() at the top.

You could do it as a a device ready callback in that scope, eg

.controller('homeCtrl', ['$rootScope','$scope', '$stateParams','$ionicPlatform','$timeout'
,function ($rootScope,$scope, $stateParams, $ionicPlatform,$timeout) {

    $scope.scanData = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia aspernatur cupiditate rerum ut repellat veniam in placeat sit porro fuga id blanditiis possimus sed molestiae, nesciunt quisquam vel ipsum, sapiente.';

    $ionicPlatform.ready(function() { /* The device must be ready */
        if(window.cordova && window.cordova.plugins && window.cordova.plugins.CipherlabRS30CordovaPlugin) {
         /* Outside of the button behaviour, I can't achieve that the scan initiated.  */
        cordova.plugins.CipherlabRS30CordovaPlugin.initialise(/* there is no callback here */);

        cordova.plugins.CipherlabRS30CordovaPlugin.setReceiveScanCallback(function (data) {
                    $scope.registerItemToScanHistory(data);
    });

    });    
}

.... Also if you have to use setTimeout(), something must be wrong. You are introducing an artificial delay to get around a race condition problem you don't understand. It will cause bugs in production because the delay won't always be long enough.

Good luck!

gcivicodev commented 7 years ago

Hi @mribbons

Thanks for the tips. As you, I think the service is the best option with angular. This code not work for me. The scan not initialize.

.controller('homeCtrl', ['$rootScope','$scope', '$stateParams','$ionicPlatform','$timeout'
,function ($rootScope,$scope, $stateParams, $ionicPlatform,$timeout) {

    $scope.scanData = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia aspernatur cupiditate rerum ut repellat veniam in placeat sit porro fuga id blanditiis possimus sed molestiae, nesciunt quisquam vel ipsum, sapiente.';

    $ionicPlatform.ready(function() { /* The device must be ready */
        if(window.cordova && window.cordova.plugins && window.cordova.plugins.CipherlabRS30CordovaPlugin) {
         /* Outside of the button behaviour, I can't achieve that the scan initiated.  */
        cordova.plugins.CipherlabRS30CordovaPlugin.initialise(/* there is no callback here */);

        cordova.plugins.CipherlabRS30CordovaPlugin.setReceiveScanCallback(function (data) {
                    $scope.registerItemToScanHistory(data);
    });

    });    
}

That's the reason I moved the cordova.plugins.CipherlabRS30CordovaPlugin.initialise(); in the button trigger. But the service will do the work.

RogerBrad commented 5 years ago

Please would you let me know if you plan to write this in Ionic 6