chariotsolutions / phonegap-nfc

PhoneGap NFC Plugin
MIT License
706 stars 557 forks source link

Works on 4.2.x but no other operating system #252

Closed MYoung25 closed 7 years ago

MYoung25 commented 7 years ago

Hi,

So I've gotten this snippet to work on an android phone (Galaxy S3 running 4.1.2):

    nfc.addNdefListener (
        function (nfcEvent) {
            var text = document.querySelector('.writeEncoded'));
            var link = ndef.textRecord(text);
            nfc.write([link], function(){
                    alert('Success!');
                },
                function(){
                    alert('I\'m sorry, something went wrong, please try again');
                }
            );
        },
        function () { 
            alert("Waiting for NDEF tag");
        },
        function (error) {
            alert("Error adding NDEF listener " + JSON.stringify(error));
        }
    );

For some reason it doesn't work on a Samsung Galaxy Tab 4 running 5.0.2, it also doesn't work on a Nexus 7 running either 4.4.4 or 5.1.

Other information: the alert for successfully adding the listener is called, but when I touch my nfc tags (mifare classic and mifare ultralight) to the reader it only gives me a response on the phone. I've tested the readers and tags on the tablets, other apps can interact with the same tags.

Any direction would be much appreciated. Thank you

MYoung25 commented 7 years ago

it does work on a Nexus 7 running 4.2.

don commented 7 years ago

Mifare Classic tags don't work as NDEF tags on devices with Broadcom NFC chips. The original Nexus 7 was OK, I'm not sure about the Nexus 7 2013. Some of the Galaxy devices might be a problem too.

You could try adding nfc.addTagDiscoveredListener to see if you can read the tag id on devices that won't read the tag. https://github.com/don/phonegap-nfc-issue-247/blob/master/www/js/index.js#L68-L81

If a tag is not formatted as NDEF, you'll need nfc.addNdefFormatableListener to read the tag and write data to it. https://github.com/don/phonegap-nfc-issue-247/blob/master/www/js/index.js#L83-L105

It's fine to have multiple listeners, Android will call the most specific one for the tag that's scanned.

Other things to try are

MYoung25 commented 7 years ago

I've done a few things now, (I'm guessing the important one is 5)

1) I downloaded an nfc reader app, all my devices can read and write to both mifare classic and mifare ultralight

2) I've added nfc.showSettings, nfc is definitely accessible on my device

3) I've added tagDiscovered, ndef formatable, and nfc.enabled to my program and tested on devices running 4.4.4, 5.0.2, and 4.2.2. nfc.enabled returns true, all listener's success functions are returned, but the only device that does anything when a tag is brought is the one running 4.2.2

4) I removed Ndef listener, for good measure, and tested the same 3 operating systems. Both discovered and formatable listeners were added, but when a tag was brought, only 4.2.2 was able to find the tag at all.

5) using chrome://inspect the log says NFCPlugin initialized, then returned 2 errors on nfcEvent Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src * 'unsafe-inline'". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback. and Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src * 'unsafe-inline'".

6) when using chrome://inspect on the 4.2.2 device I'm not even shown the app running on my device

MYoung25 commented 7 years ago

Here is the logcat result from the tablet running 4.4.4

