chariotsolutions / phonegap-nfc Goto Github PK
View Code? Open in Web Editor NEWPhoneGap NFC Plugin
License: MIT License
PhoneGap NFC Plugin
License: MIT License
If possible get the tag id and other information like tag type, tag technologies, tag capacity, is-read-only (or is-locked), can make tag read only on Windows Phone 8
Hello,
i have an issue on my nexus 7 with android 4.2.2 using the last versions of phonegap (2.5.) and phonegap-nfc (0.4.1). when using the homebutton, the app is recreated again and not resumed. but the other state is still there and available as soon as i exit from the application (as if it is started twice). i've broken this down using only the reader demo. this problem only occurres if a tag is scanned.
I can reproduce it with phonegap-nrc-reader-demo in that way:
you can the on the logs that the app is created (see logs below). if you exit the application now, the application is still available with the old data).
logs for resuming the app WITHOUT scanning a tag:
03-19 11:19:00.714: D/DroidGap(26662): Resuming the App
03-19 11:19:00.714: D/NfcPlugin(26662): onResume Intent { }
logs for resuming the app and a tag is scanned before:
03-19 11:20:45.064: D/DroidGap(26662): DroidGap.onCreate()
03-19 11:20:45.074: D/JsMessageQueue(26662): Set native->JS mode to 2
03-19 11:20:45.074: D/DroidGap(26662): DroidGap.init()
03-19 11:20:45.084: D/CordovaWebView(26662): >>> loadUrl(file:///android_asset/www/index.html)
03-19 11:20:45.084: D/PluginManager(26662): init()
03-19 11:20:45.084: D/CordovaWebView(26662): >>> loadUrlNow()
03-19 11:20:45.084: D/DroidGap(26662): Resuming the App
03-19 11:20:45.094: D/DroidGap(26662): onMessage(onPageStarted,file:///android_asset/www/index.html)
03-19 11:20:45.104: D/SoftKeyboardDetect(26662): Ignore this event
03-19 11:20:45.134: D/CordovaLog(26662): Viewport argument value "320;" for key "width" was truncated to its numeric prefix.
03-19 11:20:45.134: V/Web Console(26662): Viewport argument value "320;" for key "width" was truncated to its numeric prefix. at file:///android_asset/www/index.html:4
03-19 11:20:45.194: D/Cordova(26662): onPageFinished(file:///android_asset/www/index.html)
03-19 11:20:45.194: D/Cordova(26662): Trying to fire onNativeReady
03-19 11:20:45.204: D/DroidGap(26662): onMessage(onNativeReady,null)
03-19 11:20:45.204: D/DroidGap(26662): onMessage(onPageFinished,file:///android_asset/www/index.html)
03-19 11:20:45.214: D/SoftKeyboardDetect(26662): Ignore this event
03-19 11:20:45.264: D/NfcPlugin(26662): execute init
03-19 11:20:45.264: D/NfcPlugin(26662): Enabling plugin Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.chariotsolutions.nfc.demo.reader/.ReaderDemo bnds=[272,595][400,723] }
03-19 11:20:45.274: D/CordovaLog(26662): Initialized the NfcPlugin
03-19 11:20:45.274: I/Web Console(26662): Initialized the NfcPlugin at file:///android_asset/www/phonegap-nfc-0.4.1.js:7
03-19 11:20:45.284: D/NfcPlugin(26662): parseMessage Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.chariotsolutions.nfc.demo.reader/.ReaderDemo bnds=[272,595][400,723] }
03-19 11:20:45.284: D/NfcPlugin(26662): action android.intent.action.MAIN
03-19 11:20:45.294: D/CordovaNetworkManager(26662): Connection Type: wifi
03-19 11:20:45.294: D/DroidGap(26662): onMessage(networkconnection,wifi)
03-19 11:20:45.294: D/CordovaNetworkManager(26662): Connection Type: wifi
03-19 11:20:45.294: D/DroidGap(26662): onMessage(spinner,stop)
03-19 11:20:45.304: D/NfcPlugin(26662): execute registerNdef
03-19 11:20:45.304: D/NfcPlugin(26662): execute registerMimeType
03-19 11:20:45.314: D/CordovaLog(26662): Listening for NDEF tags.
03-19 11:20:45.314: I/Web Console(26662): Listening for NDEF tags. at file:///android_asset/www/main.js:116
03-19 11:20:45.314: D/CordovaLog(26662): Listening for NDEF mime tags with type text/pg.
03-19 11:20:45.314: I/Web Console(26662): Listening for NDEF mime tags with type text/pg. at file:///android_asset/www/main.js:128
03-19 11:20:47.214: D/DroidGap(26662): onMessage(spinner,stop)
Add methods to send events on android.nfc.action.TAG_DISCOVERED
When the ndefMessage passed to writeTag exceeds the tag capacity, the write fails but JavaScript receives a onSuccess callback
Consider an enum
Scanning fails with only mime type listener. Adding a NdefListener or NdefFormattableListener is a work around.
Using cordova 2.3, along with plugin 0.4.2 on BB10 simulator and DevAlpha .
Calling nfc.write([ndef]) inside an event handler throws the following:
Error: Status=7 Message=Action not found: writeTag cordova-2.3.0.js:1036
In the past I've written some apps using phonegap-nfc that have worked great out of the box (simply responding to scans), but I'm trying something a bit more complex now and trying to wrap my head around it.
What I'm trying to do have an app handle a share intent (ie from the Gallery) using the WebIntent plugin (I had to modify the plugin a bit, but it works) to load up my PhoneGap app and the image and then I'd like to be able to scan some tags.
With the webintent plugin alone and the following intent-filter, everything works as expected:
<intent-filter>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="image/*" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
window.webintent.getExtra() is able to pull what I need.
However, when the nfcplugin is activated, I don't seem to see anything. It seems like NfcPlugin is eating the intent?
10-16 14:39:55.728: D/NfcPlugin(28694): Enabling plugin Intent { act=android.intent.action.SEND typ=image/* flg=0x80001 cmp=com.lensley.client.roaming/.MainActivity (has clip) (has extras) }
10-16 14:39:55.728: D/NfcPlugin(28694): parseMessage Intent { act=android.intent.action.SEND typ=image/* flg=0x80001 cmp=com.lensley.client.roaming/.MainActivity (has clip) (has extras) }
10-16 14:39:55.738: D/NfcPlugin(28694): action android.intent.action.SEND
(BTW, a secondary issue was that when I enter w/ a SHARE intent, and then scanned w/ the NFC, it seems to start a second copy of the MainActivity - I switched the activity to android:launchMode="singleTask" as a workaround)
It looks like there's some programmatic stuff going on w/ NfcPlugin and intents that's beyond my ken (I'm an Android programming noob). Is there a quick fix or has this issue been encountered before?
As I see, the plugin is working all the time (draining the battery), isn't it?
Is (will be) there any way to use the plugin in sessions, e.g manually start/stop the reading?
Ndef.makeReadOnly() and possibly NdefFormatable.formatReadOnly(message)
navigator.nfc.makeReadOnly()
// consider options object for writeTag
navigator.nfc.writeTag(ndefMessage, win, lose, { read-only: true })
pluginstall expects a specific directory structure
project
|
|- plugin.xml
|- src
|- android
|- www
Handle devices without NFC more gracefully
private void startNfc() {
createPendingIntent(); // onResume can call startNfc before execute
this.ctx.runOnUiThread(new Runnable() {
public void run() {
NfcAdapter.getDefaultAdapter(ctx.getContext()).enableForegroundDispatch(
...
D/NfcPlugin( 900): execute init
D/NfcPlugin( 900): Enabling plugin Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.chariotsolutions.nfc.demo.reader/.ReaderDemo }
V/NFC ( 900): this device does not have NFC support
D/AndroidRuntime( 900): Shutting down VM
W/dalvikvm( 900): threadid=1: thread exiting with uncaught exception (group=0x40015578)
E/AndroidRuntime( 900): FATAL EXCEPTION: main
E/AndroidRuntime( 900): java.lang.NullPointerException
E/AndroidRuntime( 900): at com.chariotsolutions.nfc.plugin.NfcPlugin$1.run(NfcPlugin.java:160)
E/AndroidRuntime( 900): at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime( 900): at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime( 900): at android.os.Looper.loop(Looper.java:130)
E/AndroidRuntime( 900): at android.app.ActivityThread.main(ActivityThread.java:3687)
E/AndroidRuntime( 900): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 900): at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 900): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
E/AndroidRuntime( 900): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
E/AndroidRuntime( 900): at dalvik.system.NativeStart.main(Native Method)
D/NfcPlugin( 900): parseMessage Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.chariotsolutions.nfc.demo.reader/.ReaderDemo }
D/NfcPlugin( 900): action android.intent.action.MAIN
E/ ( 129): Dumpstate > /data/log/dumpstate_app_error
W/ActivityManager( 129): Force finishing activity com.chariotsolutions.nfc.demo.reader/.ReaderDemo
I/dumpstate( 919): begin
Hi,
I'm using the NFC as well as the Barcodescanner (https://github.com/phonegap/phonegap-plugins/tree/master/Android/BarcodeScanner) plugins in the same project for Android.
I would like to be able to continue detecting NFC tags even when the Barcodescanner activity has started.
At the moment if the barcodescanner activity is active and an NFC tag is detected, the default Android action (opening the tag's url in a browser) is performed.
Is there anyway to tell the NFC plugin to continue listening for NFC tags even if the main activity is in the background ?
I'm new to Android, and have tried to comment out the onPause and onResume functions in the NFC plugin, but this doesn't change anything.
Any help is highly appreciated.
For BB10 addTagDiscoveredListener should really be named addNdefListener
NdefFormatable tags do not return the tag id to javascript
D/NfcPlugin(14710): onNewIntent Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=com.chariotsolutions.nfc.demo.reader/.ReaderDemo (has extras) }
D/NfcPlugin(14710): parseMessage Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x24000000 cmp=com.chariotsolutions.nfc.demo.reader/.ReaderDemo (has extras) }
D/NfcPlugin(14710): action android.nfc.action.TECH_DISCOVERED
D/NfcPlugin(14710): android.nfc.tech.MifareUltralight
D/NfcPlugin(14710): android.nfc.tech.NfcA
D/NfcPlugin(14710): android.nfc.tech.NdefFormatable
V/NfcPlugin(14710): var e = document.createEvent('Events');
V/NfcPlugin(14710): e.initEvent('ndef-formatable');
V/NfcPlugin(14710): e.tag = {};
V/NfcPlugin(14710): document.dispatchEvent(e);
D/DroidGap(14710): Resuming the App
D/NfcPlugin(14710): onResume Intent { }
after scaning nfc card i see this picture. Application "NFC Taginfo" show me info about this card. (in last string "o:" i've just tried to output object "tag", without any edits result of application work the same)
also strange that "NFC Taginfo" ask me hold card for 2-3sec for reading, using your plugin event fires exact after card connect to device, without delay.
The implementation of writeTag has a few problems:
To solve these issues and let the client to be in control, I think a new stateful API is necessary.
My attempt at it follows the Android tag interfaces:
https://github.com/mzabaluev/phonegap-nfc/commits/async-tag-ops
The branch is commingled with other changes I've made, such as an update to Cordova 2.2. If there's interest, I can rebase the changes or just submit them sequentially (#28 would be a good start). There is no implementation for Blackberry.
Callback not fired after nfc.write() on WP8
May be related to #74
I just called the "share" method and got an "NullReferenceException" thrown.
My System Specification is:
The error message:
$exception {System.NullReferenceException: Object reference not set to an instance of an object.
at Cordova.Extension.Commands.NfcPlugin.publish(String type, String args)
at Cordova.Extension.Commands.NfcPlugin.shareTag(String args)} System.Exception {System.NullReferenceException}
cordova-wp8 will be removing BaseCommand.InvokeCustomScript, then means the code won't be able to fire JS events when a NFC message is received.
I'm considering changing the API so the NFC messages are returned in the success callback and not via a JS event.
The current API looks like this
nfc.addNdefListener(callback, [onSuccess], [onFailure]);
The callback is called using an event listener and receives a nfcEvent
onSuccess is only called when the listener is successfully added, which isn't very useful. onFailure is called when the the code fails to add the listener.
The proposed change would make the API look like
nfc.addNdefListener(onSuccess, [onFailure]);
The onSuccess callback would be kept and onSuccess would be called with nfcTag every time a tag was scanned. A breaking change is the callback would receive a tag not an event.
Maybe the new versions of these should be renamed, while the old versions are deprecated?
This change would apply to
var mime = "application/mah-phonegap-app";
var payload = nfc.stringToBytes(JSON.stringify(waitingForOrders.orders));
var record = ndef.mimeMediaRecord(mime, payload);
nfc.share(
[record],
function (){
console.log("NFC Share [Success]"); // <-- This never fires....
navigator.notification.vibrate(200);
},
function (reason){
console.log("problem with nfc.share :{0}".template([reason]));
}
);
I am expecting a success callback event when the ndef record is shared with a recipient, but it's not fired.
(Tested with plugin version at HEAD)
Hi Don,
Managed to get the phonegap nfc plugin working. Installed the reader demo, the app runs ok, no issues on the log, but when I read tags, I get all "undefined" for the tag type, max size etc...is tehre a step I skipped? I would like to read the tags unique id for starters. The app vibrates when it reads the tags and just shows "undefined" on each of the items. Any help? Thanks.
wtf happend to the formatting?
Add better documentation for nfcEvent.type = 'tag' and reading the NFC tag ID (not NDEF field ID)
If you register for the ACTION_TAG_DISCOVERED you will get a TAG event instead of a NDEF event in PhoneGap NFC.
(See http://developer.android.com/reference/android/nfc/NfcAdapter.html#ACTION_TAG_DISCOVERED)
The nfcEvent should look something like
{
type: "tag",
tag: {
"id": [ - 81, 105, -4, 64],
"techTypes": ["android.nfc.tech.MifareClassic", "android.nfc.tech.NfcA", "android.nfc.tech.NdefFormatable"]
}
}
Example code to read the NFC tag id
var ready = function() {
function nfcListener(nfcEvent) {
navigator.notification.alert(nfc.bytesToHexString(nfcEvent.tag.id), function() {}, "NFC Tag ID");
}
function win() {
console.log("Added Tag Discovered Listener");
}
function fail(reason) {
navigator.notification.alert(reason, function() {}, "There was a problem");
}
nfc.addTagDiscoveredListener(nfcListener, win, fail);
};
document.addEventListener('deviceready', ready, false);
Add cordova channels for nfc events so the plugin can be called when the javascript listeners are added
Then document.addEventListener("ndef", onNFC, false);
can be used instead of nfc.addNdefListener(onNFC, win, fail);
The following methods should call the error function when NFC is unavailable or disabled
This is related to NFC status #24
Scanning a tag with text/pg launches the demo, but does not scan the tag.
Hi. Using cordova 2.2.0, on blackberry dev alpha. Followed the steps required :
Please help. It works properly in android, but am not getting it to work on BB 10. Thanks in advance.
I'm creating an app which has an optional NFC feature.
I want to be able to detect if NFC is available or not so that I can enable or disable this feature accordingly.
Thanks!
Use .close();
First of all this is a great plugin!
One issue that I have (Samsung Galaxy Nexus) is that I wrote app that reads NFC tag. It works just fine when I first start app and put the tag to the phone.
Since I would like to make user experience better, I added Intent to manifest file which actually opens my application when I put NFC tag to my phone. But it seems that it does not trigger onNFC event.
Am I doing something wrong or is anyone experiencing the same issue?
it's any chance to creating working example with cordova?
Was having a lot of difficulty using uriRecord with web urls on my Nexus 7 and Galaxy Nexus. When reading the payload back off on a separate device, I would just get "U" in the default ndef handler.
I have a patch I can submit up as a pull request next week (didn't clone and have hacked around the file a lot), but basically I used Android's UriRecord.java as a reference and discovered there was a missing 0x00 prefixing the nfc.stringToBytes( text ) payload definition in uriRecord. I also used the TNF_WELL_KNOWN instead of TNF_ABSOLUTE_URI.
Tags tapped now open in the default browser.
Thanks much for your work on this - really helped us get a quick app off the ground.
Comparing types to RTD_* constants is clunky since arrays can't be compared.
This change will make the JavaScript more convenient
Converting the constants to Strings is OK, since most constructors now take Strings or [] and convert appropriately.
The native implementations probably don't need to change.
I haven't see a case where Type is not a String. Need to check the specs, but it would be nice if record.type and record.id could be strings and only payload would be a byte array.
/cc @tigoe
Hello guys, I just wanted to clarify something really. Now, I'm not overly knowledgeable about NFC but I know that you can use an NFC tag to open your application, right? But what I'm wondering is, could you also make that tag trigger an action within the app? So upon tapping the tag against the phone / tablet, it would open the app and trigger an event as well, such as opening a contact for example. And the contact that it would open would depend on the information in that specific tag? Is this possible?
I would really appreciate your help!
Thanks.
Implement nfc.share() for BB 10.
nfc.addMimeTypeListener("text/foo");
nfc.addMimeTypeListener("text/bar");
Update documentation. It is not clear that NdefMessage is an array of NdefRecords and the first argument to nfc.write and nfc.share is an array.
Some sample code in the documentation will help.
If the message exceeds the tag capacity on a formatted tag, the user receives a message "Tag capacity is 46 bytes, Message is 198 bytes"
If the tag is not formatted, the same write call formats the tag and gives an error "null"
Can we check the capacity of a tag before formatting?
In the current code, modifying intent filters or tech lists from JavaScript results in foreground dispatch being enabled on the NfcAdapter. These modifications may occur before onResume is called, resulting in an IllegalStateException.
Commit mzabaluev@d10fe6362d6bdfeb5e43e8b3dc154f41f56e7ee7 removes the state error.
Additionally, commit mzabaluev@98e6070d030bd9948a8e61a4b1d39c40c1f4fa8a resolves threading issues by synchronizing or context-passing the NFC dispatch and push data shared between the UI thread and the browser thread.
For your reference, the branch (based on my other changes) is posted here:
https://github.com/mzabaluev/phonegap-nfc/commits/lifecycle-fixes
Not an Issue report, just a helpful pointer when the JSON Error
pops up when writing or sharing a tag, it's due to the follow user error writing the method signature for nfc.share
or nfc.write
var record = ndef.textRecord("or any other ndef record creation method.");
nfc.share(record, onSuccessFunc, onFailFunc); // this will throw a JSON Error
The record must be in an array, ie.
var record = ndef.textRecord("or any other ndef record creation method.");
nfc.share( [ record ] , onSuccessFunc, onFailFunc);
// ⬆ ⬆
If this was an issue report (it's a bit late since this will already be used in implementation details downstream.) it'd be a suggestion to remove the array syntax (unless multiple tags are sharable/writable at once? @don possible?)
this needs to be replaced with NFC - we expose more than just ndef now.
The ndef event is never fired when reading some formatted empty NDEF tags.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.