phonegap-nfc
Advanced tools
Comparing version 0.6.5 to 0.6.6
@@ -0,1 +1,10 @@ | ||
= 0.6.6 = | ||
Update Windows platforms (includes Windows Phone 8.1) | ||
* tag event contains nested ndefMessage object #215 | ||
* support unformatted tags with addTagDiscoveredListener & removeTagDiscoveredListener #204 | ||
* implement showSettings #147 | ||
* better error messages when NFC is disabled #213 | ||
* use NDEF parsing and encoding code from www/phonegap-nfc.js (remove duplication) | ||
* update documentation | ||
= 0.6.5 = | ||
@@ -2,0 +11,0 @@ Add nfc.showSettings for Android and BlackBerry 10 #147 |
## Quickstart for PhoneGap NFC - Cordova CLI | ||
These instructions use [Cordova](http://cordova.apache.org/) to generate a default PhoneGap app and modify it to read NFC tags. | ||
These instructions use [Cordova](http://cordova.apache.org/) to generate a default PhoneGap app and modify it to read NFC tags. BlackBerry users should refer to [Getting Started with BlackBerry 10](https://github.com/chariotsolutions/phonegap-nfc/blob/master/doc/GettingStartedBlackBerry10.md). | ||
@@ -5,0 +5,0 @@ ### Cordova Command Line Interface (CLI) |
{ | ||
"name": "phonegap-nfc", | ||
"version": "0.6.5", | ||
"description": "Near Field Communication (NFC) Plugin. Read and write NDEF messages to tags or share NDEF messages with peers.", | ||
"version": "0.6.6", | ||
"description": "Near Field Communication (NFC) Plugin. Read and write NDEF messages to NFC tags and share NDEF messages with peers.", | ||
"cordova": { | ||
@@ -6,0 +6,0 @@ "id": "phonegap-nfc", |
PhoneGap NFC Plugin | ||
========================== | ||
Near Field Communication (NFC) Plugin. Read and write NDEF messages to tags or share NDEF messages with peers. | ||
The NFC plugin allows you to read and write NFC tags. You can also beam to, and receive from, other NFC enabled devices. | ||
Use to | ||
* read data from NFC tags | ||
* write data to NFC tags | ||
* send data to other NFC enabled devices | ||
* receive data from NFC devices | ||
This plugin uses NDEF (NFC Data Exchange Format) for maximum compatibilty between NFC devices, tag types, and operating systems. | ||
Supported Platforms | ||
------------------- | ||
* Android | ||
* Windows (includes Windows Phone 8.1, Windows 8.1, Windows 10) | ||
* BlackBerry 10 | ||
* Windows Phone 8 | ||
* BlackBerry 10 | ||
* BlackBerry 7 | ||
@@ -31,8 +40,23 @@ | ||
### Cordova | ||
$ cordova plugin add phonegap-nfc | ||
see [Getting Started](https://github.com/chariotsolutions/phonegap-nfc/blob/master/doc/GettingStartedCLI.md) for more details. | ||
### PhoneGap | ||
Note: BlackBerry 7 support is only available for Cordova 2.x. For applications targeting BlackBerry 7, you may need to use an older version of phonegap-nfc. | ||
$ phonegap plugin add phonegap-nfc | ||
### PhoneGap Build | ||
Edit config.xml to install the plugin for [PhoneGap Build](http://build.phonegap.com). | ||
<gap:plugin name="phonegap-nfc" source="npm" /> | ||
Windows Phone 8.1 should use the **windows** platform. The Silverlight based Windows Phone 8 code is no longer being maintained. | ||
BlackBerry 7 support is only available for Cordova 2.x. For applications targeting BlackBerry 7, you may need to use an older version of phonegap-nfc. | ||
See [Getting Started](https://github.com/chariotsolutions/phonegap-nfc/blob/master/doc/GettingStartedCLI.md) and [Getting Started BlackBerry 10](https://github.com/chariotsolutions/phonegap-nfc/blob/master/doc/GettingStartedBlackberry10.md)for more details. | ||
# NFC | ||
@@ -86,2 +110,3 @@ | ||
- Android | ||
- Windows | ||
- BlackBerry 7 | ||
@@ -106,2 +131,3 @@ - BlackBerry 10 | ||
- Android | ||
- Windows | ||
- BlackBerry 7 | ||
@@ -130,2 +156,3 @@ | ||
- Android | ||
- Windows | ||
- BlackBerry 7 | ||
@@ -148,2 +175,3 @@ | ||
- Android | ||
- Windows | ||
- BlackBerry 7 | ||
@@ -180,2 +208,3 @@ | ||
- Android | ||
- Windows | ||
- BlackBerry 7 | ||
@@ -247,4 +276,5 @@ | ||
On **Android** this method *must* be called from within an NDEF Event Handler. | ||
On **Windows** this method *may* be called from within the NDEF Event Handler. | ||
On **Windows Phone** this method should be called outside the NDEF Event Handler, otherwise Windows tries to read the tag contents as you are writing to the tag. | ||
On **Windows Phone 8.1** this method should be called outside the NDEF Event Handler, otherwise Windows tries to read the tag contents as you are writing to the tag. | ||
@@ -254,2 +284,3 @@ ### Supported Platforms | ||
- Android | ||
- Windows | ||
- BlackBerry 7 | ||
@@ -328,2 +359,3 @@ - Windows Phone 8 | ||
- Android | ||
- Windows | ||
- BlackBerry 7 | ||
@@ -357,2 +389,3 @@ - BlackBerry 10 | ||
- Android | ||
- Windows | ||
- BlackBerry 7 | ||
@@ -434,3 +467,3 @@ - BlackBerry 10 | ||
## showSettings | ||
## nfc.showSettings | ||
@@ -456,3 +489,5 @@ Show the NFC settings on the device. | ||
- Android | ||
- Android | ||
- Windows | ||
- BlackBerry 10 | ||
@@ -478,7 +513,10 @@ ## nfc.enabled | ||
Note: that on Android the NFC status is checked before every API call **NO_NFC** or **NFC_DISABLED** can be returned in **any** failure funtion. | ||
Note: that on Android the NFC status is checked before every API call **NO_NFC** or **NFC_DISABLED** can be returned in **any** failure function. | ||
Windows will return **NO_NFC_OR_NFC_DISABLED** when NFC is not present or disabled. If the user disabled NFC after the application started, Windows may return **NFC_DISABLED**. Windows checks the NFC status before most API calls, but there are some cases when the NFC state can not be determined. | ||
### Supported Platforms | ||
- Android | ||
- Windows | ||
@@ -567,3 +605,3 @@ # NDEF | ||
Windows Phone 8 and BlackBerry 10 read the NDEF information from a tag, but do not have access to the tag id or other meta data like capacity, read-only status or tag technologies. | ||
Windows, Windows Phone 8, and BlackBerry 10 read the NDEF information from a tag, but do not have access to the tag id or other meta data like capacity, read-only status or tag technologies. | ||
@@ -596,3 +634,2 @@ Assuming the following NDEF message is written to a tag, it will produce the following events when read. | ||
#### Sample Event on BlackBerry 7 | ||
@@ -619,3 +656,3 @@ | ||
#### Sample Event on BlackBerry 10 or Windows Phone 8 | ||
#### Sample Event on Windows, BlackBerry 10, or Windows Phone 8 | ||
@@ -634,3 +671,2 @@ { | ||
## Getting Details about Events | ||
@@ -646,11 +682,11 @@ | ||
Only Android and BlackBerry 7 can read Non-NDEF NFC tags. | ||
Only Android and BlackBerry 7 can read data from non-NDEF NFC tags. | ||
## Mifare Classic Tags | ||
BlackBerry 7, BlackBerry 10 and many newer Android phones will not read Mifare Classic tags. Mifare Ultralight tags will work since they are NFC Forum Type 2 tags. | ||
BlackBerry 7, BlackBerry 10 and many newer Android phones will not read Mifare Classic tags. Mifare Ultralight tags will work since they are NFC Forum Type 2 tags. Newer Windows 8.1 phones (Lumia 640) can read Mifare Classic tags. | ||
## Tag Id and Meta Data | ||
Windows Phone 8 and BlackBerry 10 read the NDEF information from a tag, but do not have access to the tag id or other meta data like capacity, read-only status or tag technologies. | ||
Windows Phone 8, BlackBerry 10, and Windows read the NDEF information from a tag, but do not have access to the tag id or other meta data like capacity, read-only status or tag technologies. | ||
@@ -663,2 +699,4 @@ ## Multiple Listeners | ||
For Windows, this plugin mimics the Android behavior. If an ndef event is fired, a tag event will not be fired. You should receive one event per tag. | ||
On BlackBerry 7, all the events fire if a Mime Media Tag is scanned. | ||
@@ -670,2 +708,4 @@ | ||
Windows can scan non-NDEF (unformatted) tags using addTagDiscoveredListener. The tag event will not include any data. | ||
On BlackBerry 7, addTagDiscoveredListener does NOT scan non-NDEF tags. Webworks returns the ndefMessage in the event. | ||
@@ -694,2 +734,10 @@ | ||
### Non-NDEF tag scanned with addTagDiscoveredListener on *Windows* | ||
{ | ||
type: 'tag', | ||
tag: { | ||
} | ||
} | ||
# BlackBerry 10 Invoke Target | ||
@@ -803,3 +851,3 @@ | ||
Copyright (c) 2011-2014 Chariot Solutions | ||
Copyright (c) 2011-2015 Chariot Solutions | ||
@@ -806,0 +854,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
@@ -0,5 +1,14 @@ | ||
/* globals: export, module, console, document, ndef, Windows, Uint8Array */ | ||
"use strict"; | ||
var STATUS_NFC_OK = "NFC_OK"; | ||
var STATUS_NO_NFC = "NO_NFC"; | ||
var STATUS_NFC_DISABLED = "NFC_DISABLED"; | ||
// I don't think there is a Windows API to determine if NFC exists | ||
var STATUS_NO_NFC_OR_NFC_DISABLED = "NO_NFC_OR_NFC_DISABLED"; | ||
var STATUS_NDEF_PUSH_DISABLED = "NDEF_PUSH_DISABLED"; | ||
var ndefUtils = { | ||
// convert Uint8Array to [] | ||
toArray: function (bytes) { | ||
@@ -12,197 +21,83 @@ var output = [], i = 0; | ||
return output; | ||
}, | ||
parse: function (bytes) { | ||
var records = [], | ||
index = 0, | ||
tnf_byte, mb, me, cf, sr, il, tnf, typeLength, idLength, payloadLength, type, id, payload, record; | ||
} | ||
}; | ||
while (index <= bytes.length) { | ||
tnf_byte = bytes[index]; | ||
mb = (tnf_byte & 0x80) != 0; | ||
me = (tnf_byte & 0x40) != 0; | ||
cf = (tnf_byte & 0x20) != 0; | ||
sr = (tnf_byte & 0x10) != 0; | ||
il = (tnf_byte & 0x8) != 0; | ||
tnf = tnf_byte & 0x7; | ||
if (cf) { | ||
// TODO implement me | ||
throw "Chunked records are not supported."; | ||
var self = { | ||
subscribedMessageId: -1, | ||
publishedMessageId: -1, | ||
proximityDeviceStatus: STATUS_NO_NFC_OR_NFC_DISABLED, | ||
listeningForNonNdefTags: false, | ||
tagEventTimeoutId: -1, | ||
initializeProximityDevice: function() { | ||
if (self.proximityDevice) { | ||
// TODO Is there an API to tell if the user disabled NFC? | ||
try { | ||
// KLUDGE this call fails when the user has disabled the device | ||
var kludge = self.proximityDevice.maxMessageBytes; | ||
self.proximityDeviceStatus = STATUS_NFC_OK; | ||
} catch (e) { | ||
console.log(e); | ||
self.proximityDeviceStatus = STATUS_NFC_DISABLED; | ||
} | ||
index++; | ||
typeLength = bytes[index]; | ||
idLength = 0; | ||
payloadLength = 0; | ||
if (sr) { | ||
index++; | ||
payloadLength = bytes[index]; | ||
} else { | ||
payloadLength = ((0xFF & bytes[++index]) << 24) | | ||
((0xFF & bytes[++index]) << 26) | | ||
((0xFF & bytes[++index]) << 8) | | ||
(0xFF & bytes[++index]); | ||
} | ||
if (il) { | ||
index++; | ||
idLength = bytes[index]; | ||
} | ||
index++; | ||
type = ndefUtils.toArray(bytes.subarray(index, typeLength + index)); | ||
index += typeLength; | ||
id = ndefUtils.toArray(bytes.subarray(index, idLength + index)); | ||
index += idLength; | ||
payload = ndefUtils.toArray(bytes.subarray(index, payloadLength + index)); | ||
index += payloadLength; | ||
record = ndefRecord(); | ||
record.tnf = tnf; | ||
record.type = typeLength > 0 ? type : []; | ||
record.id = idLength > 0 ? id : []; | ||
record.payload = payloadLength > 0 ? payload : []; | ||
records.push(record); | ||
if (me) { | ||
break; // last message | ||
} | ||
return self.proximityDeviceStatus === STATUS_NFC_OK; | ||
} | ||
return records; | ||
}, | ||
toBytes: function (records) { | ||
var encoded = [], | ||
mb, me, cf, sr, il, tnf_byte, type_length, payload_length, id_length; | ||
// try to get device again because user might have re-enabled the device | ||
self.proximityDevice = Windows.Networking.Proximity.ProximityDevice.getDefault(); | ||
for (var i = 0; i < records.length; i += 1) { | ||
mb = (i == 0); | ||
me = (i == (records.length - 1)); | ||
cf = false; // TODO | ||
sr = (records[i].payload.length < 0xFF); | ||
il = (records[i].id.Lenlengthgth > 0); | ||
// TODO use these events to implement nfc.addTagDiscoveredListener | ||
if (self.proximityDevice) { | ||
self.proximityDevice.ondevicearrived = function (eventArgs) { | ||
console.log("NFC tag detected"); | ||
if (self.listeningForNonNdefTags) { | ||
// set a timeout so NDEF tags can cancel this event | ||
// we want one event to mimic the Android behavior | ||
self.tagEventTimeoutId = setTimeout(self.fireTagEvent, 100); | ||
} | ||
}; | ||
tnf_byte = this.encodeTnf(mb, me, cf, sr, il, records[i].tnf); | ||
encoded.push(tnf_byte); | ||
type_length = records[i].type.length; | ||
encoded.push(type_length); | ||
payload_length = records[i].payload.length; | ||
if (sr) { | ||
encoded.push(payload_length); | ||
} else { | ||
// 4 bytes | ||
encoded.push((payload_length >> 24)); | ||
encoded.push((payload_length >> 16)); | ||
encoded.push((payload_length >> 8)); | ||
encoded.push((payload_length & 0xFF)); | ||
} | ||
id_length = 0; | ||
if (il) { | ||
id_length = records[i].id.length; | ||
encoded.push(id_length); | ||
} | ||
encoded = encoded.concat(records[i].type); | ||
if (il) { | ||
encoded = encoded.concat(records[i].id); | ||
} | ||
encoded = encoded.concat(records[i].payload); | ||
} | ||
return encoded; | ||
}, | ||
encodeTnf: function(mb, me, cf, sr, il, tnf) { | ||
var value = tnf; | ||
if (mb) { | ||
value = (value | 0x80); | ||
self.proximityDevice.ondevicedeparted = function (eventArgs) { | ||
console.log("NFC tag is gone"); | ||
}; | ||
} else { | ||
self.proximityDeviceStatus = STATUS_NO_NFC_OR_NFC_DISABLED; | ||
} | ||
if (me) { | ||
value = (value | 0x40); | ||
} | ||
return self.proximityDeviceStatus === STATUS_NFC_OK; | ||
}, | ||
init: function (success, failure, args) { | ||
if (cf) { | ||
value = (value | 0x20); | ||
} | ||
self.initializeProximityDevice(); | ||
if (sr) { | ||
value = (value | 0x10); | ||
if (!self.proximityDevice) { | ||
console.log("WARNING: proximity device is null"); | ||
} | ||
if (il) { | ||
value = (value | 0x8); | ||
} | ||
success(); | ||
}, | ||
registerNdef: function (success, failure, args) { | ||
console.log("Listening for NFC tags with NDEF messages."); | ||
if (cf) { | ||
if (!(tnf == 0x06 && !mb && !me && !il)) | ||
{ | ||
throw "When cf is true, mb, me and il must be false and tnf must be 0x6"; | ||
} | ||
} | ||
return value; | ||
} | ||
}; | ||
function ndefRecord() { | ||
return { | ||
tnf: [], | ||
type: [], | ||
id: [], | ||
payload: [] | ||
}; | ||
} | ||
var self = module.exports = { | ||
init: function (win, fail, args) { | ||
if (self._initialized) { | ||
if (win) { | ||
win(); | ||
} | ||
if (!self.initializeProximityDevice()) { | ||
failure(self.proximityDeviceStatus); | ||
return; | ||
} | ||
self.subscribedMessageId = -1; | ||
self.publishedMessageId = -1; | ||
self.proximityDevice = Windows.Networking.Proximity.ProximityDevice.getDefault(); | ||
if (!self.proximityDevice) { | ||
console.log("WARNING: proximity device is null"); | ||
if (fail) { | ||
fail(); | ||
} | ||
} | ||
self._initialized = true; | ||
}, | ||
registerNdef: function (win, fail, args) { | ||
self.init(); | ||
console.log("Registering for NDEF"); | ||
try { | ||
self.subscribedMessageId = self.proximityDevice.subscribeForMessage("NDEF", self.messageReceivedHandler); | ||
win(); | ||
success(); | ||
} catch (e) { | ||
console.log(e); | ||
fail(e); | ||
} | ||
failure(e); | ||
} | ||
}, | ||
removeNdef: function (win, fail, args) { | ||
self.init(); | ||
removeNdef: function (success, failure, args) { | ||
console.log("Removing NDEF"); | ||
console.log("Removing NDEF Listener"); | ||
if (!self.initializeProximityDevice()) { | ||
failure(self.proximityDeviceStatus); | ||
return; | ||
} | ||
try { | ||
@@ -214,16 +109,28 @@ if (self.subscribedMessageId !== -1) { | ||
win(); | ||
success(); | ||
} catch (e) { | ||
console.log(e); | ||
fail(e); | ||
} | ||
failure(e.message); | ||
} | ||
}, | ||
writeTag: function (win, fail, args) { | ||
self.init(); | ||
addTagDiscoveredListener: function(success, failure, args) { | ||
self.listeningForNonNdefTags = true; | ||
success(); | ||
}, | ||
remoteTagDiscoveredListener: function(success, failure, args) { | ||
self.listeningForNonNdefTags = false; | ||
success(); | ||
}, | ||
writeTag: function (success, failure, args) { | ||
console.log("Write Tag"); | ||
if (!self.initializeProximityDevice()) { | ||
failure(self.proximityDeviceStatus); | ||
return; | ||
} | ||
try { | ||
var records = args[0]; | ||
var bytes = ndefUtils.toBytes(records); | ||
var bytes = ndef.encodeMessage(records); | ||
@@ -239,21 +146,26 @@ self.stopPublishing(); | ||
function (sender, messageId) { | ||
console.log("Successfully wrote message to the NFC tag."); | ||
self.stopPublishing(); | ||
win(); | ||
}); | ||
console.log("Successfully wrote message to the NFC tag."); | ||
self.stopPublishing(); | ||
success(); | ||
} | ||
); | ||
} catch (e) { | ||
console.log(e); | ||
fail(e); | ||
failure(e.message); | ||
} | ||
}, | ||
shareTag: function(win, fail, args) { | ||
self.init(); | ||
shareTag: function(success, failure, args) { | ||
console.log("Share Tag"); | ||
if (!self.initializeProximityDevice()) { | ||
failure(self.proximityDeviceStatus); | ||
return; | ||
} | ||
try { | ||
var records = args[0]; | ||
var bytes = ndefUtils.toBytes(records); | ||
var bytes = ndef.encodeMessage(records); | ||
@@ -267,28 +179,57 @@ self.stopPublishing(); | ||
self.publishedMessageId = self.proximityDevice.publishBinaryMessage("NDEF", | ||
dataWriter.detachBuffer(), | ||
dataWriter.detachBuffer(), | ||
function (sender, messageId) { | ||
console.log("Successfully shared message over peer-to-peer."); | ||
self.stopPublishing(); | ||
console.log("Successfully shared message over peer-to-peer."); | ||
self.stopPublishing(); | ||
win(); | ||
}); | ||
success(); | ||
}); | ||
} catch (e) { | ||
console.log(e); | ||
fail(e); | ||
} | ||
failure(e.message); | ||
} | ||
}, | ||
unshareTag: function(win, fail, args) { | ||
self.init(); | ||
unshareTag: function(success, failure, args) { | ||
console.log("Unshare Tag"); | ||
if (!self.initializeProximityDevice()) { | ||
failure(self.proximityDeviceStatus); | ||
return; | ||
} | ||
try { | ||
self.stopPublishing(); | ||
win(); | ||
success(); | ||
} catch (e) { | ||
console.log(e); | ||
fail(e); | ||
failure(e.message); | ||
} | ||
}, | ||
enabled: function(success, failure, args) { | ||
self.initializeProximityDevice(); | ||
if (self.initializeProximityDevice()) { | ||
success(); | ||
} else { | ||
failure(self.proximityDeviceStatus); | ||
} | ||
}, | ||
showSettings: function(success, failure, args) { | ||
// WARNING: this isn't documented, so it might break | ||
var nfcSettingsUri = "ms-settings-proximity:"; | ||
var uri = new Windows.Foundation.Uri(nfcSettingsUri); | ||
Windows.System.Launcher.launchUriAsync(uri).then( | ||
function (settingsAppeared) { | ||
if (settingsAppeared) { | ||
success(); | ||
} else { | ||
failure(); | ||
} | ||
} | ||
); | ||
}, | ||
stopPublishing: function() { | ||
@@ -301,2 +242,6 @@ if (self.publishedMessageId !== -1) { | ||
messageReceivedHandler: function (sender, message) { | ||
// this is an NDEF message so cancel the tag event before it fires | ||
clearTimeout(self.tagEventTimeoutId); | ||
var bytes = new Uint8Array(message.data.length); | ||
@@ -307,9 +252,40 @@ var dataReader = Windows.Storage.Streams.DataReader.fromBuffer(message.data); | ||
var json = ndefUtils.parse(bytes); | ||
var byteArray = ndefUtils.toArray(bytes); | ||
var ndefMessage = ndef.decodeMessage(byteArray); | ||
console.log(JSON.stringify(ndefMessage)); | ||
fireNfcTagEvent("ndef", JSON.stringify(json)); | ||
// on windows, tag only contains the ndef message | ||
// other platforms have tag data | ||
var tag = { | ||
ndefMessage: ndefMessage | ||
}; | ||
// fire JavaScript event with NDEF data | ||
var e = document.createEvent('Events'); | ||
e.initEvent("ndef", true, false); | ||
e.tag = tag; | ||
document.dispatchEvent(e); | ||
}, | ||
fireTagEvent: function() { | ||
var e = document.createEvent('Events'); | ||
e.initEvent("tag", true, false); | ||
// unfortunately we don't have any tag metadata | ||
e.tag = {}; | ||
document.dispatchEvent(e); | ||
} | ||
}; // exports | ||
}; | ||
module.exports = { | ||
init: self.init, | ||
registerNdef: self.registerNdef, | ||
removeNdef: self.removeNdef, | ||
registerTag: self.addTagDiscoveredListener, | ||
remoteTag: self.removeTagDiscoveredListener, | ||
writeTag: self.writeTag, | ||
shareTag: self.shareTag, | ||
unshareTag: self.unshareTag, | ||
enabled: self.enabled, | ||
showSettings: self.showSettings | ||
} | ||
require("cordova/exec/proxy").add("NfcPlugin", module.exports); | ||
Sorry, the diff of this file is not supported yet
215516
24
849
2219