D/NfcDispatcher(  757): dispatch tag: TAG: Tech [android.nfc.tech.MifareUltralight, android.nfc.tech.NfcA, android.nfc.tech.Ndef] message: NdefMessage [NdefRecord tnf=1 type=54 payload=02656E32763570636E686D]
D/NfcPlugin( 5406): onPause Intent {  }
D/NfcPlugin( 5406): stopNfc
D/NfcDispatcher(  757): Set Foreground Dispatch
I/ActivityManager(  494): START u0 {act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras)} from pid -1
W/ActivityManager(  494): startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras) }
D/NfcPlugin( 5406): onNewIntent Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras) }
I/NfcDispatcher(  757): matched TECH override
D/NfcPlugin( 5406): onResume Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras) }
D/NfcDispatcher(  757): Set Foreground Dispatch
D/NfcPlugin( 5406): parseMessage Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras) }
D/NfcPlugin( 5406): action android.nfc.action.TECH_DISCOVERED
D/NfcPlugin( 5406): android.nfc.tech.MifareUltralight
D/NfcPlugin( 5406): android.nfc.tech.NfcA
D/NfcPlugin( 5406): android.nfc.tech.Ndef
V/NfcPlugin( 5406): var e = document.createEvent('Events');
V/NfcPlugin( 5406): e.initEvent('ndef');
V/NfcPlugin( 5406): e.tag = {"isWritable":true,"id":[4,33,-51,-126,116,64,-127],"techTypes":["android.nfc.tech.MifareUltralight","android.nfc.tech.NfcA","android.nfc.tech.Ndef"],"type":"NFC Forum Type 2","canMakeReadOnly":true,"maxSize":137,"ndefMessage":[{"id":[],"type":[84],"payload":[2,101,110,50,118,53,112,99,110,104,109],"tnf":1}]};
V/NfcPlugin( 5406): document.dispatchEvent(e);
I/chromium( 5406): [INFO:CONSOLE(0)] "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src * 'unsafe-inline'". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
I/chromium( 5406): ", source:  (0)
I/chromium( 5406): [INFO:CONSOLE(1070)] "Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src * 'unsafe-inline'".
I/chromium( 5406): ", source: file:///android_asset/www/cordova.js (1070)
D/NativeNfcTag(  757): Tag lost, restarting polling loop

and the logcat from 4.2.2

D/NfcDispatcher(  754): dispatch tag: TAG: Tech [android.nfc.tech.MifareUltralight, android.nfc.tech.NfcA, android.nfc.tech.Ndef] message: NdefMessage [NdefRecord tnf=1 type=54 payload=02656E32763570636E686D]
I/ActivityManager(  477): START u0 {act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras)} from pid -1
D/NfcPlugin( 5500): onPause Intent {  }
D/NfcPlugin( 5500): stopNfc
D/NfcDispatcher(  754): Set Foreground Dispatch
D/NfcPlugin( 5500): onNewIntent Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras) }
W/ActivityManager(  477): startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras) }
D/NfcPlugin( 5500): onResume Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras) }
D/NfcPlugin( 5500): parseMessage Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=org.ali75.form/.NFC_Form (has extras) }
D/NfcPlugin( 5500): action android.nfc.action.TECH_DISCOVERED
D/NfcPlugin( 5500): android.nfc.tech.MifareUltralight
D/NfcPlugin( 5500): android.nfc.tech.NfcA
D/NfcPlugin( 5500): android.nfc.tech.Ndef
V/NfcPlugin( 5500): var e = document.createEvent('Events');
V/NfcPlugin( 5500): e.initEvent('ndef');
V/NfcPlugin( 5500): e.tag = {"isWritable":true,"id":[4,33,-51,-126,116,64,-127],"techTypes":["android.nfc.tech.MifareUltralight","android.nfc.tech.NfcA","android.nfc.tech.Ndef"],"type":"NFC Forum Type 2","canMakeReadOnly":true,"maxSize":137,"ndefMessage":[{"id":[],"type":[84],"payload":[2,101,110,50,118,53,112,99,110,104,109],"tnf":1}]};
V/NfcPlugin( 5500): document.dispatchEvent(e);
D/NfcDispatcher(  754): Set Foreground Dispatch
I/NfcDispatcher(  754): matched TECH override
D/dalvikvm( 5500): GC_CONCURRENT freed 2214K, 23% free 8153K/10512K, paused 4ms+3ms, total 33ms
D/NativeNfcTag(  754): Tag lost, restarting polling loop
AVancans commented 7 years ago

Any updates on this?

don commented 7 years ago

It looks like the Content Security Policy (CSP) for you app is causing the plugin to fail.

[INFO:CONSOLE(0)] "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src * 'unsafe-inline'". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.

I just followed these instructions and my Nexus 5X running Android 7.0 can scan tags with NDEF messages. https://github.com/chariotsolutions/phonegap-nfc/blob/master/doc/GettingStartedCLI.md

The CSP from the default generated app is very permissive

        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">

See the Cordova docs for more info on how to customize the CSP for your app https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy

don commented 7 years ago

Also see https://github.com/chariotsolutions/phonegap-nfc/issues/249#issuecomment-236559032 for more CSP info