chariotsolutions / phonegap-nfc

PhoneGap NFC Plugin
MIT License
712 stars 570 forks source link

.nfc.write() success and failure callbacks are both called on write error #107

Closed floutchito closed 6 years ago

floutchito commented 10 years ago

I do not have time to provide a test case ATM, but I will in the next few days. I use the plugin to read and write tags for my app.

Unfortunately, I can't detect a tag loss, so I detect presence of a tag and write a flag to call nfc.write() when user clicks a button.

But if the tag is removed from the field of the NFC adapter before calling nfc.write(), I receive both callbacks : success and failure.

How could I detect loss, or only receive failure callback in that case?

Many thanks for the plugin, by the way.

don commented 10 years ago

That's unfortunate that the success and failure callbacks are both called, hopefully I can fix this with better error handling in my code.

Android does have a TagLostException so it might be possible to add tag lost detection.

I'll look into this, but there might be a bit of a delay before I get to it.

don commented 10 years ago

I can't duplicate this using 683b1bd2d03fa959c3010b0592d7c7ee489a8882 and Cordova 3.3.1-0.1.2 on OS X

Test code added to deviceready

    nfc.addNdefListener(
        function(nfcEvent) {
            // ignore what's on the tag
            console.log("preparing to write tag");
            nfc.write(
                [
                    ndef.textRecord("Hello!")
                ],
                function() { console.log("============= WRITE SUCCESS ==============="); }, 
                function(error) { console.log("=================== WRITE FAILED =================="); console.log(error); } 
            );
            console.log("OK!");

        }, 
        function() { console.log("listening for NDEF tags"); }, 
        function(error) { console.log("Error registering NDEF listener " + error); } 
    );

Success handler is called on good write. Pull phone away from tag to cause an error, only error callback is called

D/NfcPlugin(10252): execute writeTag
D/CordovaLog(10252): file:///android_asset/www/js/index.js: Line 17 : preparing to write tag
I/Web Console(10252): preparing to write tag at file:///android_asset/www/js/index.js:17
D/CordovaLog(10252): file:///android_asset/www/js/index.js: Line 25 : OK!
I/Web Console(10252): OK! at file:///android_asset/www/js/index.js:25
D/dalvikvm(  251): GC_CONCURRENT freed 2733K, 20% free 15860K/19591K, paused 32ms+13ms, total 156ms
D/CordovaLog(10252): file:///android_asset/www/js/index.js: Line 23 : =================== WRITE FAILED ==================
I/Web Console(10252): =================== WRITE FAILED ================== at file:///android_asset/www/js/index.js:23
D/CordovaLog(10252): file:///android_asset/www/js/index.js: Line 23 : Tag is not ndef
I/Web Console(10252): Tag is not ndef at file:///android_asset/www/js/index.js:23
E/NFCJNI  (  552): phLibNfc_RemoteDev_CheckPresence() returned 0x00ff[NFCSTATUS_FAILED]
D/NativeNfcTag(  552): Tag lost, restarting polling loop
D/AudioHardware(   90): AudioHardware pcm playback is going to standby.

Tested on

Tags

floutchito commented 10 years ago

Thank you very much to take time to answer this issue.

I wrote a test-case to illustrate the way i use the plugin, and I observe that the issue is still present. Dev platform is Eclipse on Win8, Plugin is v0.4.8 https://github.com/chariotsolutions/phonegap-nfc/commit/683b1bd2d03fa959c3010b0592d7c7ee489a8882 with Cordova 3.3.0-0.1.1 And device is a Nexus 10 (Android 4.4.2) Tags are android.nfc.tech.NfcV / ICODE SLIX

var NFC_EVENT;

