UNPKG

phonegap-nfc

Version:

Near Field Communication (NFC) Plugin. Read and write NDEF messages to NFC tags and share NDEF messages with peers.

286 lines (238 loc) 8.98 kB
/* 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) { var output = [], i = 0; for (; i < bytes.length; i += 1) { output.push(bytes[i]); } return output; } }; 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; } return self.proximityDeviceStatus === STATUS_NFC_OK; } // try to get device again because user might have re-enabled the device self.proximityDevice = Windows.Networking.Proximity.ProximityDevice.getDefault(); // 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); } }; self.proximityDevice.ondevicedeparted = function (eventArgs) { console.log("NFC tag is gone"); }; } else { self.proximityDeviceStatus = STATUS_NO_NFC_OR_NFC_DISABLED; } return self.proximityDeviceStatus === STATUS_NFC_OK; }, init: function (success, failure, args) { self.initializeProximityDevice(); if (!self.proximityDevice) { console.log("WARNING: proximity device is null"); } success(); }, registerNdef: function (success, failure, args) { console.log("Listening for NFC tags with NDEF messages."); if (!self.initializeProximityDevice()) { failure(self.proximityDeviceStatus); return; } try { self.subscribedMessageId = self.proximityDevice.subscribeForMessage("NDEF", self.messageReceivedHandler); success(); } catch (e) { console.log(e); failure(e); } }, removeNdef: function (success, failure, args) { console.log("Removing NDEF Listener"); if (!self.initializeProximityDevice()) { failure(self.proximityDeviceStatus); return; } try { if (self.subscribedMessageId !== -1) { self.proximityDevice.stopSubscribingForMessage(self.subscribedMessageId); self.subscribedMessageId = -1; } success(); } catch (e) { console.log(e); failure(e.message); } }, 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 = ndef.encodeMessage(records); self.stopPublishing(); var dataWriter = new Windows.Storage.Streams.DataWriter(); dataWriter.unicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.utf16LE; dataWriter.writeBytes(bytes); self.publishedMessageId = self.proximityDevice.publishBinaryMessage("NDEF:WriteTag", dataWriter.detachBuffer(), function (sender, messageId) { console.log("Successfully wrote message to the NFC tag."); self.stopPublishing(); success(); } ); } catch (e) { console.log(e); failure(e.message); } }, shareTag: function(success, failure, args) { console.log("Share Tag"); if (!self.initializeProximityDevice()) { failure(self.proximityDeviceStatus); return; } try { var records = args[0]; var bytes = ndef.encodeMessage(records); self.stopPublishing(); var dataWriter = new Windows.Storage.Streams.DataWriter(); dataWriter.unicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.utf16LE; dataWriter.writeBytes(bytes); self.publishedMessageId = self.proximityDevice.publishBinaryMessage("NDEF", dataWriter.detachBuffer(), function (sender, messageId) { console.log("Successfully shared message over peer-to-peer."); self.stopPublishing(); success(); }); } catch (e) { console.log(e); failure(e.message); } }, unshareTag: function(success, failure, args) { console.log("Unshare Tag"); if (!self.initializeProximityDevice()) { failure(self.proximityDeviceStatus); return; } try { self.stopPublishing(); success(); } catch (e) { console.log(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() { if (self.publishedMessageId !== -1) { self.proximityDevice.stopPublishingMessage(self.publishedMessageId); 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); var dataReader = Windows.Storage.Streams.DataReader.fromBuffer(message.data); dataReader.readBytes(bytes); dataReader.close(); var byteArray = ndefUtils.toArray(bytes); var ndefMessage = ndef.decodeMessage(byteArray); console.log(JSON.stringify(ndefMessage)); // 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); } }; 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);