chariotsolutions / phonegap-nfc

PhoneGap NFC Plugin
MIT License
706 stars 556 forks source link

nfc.erase is failing on Android #276

Closed halindrome closed 6 years ago

halindrome commented 7 years ago

I have a bunch of blank tags that we are using for a project. I have set up a handler to get called when there is an NDEF Formatable tag discovered. That handler is getting called. Within the handler the logic is:

 var record = [ ndef.mimeMediaRecord("cvx/bcn", nfc.stringToBytes(beaconID)) ];

    // Set up handler for formatting
    app.watchForBlankNFC = function(item) {
       this NFC is not formatted
      nfc.erase(function() {
        nfc.write(record, function() {
          dataWritten = true;
        }.bind(this), function(err) {
          console.log("NFC Write Failed: " +err);
        });
      }, function(err) {
        console.log("NFC Formatting failed: " + err) ;
      });
    };

This handler gets called, and when inspecting I can see that the formatting failed clause is being called... but there is no parameter so I don't know why. When the event handler is called, the "tag" property contains:

{"id":[4,95,59,-102,-7,78,-124],
     "techTypes":["android.nfc.tech.NfcA","android.nfc.tech.MifareUltralight","android.nfc.tech.NdefFormatable"]}"

I did run an adb logcat while trying this. Here is the relevant output:

  06-12 09:49:54.541  2693 32388 D NativeNfcTag: Starting background presence check
  06-12 09:49:54.572  1046  4870 I ActivityManager: START u0 {act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=com.corvexsafety.sdapp/.MainActivity (has extras)} from uid 1
0165 on display 0
  06-12 09:49:54.573  1046  4870 W ActivityManager: startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { act=android.nfc.action.TECH_D
ISCOVERED flg=0x24000000 cmp=com.corvexsafety.sdapp/.MainActivity (has extras) }
  06-12 09:49:54.575 30223 30223 D CordovaActivity: Paused the activity.
  06-12 09:49:54.623 30223 30223 D CordovaWebViewImpl: >>> loadUrl(javascript:cordova.plugins.backgroundMode._isActive=true;cordova.plugins.backgroundMode.fireEvent('activate',null)
;cordova.plugins.backgroundMode.onactivate(null);)
  06-12 09:49:54.626 30223 30223 D NfcPlugin: onPause Intent {  }
  06-12 09:49:54.626 30223 30223 D NfcPlugin: stopNfc
  06-12 09:49:54.633 30223 30223 D NfcPlugin: onNewIntent Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x34000000 cmp=com.corvexsafety.sdapp/.MainActivity (has extras) }
  06-12 09:49:54.635 30223 32389 D NfcPlugin: parseMessage Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x34000000 cmp=com.corvexsafety.sdapp/.MainActivity (has extras) }
  06-12 09:49:54.635 30223 32389 D NfcPlugin: action android.nfc.action.TECH_DISCOVERED
  06-12 09:49:54.635 30223 30223 D CordovaActivity: Resumed the activity.
  06-12 09:49:54.636 30223 32389 D NfcPlugin: android.nfc.tech.NfcA
  06-12 09:49:54.636 30223 32389 D NfcPlugin: android.nfc.tech.MifareUltralight
  06-12 09:49:54.636 30223 32389 D NfcPlugin: android.nfc.tech.NdefFormatable
  06-12 09:49:54.636 30223 30223 D CordovaWebViewImpl: >>> loadUrl(javascript:cordova.plugins.backgroundMode._isActive=false;cordova.plugins.backgroundMode.fireEvent('deactivate',nu
ll);cordova.plugins.backgroundMode.ondeactivate(null);)
  06-12 09:49:54.636 30223 32389 V NfcPlugin: var e = document.createEvent('Events');
  06-12 09:49:54.636 30223 32389 V NfcPlugin: e.initEvent('ndef-formatable');
  06-12 09:49:54.636 30223 32389 V NfcPlugin: e.tag = {"id":[4,81,51,-102,-7,78,-124],"techTypes":["android.nfc.tech.NfcA","android.nfc.tech.MifareUltralight","android.nfc.tech.Ndef
Formatable"]};
  06-12 09:49:54.636 30223 32389 V NfcPlugin: document.dispatchEvent(e);
  06-12 09:49:54.641 30223 30223 D NfcPlugin: onResume Intent {  }
  06-12 09:49:54.645 30223 30261 D NfcPlugin: execute eraseTag
  06-12 09:49:54.669 30223 30223 D SystemWebChromeClient: file:///android_asset/www/js/index.js: Line 3628 : Going into background mode
  06-12 09:49:54.669 30223 30223 I chromium: [INFO:CONSOLE(3628)] "Going into background mode", source: file:///android_asset/www/js/index.js (3628)
  06-12 09:49:54.678 30223 30223 D SystemWebChromeClient: file:///android_asset/www/js/index.js: Line 3632 : Coming out of background mode
  06-12 09:49:54.678 30223 30223 I chromium: [INFO:CONSOLE(3632)] "Coming out of background mode", source: file:///android_asset/www/js/index.js (3632)
  06-12 09:49:54.681 30223 30223 D SystemWebChromeClient: file:///android_asset/www/js/index.js: Line 1643 : NFC Formatting failed:
  06-12 09:49:54.681 30223 30223 I chromium: [INFO:CONSOLE(1643)] "NFC Formatting failed: ", source: file:///android_asset/www/js/index.js (1643)

Any ideas why it might not want to format? Or any additional information I can capture?

don commented 6 years ago

I don't think you can erase a tag that isn't formatted. Try removing the erase and just writing the message. IIRC it will format and write the message.

halindrome commented 6 years ago

BTW I tried this and the write failed. Can you imagine a path that will get us from "formatted in some unknown format" to "formatted as NDEF and written with an NDEF record" ?

don commented 6 years ago

It looks like nfc.erase is writing an empty NDEF record to the tag. If your tag is blank, this will format and write the empty message. If you tag has an NDEF message erase will overwrite it. https://github.com/chariotsolutions/phonegap-nfc/blob/master/src/android/src/com/chariotsolutions/nfc/plugin/NfcPlugin.java#L227-L234

Calling nfc.write will format the tag if necessary before writing the NDEF message. I'd expect that's what's failing.

If there is non-NDEF content on the tag, it'll probably fail. Can you see what happens with NXP Tag Writer when you use "Erase to Factory Default"? That should blank the tag and allow you to write NDEF messages to it.

Not all NFC tags can be erased. NXP Tag Write fails on Mifare Classic tags when some sectors have different keys. You can write custom code to fix this, but generally I just get a new tag. If it won't format, I'd look at the bytes on the tag using NXP Tag Info or NFC TagInfo to determine what's wrong.

sultano commented 6 years ago

I'm having the same issues as @halindrome using Mifare Ultralight cards. Both nfc.erase and nfc.write fail with blank cards. I used NXP Tag Writer to format the cards using the "Erase to Factory Default" option, only then both methods worked as expected.

don commented 6 years ago

I don't have a good fix for this. In the past my devices would format before writing. For now I think you just need more error handling for unformatted tags.