var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        //app.receivedEvent('deviceready');
        nfc.addNdefListener(
            function(nfcEvent) {
                // ignore what's on the tag
                console.log("preparing to write tag");
                console.log(nfcEvent);
                NFC_EVENT = nfcEvent;
                console.log("OK!");

            }, 
            function() { console.log("listening for NDEF tags"); }, 
            function(error) { console.log("Error registering NDEF listener " + error); } 
        );

        nfc.addNdefFormatableListener(
            function(nfcEvent) {
                // ignore what's on the tag
                console.log("preparing to write tag if NdefFormatable");
                console.log(nfcEvent);
                NFC_EVENT = nfcEvent;
                console.log("OK!");

            }, 
            function() { console.log("listening for NDEF FORMATABLE tags"); }, 
            function(error) { console.log("Error registering NDEF FORMATABLE listener " + error); } 
        );

        //if (device.platform == "Android") {

            // Android reads non-NDEF tag. BlackBerry and Windows don't.
            nfc.addTagDiscoveredListener(
                function(nfcEvent) {
                    // ignore what's on the tag
                    console.log("preparing to write tag if Non-NDEF");
                    console.log(nfcEvent);
                    NFC_EVENT = nfcEvent;
                    console.log("OK!");

                }, 
                function() { console.log("listening for NON-NDEF tags"); }, 
                function(error) { console.log("Error registering NON-NDEF listener " + error); } 
            );

            nfc.addMimeTypeListener(
                'tko/ty',
                function(nfcEvent) {
                    // ignore what's on the tag
                    console.log("preparing to write tag if tko/ty");
                    console.log(nfcEvent);
                    NFC_EVENT = nfcEvent;
                    console.log("OK!");

                }, 
                function() { console.log("listening for MIME NDEF tags"); }, 
                function(error) { console.log("Error registering MIME NDEF listener " + error); } 
            );

        //}
    },
    clickedWriteButton: function(){
        var message = [
            ndef.mimeMediaRecord("tko/ab", nfc.stringToBytes("0")),
            ndef.mimeMediaRecord("tko/ac", nfc.stringToBytes("Some text")),
            ndef.mimeMediaRecord("tko/ad", nfc.stringToBytes("Some other text")),
            ndef.mimeMediaRecord("tko/ae", nfc.stringToBytes("45"))
        ];
        app.writeTag( message );
    },
    writeTag: function( message ) {

        nfc.write(
            message,
            app.onTagWritten(),
            function (reason) {
                app.onTagWritingError( reason );
            }
        );
    },
    onTagWritten: function(){

        console.log( "Tag successfully written by " + NFC_EVENT.type );
    },
    onTagWritingError: function( e ){

        console.log( "Tag writing failed : " + e + " for handler " + NFC_EVENT.type );
    }
};

See test case repo for details https://github.com/floutchito/tag-writing-failure-testcase

And here is the console output :

listening for NDEF tags index.js:49
listening for NDEF FORMATABLE tags index.js:63
listening for NON-NDEF tags index.js:79
listening for MIME NDEF tags index.js:93
Initialized the NfcPlugin phonegap-nfc.js:18
preparing to write tag index.js:43
OK! index.js:46

CLICK WITH TAG IN FIELD

Tag successfully written by ndef index.js:120
preparing to write tag index.js:43
OK! index.js:46

CLICK WITHOUT TAG IN FIELD: 

Tag successfully written by ndef index.js:120
Tag writing failed : nullfor handler ndef index.js:124

Let me explain a bit more :

I use the plugin to write tags when validating something by clicking a button. When clicked, I want to write if a tag is present, or receive failure callback if tag is not present.

I use a workaround for the moment (neutralize Success callback actions in failure callback... tricky.)

I don't really undestand why this does not work as I expect. Could you please explain why this does not work if you understand the issue ?

Regards.

snjak commented 10 years ago

Hello Don. I'm sorry for disturbing you but I got this problem fixed... Apparently it was bad NFC tag.

I want to thank you for all your work! You have helped me in my project A LOT.

So thank you again, kind regards, and sorry!

On Tue, Sep 30, 2014 at 4:13 PM, Don Coleman notifications@github.com wrote:

Reopened #107 https://github.com/chariotsolutions/phonegap-nfc/issues/107.

— Reply to this email directly or view it on GitHub https://github.com/chariotsolutions/phonegap-nfc/issues/107#event-172100152 .

floutchito commented 10 years ago

Hello Don, I'm still looking for a solution for this. May I help by any way?

don commented 10 years ago

@floutchito In general I'd prefer you to handle the NFC event and determine if you should read or write, rather than pushing a button. But I'm going to look into this some more since I'd rather have the code call one callback on error if possible.

don commented 10 years ago

@josipbosnjak glad you got it working