@iotize/device-com-nfc.cordova 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +31 -0
  2. package/README.md +673 -0
  3. package/bundles/iotize-device-com-nfc.cordova.umd.js +469 -0
  4. package/bundles/iotize-device-com-nfc.cordova.umd.js.map +1 -0
  5. package/esm2015/iotize-device-com-nfc.cordova.js +5 -0
  6. package/esm2015/iotize-device-com-nfc.cordova.js.map +1 -0
  7. package/esm2015/iotize-device-com-nfc.cordova.metadata.json +1 -0
  8. package/esm2015/iotize-device-com-nfc.cordova.ngsummary.json +1 -0
  9. package/esm2015/public_api.js +2 -0
  10. package/esm2015/public_api.js.map +1 -0
  11. package/esm2015/public_api.metadata.json +1 -0
  12. package/esm2015/public_api.ngsummary.json +1 -0
  13. package/esm2015/www/cordova-interface.js +2 -0
  14. package/esm2015/www/cordova-interface.js.map +1 -0
  15. package/esm2015/www/cordova-interface.metadata.json +1 -0
  16. package/esm2015/www/cordova-interface.ngsummary.json +1 -0
  17. package/esm2015/www/errors.js +28 -0
  18. package/esm2015/www/errors.js.map +1 -0
  19. package/esm2015/www/errors.metadata.json +1 -0
  20. package/esm2015/www/errors.ngsummary.json +1 -0
  21. package/esm2015/www/index.js +5 -0
  22. package/esm2015/www/index.js.map +1 -0
  23. package/esm2015/www/index.metadata.json +1 -0
  24. package/esm2015/www/index.ngsummary.json +1 -0
  25. package/esm2015/www/logger.js +3 -0
  26. package/esm2015/www/logger.js.map +1 -0
  27. package/esm2015/www/logger.metadata.json +1 -0
  28. package/esm2015/www/logger.ngsummary.json +1 -0
  29. package/esm2015/www/nfc-com-protocol.js +109 -0
  30. package/esm2015/www/nfc-com-protocol.js.map +1 -0
  31. package/esm2015/www/nfc-com-protocol.metadata.json +1 -0
  32. package/esm2015/www/nfc-com-protocol.ngsummary.json +1 -0
  33. package/esm2015/www/tap-ndef/definitions.js +2 -0
  34. package/esm2015/www/tap-ndef/definitions.js.map +1 -0
  35. package/esm2015/www/tap-ndef/definitions.metadata.json +1 -0
  36. package/esm2015/www/tap-ndef/definitions.ngsummary.json +1 -0
  37. package/esm2015/www/tap-ndef/index.js +3 -0
  38. package/esm2015/www/tap-ndef/index.js.map +1 -0
  39. package/esm2015/www/tap-ndef/index.metadata.json +1 -0
  40. package/esm2015/www/tap-ndef/index.ngsummary.json +1 -0
  41. package/esm2015/www/tap-ndef/parse-ndef-message.js +57 -0
  42. package/esm2015/www/tap-ndef/parse-ndef-message.js.map +1 -0
  43. package/esm2015/www/tap-ndef/parse-ndef-message.metadata.json +1 -0
  44. package/esm2015/www/tap-ndef/parse-ndef-message.ngsummary.json +1 -0
  45. package/fesm2015/iotize-device-com-nfc.cordova.js +196 -0
  46. package/fesm2015/iotize-device-com-nfc.cordova.js.map +1 -0
  47. package/iotize-device-com-nfc.cordova.d.ts +4 -0
  48. package/iotize-device-com-nfc.cordova.metadata.json +1 -0
  49. package/package.json +54 -0
  50. package/plugin.xml +97 -0
  51. package/public_api.d.ts +1 -0
  52. package/src/android/build.gradle +38 -0
  53. package/src/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  54. package/src/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  55. package/src/android/gradlew +172 -0
  56. package/src/android/gradlew.bat +84 -0
  57. package/src/android/local.properties +8 -0
  58. package/src/android/src/com/chariotsolutions/nfc/plugin/JSONBuilder.java +60 -0
  59. package/src/android/src/com/chariotsolutions/nfc/plugin/NfcPlugin.java +1192 -0
  60. package/src/android/src/com/chariotsolutions/nfc/plugin/NfcPluginError.java +15 -0
  61. package/src/android/src/com/chariotsolutions/nfc/plugin/PluginResponse.java +85 -0
  62. package/src/android/src/com/chariotsolutions/nfc/plugin/Util.java +140 -0
  63. package/src/ios/AppDelegate+NFC.swift +51 -0
  64. package/src/ios/ISO15Reader.swift +376 -0
  65. package/src/ios/NFCNDEFDelegate.swift +78 -0
  66. package/src/ios/NFCPlugin-Bridging-Header.h +7 -0
  67. package/src/ios/NFCTapPlugin.swift +251 -0
  68. package/www/cordova-interface.d.ts +18 -0
  69. package/www/errors.d.ts +16 -0
  70. package/www/index.d.ts +4 -0
  71. package/www/logger.d.ts +2 -0
  72. package/www/nfc-com-protocol.d.ts +14 -0
  73. package/www/phonegap-nfc.js +885 -0
  74. package/www/tap-ndef/definitions.d.ts +25 -0
  75. package/www/tap-ndef/index.d.ts +2 -0
  76. package/www/tap-ndef/parse-ndef-message.d.ts +6 -0
@@ -0,0 +1,885 @@
1
+ /*jshint bitwise: false, camelcase: false, quotmark: false, unused: vars, esversion: 6, browser: true*/
2
+ /*global cordova, console, require */
3
+
4
+ function handleNfcFromIntentFilter() {
5
+
6
+ // This was historically done in cordova.addConstructor but broke with PhoneGap-2.2.0.
7
+ // We need to handle NFC from an Intent that launched the application, but *after*
8
+ // the code in the application's deviceready has run. After upgrading to 2.2.0,
9
+ // addConstructor was finishing *before* deviceReady was complete and the
10
+ // ndef listeners had not been registered.
11
+ // It seems like there should be a better solution.
12
+ if (cordova.platformId === "android" || cordova.platformId === "windows") {
13
+ setTimeout(
14
+ function () {
15
+ cordova.exec(
16
+ function () {
17
+ console.log("Initialized the NfcPlugin");
18
+ },
19
+ function (reason) {
20
+ console.log("Failed to initialize the NfcPlugin " + reason);
21
+ },
22
+ "NfcPlugin", "init", []
23
+ );
24
+ }, 10
25
+ );
26
+ }
27
+ }
28
+
29
+ document.addEventListener('deviceready', handleNfcFromIntentFilter, false);
30
+
31
+ var ndef = {
32
+
33
+ // see android.nfc.NdefRecord for documentation about constants
34
+ // http://developer.android.com/reference/android/nfc/NdefRecord.html
35
+ TNF_EMPTY: 0x0,
36
+ TNF_WELL_KNOWN: 0x01,
37
+ TNF_MIME_MEDIA: 0x02,
38
+ TNF_ABSOLUTE_URI: 0x03,
39
+ TNF_EXTERNAL_TYPE: 0x04,
40
+ TNF_UNKNOWN: 0x05,
41
+ TNF_UNCHANGED: 0x06,
42
+ TNF_RESERVED: 0x07,
43
+
44
+ RTD_TEXT: [0x54], // "T"
45
+ RTD_URI: [0x55], // "U"
46
+ RTD_SMART_POSTER: [0x53, 0x70], // "Sp"
47
+ RTD_ALTERNATIVE_CARRIER: [0x61, 0x63], // "ac"
48
+ RTD_HANDOVER_CARRIER: [0x48, 0x63], // "Hc"
49
+ RTD_HANDOVER_REQUEST: [0x48, 0x72], // "Hr"
50
+ RTD_HANDOVER_SELECT: [0x48, 0x73], // "Hs"
51
+
52
+ /**
53
+ * Creates a JSON representation of a NDEF Record.
54
+ *
55
+ * @tnf 3-bit TNF (Type Name Format) - use one of the TNF_* constants
56
+ * @type byte array, containing zero to 255 bytes, must not be null
57
+ * @id byte array, containing zero to 255 bytes, must not be null
58
+ * @payload byte array, containing zero to (2 ** 32 - 1) bytes, must not be null
59
+ *
60
+ * @returns JSON representation of a NDEF record
61
+ *
62
+ * @see Ndef.textRecord, Ndef.uriRecord and Ndef.mimeMediaRecord for examples
63
+ */
64
+ record: function (tnf, type, id, payload) {
65
+
66
+ // handle null values
67
+ if (!tnf) { tnf = ndef.TNF_EMPTY; }
68
+ if (!type) { type = []; }
69
+ if (!id) { id = []; }
70
+ if (!payload) { payload = []; }
71
+
72
+ // convert strings to arrays
73
+ if (!(type instanceof Array)) {
74
+ type = nfc.stringToBytes(type);
75
+ }
76
+ if (!(id instanceof Array)) {
77
+ id = nfc.stringToBytes(id);
78
+ }
79
+ if (!(payload instanceof Array)) {
80
+ payload = nfc.stringToBytes(payload);
81
+ }
82
+
83
+ return {
84
+ tnf: tnf,
85
+ type: type,
86
+ id: id,
87
+ payload: payload
88
+ };
89
+ },
90
+
91
+ /**
92
+ * Helper that creates an NDEF record containing plain text.
93
+ *
94
+ * @text String of text to encode
95
+ * @languageCode ISO/IANA language code. Examples: “fi”, “en-US”, “fr- CA”, “jp”. (optional)
96
+ * @id byte[] (optional)
97
+ */
98
+ textRecord: function (text, languageCode, id) {
99
+ var payload = textHelper.encodePayload(text, languageCode);
100
+ if (!id) { id = []; }
101
+ return ndef.record(ndef.TNF_WELL_KNOWN, ndef.RTD_TEXT, id, payload);
102
+ },
103
+
104
+ /**
105
+ * Helper that creates a NDEF record containing a URI.
106
+ *
107
+ * @uri String
108
+ * @id byte[] (optional)
109
+ */
110
+ uriRecord: function (uri, id) {
111
+ var payload = uriHelper.encodePayload(uri);
112
+ if (!id) { id = []; }
113
+ return ndef.record(ndef.TNF_WELL_KNOWN, ndef.RTD_URI, id, payload);
114
+ },
115
+
116
+ /**
117
+ * Helper that creates a NDEF record containing an absolute URI.
118
+ *
119
+ * An Absolute URI record means the URI describes the payload of the record.
120
+ *
121
+ * For example a SOAP message could use "http://schemas.xmlsoap.org/soap/envelope/"
122
+ * as the type and XML content for the payload.
123
+ *
124
+ * Absolute URI can also be used to write LaunchApp records for Windows.
125
+ *
126
+ * See 2.4.2 Payload Type of the NDEF Specification
127
+ * http://www.nfc-forum.org/specs/spec_list#ndefts
128
+ *
129
+ * Note that by default, Android will open the URI defined in the type
130
+ * field of an Absolute URI record (TNF=3) and ignore the payload.
131
+ * BlackBerry and Windows do not open the browser for TNF=3.
132
+ *
133
+ * To write a URI as the payload use ndef.uriRecord(uri)
134
+ *
135
+ * @uri String
136
+ * @payload byte[] or String
137
+ * @id byte[] (optional)
138
+ */
139
+ absoluteUriRecord: function (uri, payload, id) {
140
+ if (!id) { id = []; }
141
+ if (!payload) { payload = []; }
142
+ return ndef.record(ndef.TNF_ABSOLUTE_URI, uri, id, payload);
143
+ },
144
+
145
+ /**
146
+ * Helper that creates a NDEF record containing an mimeMediaRecord.
147
+ *
148
+ * @mimeType String
149
+ * @payload byte[]
150
+ * @id byte[] (optional)
151
+ */
152
+ mimeMediaRecord: function (mimeType, payload, id) {
153
+ if (!id) { id = []; }
154
+ return ndef.record(ndef.TNF_MIME_MEDIA, nfc.stringToBytes(mimeType), id, payload);
155
+ },
156
+
157
+ /**
158
+ * Helper that creates an NDEF record containing an Smart Poster.
159
+ *
160
+ * @ndefRecords array of NDEF Records
161
+ * @id byte[] (optional)
162
+ */
163
+ smartPoster: function (ndefRecords, id) {
164
+ var payload = [];
165
+
166
+ if (!id) { id = []; }
167
+
168
+ if (ndefRecords)
169
+ {
170
+ // make sure we have an array of something like NDEF records before encoding
171
+ if (ndefRecords[0] instanceof Object && ndefRecords[0].hasOwnProperty('tnf')) {
172
+ payload = ndef.encodeMessage(ndefRecords);
173
+ } else {
174
+ // assume the caller has already encoded the NDEF records into a byte array
175
+ payload = ndefRecords;
176
+ }
177
+ } else {
178
+ console.log("WARNING: Expecting an array of NDEF records");
179
+ }
180
+
181
+ return ndef.record(ndef.TNF_WELL_KNOWN, ndef.RTD_SMART_POSTER, id, payload);
182
+ },
183
+
184
+ /**
185
+ * Helper that creates an empty NDEF record.
186
+ *
187
+ */
188
+ emptyRecord: function() {
189
+ return ndef.record(ndef.TNF_EMPTY, [], [], []);
190
+ },
191
+
192
+ /**
193
+ * Helper that creates an Android Application Record (AAR).
194
+ * http://developer.android.com/guide/topics/connectivity/nfc/nfc.html#aar
195
+ *
196
+ */
197
+ androidApplicationRecord: function(packageName) {
198
+ return ndef.record(ndef.TNF_EXTERNAL_TYPE, "android.com:pkg", [], packageName);
199
+ },
200
+
201
+ /**
202
+ * Encodes an NDEF Message into bytes that can be written to a NFC tag.
203
+ *
204
+ * @ndefRecords an Array of NDEF Records
205
+ *
206
+ * @returns byte array
207
+ *
208
+ * @see NFC Data Exchange Format (NDEF) http://www.nfc-forum.org/specs/spec_list/
209
+ */
210
+ encodeMessage: function (ndefRecords) {
211
+
212
+ var encoded = [],
213
+ tnf_byte,
214
+ type_length,
215
+ payload_length,
216
+ id_length,
217
+ i,
218
+ mb, me, // messageBegin, messageEnd
219
+ cf = false, // chunkFlag TODO implement
220
+ sr, // boolean shortRecord
221
+ il; // boolean idLengthFieldIsPresent
222
+
223
+ for(i = 0; i < ndefRecords.length; i++) {
224
+
225
+ mb = (i === 0);
226
+ me = (i === (ndefRecords.length - 1));
227
+ sr = (ndefRecords[i].payload.length < 0xFF);
228
+ il = (ndefRecords[i].id.length > 0);
229
+ tnf_byte = ndef.encodeTnf(mb, me, cf, sr, il, ndefRecords[i].tnf);
230
+ encoded.push(tnf_byte);
231
+
232
+ type_length = ndefRecords[i].type.length;
233
+ encoded.push(type_length);
234
+
235
+ if (sr) {
236
+ payload_length = ndefRecords[i].payload.length;
237
+ encoded.push(payload_length);
238
+ } else {
239
+ payload_length = ndefRecords[i].payload.length;
240
+ // 4 bytes
241
+ encoded.push((payload_length >> 24));
242
+ encoded.push((payload_length >> 16));
243
+ encoded.push((payload_length >> 8));
244
+ encoded.push((payload_length & 0xFF));
245
+ }
246
+
247
+ if (il) {
248
+ id_length = ndefRecords[i].id.length;
249
+ encoded.push(id_length);
250
+ }
251
+
252
+ encoded = encoded.concat(ndefRecords[i].type);
253
+
254
+ if (il) {
255
+ encoded = encoded.concat(ndefRecords[i].id);
256
+ }
257
+
258
+ encoded = encoded.concat(ndefRecords[i].payload);
259
+ }
260
+
261
+ return encoded;
262
+ },
263
+
264
+ /**
265
+ * Decodes an array bytes into an NDEF Message
266
+ *
267
+ * @bytes an array bytes read from a NFC tag
268
+ *
269
+ * @returns array of NDEF Records
270
+ *
271
+ * @see NFC Data Exchange Format (NDEF) http://www.nfc-forum.org/specs/spec_list/
272
+ */
273
+ decodeMessage: function (ndefBytes) {
274
+
275
+ var bytes = ndefBytes.slice(0), // clone since parsing is destructive
276
+ ndef_message = [],
277
+ tnf_byte,
278
+ header,
279
+ type_length = 0,
280
+ payload_length = 0,
281
+ id_length = 0,
282
+ record_type = [],
283
+ id = [],
284
+ payload = [];
285
+
286
+ while(bytes.length) {
287
+ tnf_byte = bytes.shift();
288
+ header = ndef.decodeTnf(tnf_byte);
289
+
290
+ type_length = bytes.shift();
291
+
292
+ if (header.sr) {
293
+ payload_length = bytes.shift();
294
+ } else {
295
+ // next 4 bytes are length
296
+ payload_length = ((0xFF & bytes.shift()) << 24) |
297
+ ((0xFF & bytes.shift()) << 26) |
298
+ ((0xFF & bytes.shift()) << 8) |
299
+ (0xFF & bytes.shift());
300
+ }
301
+
302
+ if (header.il) {
303
+ id_length = bytes.shift();
304
+ }
305
+
306
+ record_type = bytes.splice(0, type_length);
307
+ id = bytes.splice(0, id_length);
308
+ payload = bytes.splice(0, payload_length);
309
+
310
+ ndef_message.push(
311
+ ndef.record(header.tnf, record_type, id, payload)
312
+ );
313
+
314
+ if (header.me) { break; } // last message
315
+ }
316
+
317
+ return ndef_message;
318
+ },
319
+
320
+ /**
321
+ * Decode the bit flags from a TNF Byte.
322
+ *
323
+ * @returns object with decoded data
324
+ *
325
+ * See NFC Data Exchange Format (NDEF) Specification Section 3.2 RecordLayout
326
+ */
327
+ decodeTnf: function (tnf_byte) {
328
+ return {
329
+ mb: (tnf_byte & 0x80) !== 0,
330
+ me: (tnf_byte & 0x40) !== 0,
331
+ cf: (tnf_byte & 0x20) !== 0,
332
+ sr: (tnf_byte & 0x10) !== 0,
333
+ il: (tnf_byte & 0x8) !== 0,
334
+ tnf: (tnf_byte & 0x7)
335
+ };
336
+ },
337
+
338
+ /**
339
+ * Encode NDEF bit flags into a TNF Byte.
340
+ *
341
+ * @returns tnf byte
342
+ *
343
+ * See NFC Data Exchange Format (NDEF) Specification Section 3.2 RecordLayout
344
+ */
345
+ encodeTnf: function (mb, me, cf, sr, il, tnf) {
346
+
347
+ var value = tnf;
348
+
349
+ if (mb) {
350
+ value = value | 0x80;
351
+ }
352
+
353
+ if (me) {
354
+ value = value | 0x40;
355
+ }
356
+
357
+ // note if cf: me, mb, li must be false and tnf must be 0x6
358
+ if (cf) {
359
+ value = value | 0x20;
360
+ }
361
+
362
+ if (sr) {
363
+ value = value | 0x10;
364
+ }
365
+
366
+ if (il) {
367
+ value = value | 0x8;
368
+ }
369
+
370
+ return value;
371
+ },
372
+
373
+ /**
374
+ * Convert TNF to String for user friendly display
375
+ *
376
+ */
377
+ tnfToString: function (tnf) {
378
+ var value = tnf;
379
+
380
+ switch (tnf) {
381
+ case ndef.TNF_EMPTY:
382
+ value = "Empty";
383
+ break;
384
+ case ndef.TNF_WELL_KNOWN:
385
+ value = "Well Known";
386
+ break;
387
+ case ndef.TNF_MIME_MEDIA:
388
+ value = "Mime Media";
389
+ break;
390
+ case ndef.TNF_ABSOLUTE_URI:
391
+ value = "Absolute URI";
392
+ break;
393
+ case ndef.TNF_EXTERNAL_TYPE:
394
+ value = "External";
395
+ break;
396
+ case ndef.TNF_UNKNOWN:
397
+ value = "Unknown";
398
+ break;
399
+ case ndef.TNF_UNCHANGED:
400
+ value = "Unchanged";
401
+ break;
402
+ case ndef.TNF_RESERVED:
403
+ value = "Reserved";
404
+ break;
405
+ }
406
+ return value;
407
+ }
408
+
409
+ };
410
+
411
+ // nfc provides javascript wrappers to the native phonegap implementation
412
+ var nfc = {
413
+
414
+ // addTagDiscoveredListener: function (callback, win, fail) {
415
+ // document.addEventListener("tag", callback, false);
416
+ // cordova.exec(win, fail, "NfcPlugin", "registerTag", []);
417
+ // },
418
+
419
+ addMimeTypeListener: function (mimeType, callback, win, fail) {
420
+ document.addEventListener("ndef-mime", callback, false);
421
+ cordova.exec(win, fail, "NfcPlugin", "registerMimeType", [mimeType]);
422
+ },
423
+
424
+ addNdefListener: function (callback, win, fail) {
425
+ document.addEventListener("ndef", callback, false);
426
+ cordova.exec(win, fail, "NfcPlugin", "registerNdef", []);
427
+ },
428
+
429
+ addTapDeviceListener: function (callback, win, fail) {
430
+ document.addEventListener("nfc-tap-device", callback, false);
431
+ win();
432
+ // cordova.exec(win, fail, "NfcPlugin", "registerTapDevice", [
433
+ // JSON.stringify(options)
434
+ // ]);
435
+ },
436
+
437
+ // addNdefFormatableListener: function (callback, win, fail) {
438
+ // document.addEventListener("ndef-formatable", callback, false);
439
+ // cordova.exec(win, fail, "NfcPlugin", "registerNdefFormatable", []);
440
+ // },
441
+
442
+ // write: function (ndefMessage, win, fail) {
443
+ // cordova.exec(win, fail, "NfcPlugin", "writeTag", [ndefMessage]);
444
+ // },
445
+
446
+ // makeReadOnly: function (win, fail) {
447
+ // cordova.exec(win, fail, "NfcPlugin", "makeReadOnly", []);
448
+ // },
449
+
450
+ // share: function (ndefMessage, win, fail) {
451
+ // cordova.exec(win, fail, "NfcPlugin", "shareTag", [ndefMessage]);
452
+ // },
453
+
454
+ // unshare: function (win, fail) {
455
+ // cordova.exec(win, fail, "NfcPlugin", "unshareTag", []);
456
+ // },
457
+
458
+ // handover: function (uris, win, fail) {
459
+ // // if we get a single URI, wrap it in an array
460
+ // if (!Array.isArray(uris)) {
461
+ // uris = [ uris ];
462
+ // }
463
+ // cordova.exec(win, fail, "NfcPlugin", "handover", uris);
464
+ // },
465
+
466
+ // stopHandover: function (win, fail) {
467
+ // cordova.exec(win, fail, "NfcPlugin", "stopHandover", []);
468
+ // },
469
+
470
+ // erase: function (win, fail) {
471
+ // cordova.exec(win, fail, "NfcPlugin", "eraseTag", [[]]);
472
+ // },
473
+
474
+ enabled: function (win, fail) {
475
+ cordova.exec(win, fail, "NfcPlugin", "enabled", [[]]);
476
+ },
477
+
478
+ // removeTagDiscoveredListener: function (callback, win, fail) {
479
+ // document.removeEventListener("tag", callback, false);
480
+ // cordova.exec(win, fail, "NfcPlugin", "removeTag", []);
481
+ // },
482
+
483
+ removeMimeTypeListener: function(mimeType, callback, win, fail) {
484
+ document.removeEventListener("ndef-mime", callback, false);
485
+ cordova.exec(win, fail, "NfcPlugin", "removeMimeType", [mimeType]);
486
+ },
487
+
488
+ removeNdefListener: function (callback, win, fail) {
489
+ document.removeEventListener("ndef", callback, false);
490
+ cordova.exec(win, fail, "NfcPlugin", "removeNdef", []);
491
+ },
492
+
493
+ showSettings: function (win, fail) {
494
+ cordova.exec(win, fail, "NfcPlugin", "showSettings", []);
495
+ },
496
+
497
+ // iOS only
498
+
499
+ beginNDEFSession: function (win, fail) {
500
+ cordova.exec(win, fail, "NfcPlugin", "beginNDEFSession", []);
501
+ },
502
+
503
+ // iOS only
504
+
505
+ invalidateNDEFSession: function (win, fail) {
506
+ cordova.exec(win, fail, 'NfcPlugin', 'invalidateNDEFSession', []);
507
+ },
508
+
509
+ connect: function(tech, timeout) {
510
+ return new Promise(function(resolve, reject) {
511
+ cordova.exec(resolve, reject, 'NfcPlugin', 'connect', [tech, timeout]);
512
+ });
513
+ },
514
+
515
+ close: function() {
516
+ return new Promise(function(resolve, reject) {
517
+ cordova.exec(resolve, reject, 'NfcPlugin', 'close', []);
518
+ });
519
+ },
520
+
521
+ // data - ArrayBuffer or string of hex data for transcieve
522
+ // the results of transcieve are returned in the promise success as an ArrayBuffer
523
+ transceive: function(data) {
524
+ return new Promise(function(resolve, reject) {
525
+
526
+ var buffer;
527
+ if (typeof data === 'string') {
528
+ buffer = util.hexStringToArrayBuffer(data);
529
+ } else if (data instanceof ArrayBuffer) {
530
+ buffer = data;
531
+ } else if (data instanceof Uint8Array) {
532
+ buffer = data.buffer;
533
+ } else {
534
+ reject("Expecting an ArrayBuffer or String");
535
+ }
536
+
537
+ cordova.exec(resolve, reject, 'NfcPlugin', 'transceive', [buffer]);
538
+ });
539
+ },
540
+
541
+ // // Android NfcAdapter.enableReaderMode flags
542
+ // FLAG_READER_NFC_A: 0x1,
543
+ // FLAG_READER_NFC_B: 0x2,
544
+ // FLAG_READER_NFC_F: 0x4,
545
+ // FLAG_READER_NFC_V: 0x8,
546
+ // FLAG_READER_NFC_BARCODE: 0x10,
547
+ // FLAG_READER_SKIP_NDEF_CHECK: 0x80,
548
+ // FLAG_READER_NO_PLATFORM_SOUNDS: 0x100,
549
+
550
+ // // Android NfcAdapter.enabledReaderMode
551
+ // readerMode: function(flags, readCallback, errorCallback) {
552
+ // cordova.exec(readCallback, errorCallback, 'NfcPlugin', 'readerMode', [flags]);
553
+ // },
554
+
555
+ // disableReaderMode: function(successCallback, errorCallback) {
556
+ // cordova.exec(successCallback, errorCallback, 'NfcPlugin', 'disableReaderMode', []);
557
+ // }
558
+
559
+ };
560
+
561
+ var util = {
562
+ // i must be <= 256
563
+ toHex: function (i) {
564
+ var hex;
565
+
566
+ if (i < 0) {
567
+ i += 256;
568
+ }
569
+
570
+ hex = i.toString(16);
571
+
572
+ // zero padding
573
+ if (hex.length === 1) {
574
+ hex = "0" + hex;
575
+ }
576
+
577
+ return hex;
578
+ },
579
+
580
+ toPrintable: function(i) {
581
+
582
+ if (i >= 0x20 & i <= 0x7F) {
583
+ return String.fromCharCode(i);
584
+ } else {
585
+ return '.';
586
+ }
587
+ },
588
+
589
+ bytesToString: function(bytes) {
590
+ // based on http://ciaranj.blogspot.fr/2007/11/utf8-characters-encoding-in-javascript.html
591
+
592
+ var result = "";
593
+ var i, c, c1, c2, c3;
594
+ i = c = c1 = c2 = c3 = 0;
595
+
596
+ // Perform byte-order check.
597
+ if( bytes.length >= 3 ) {
598
+ if( (bytes[0] & 0xef) == 0xef && (bytes[1] & 0xbb) == 0xbb && (bytes[2] & 0xbf) == 0xbf ) {
599
+ // stream has a BOM at the start, skip over
600
+ i = 3;
601
+ }
602
+ }
603
+
604
+ while ( i < bytes.length ) {
605
+ c = bytes[i] & 0xff;
606
+
607
+ if ( c < 128 ) {
608
+
609
+ result += String.fromCharCode(c);
610
+ i++;
611
+
612
+ } else if ( (c > 191) && (c < 224) ) {
613
+
614
+ if ( i + 1 >= bytes.length ) {
615
+ throw "Un-expected encoding error, UTF-8 stream truncated, or incorrect";
616
+ }
617
+ c2 = bytes[i + 1] & 0xff;
618
+ result += String.fromCharCode( ((c & 31) << 6) | (c2 & 63) );
619
+ i += 2;
620
+
621
+ } else {
622
+
623
+ if ( i + 2 >= bytes.length || i + 1 >= bytes.length ) {
624
+ throw "Un-expected encoding error, UTF-8 stream truncated, or incorrect";
625
+ }
626
+ c2 = bytes[i + 1] & 0xff;
627
+ c3 = bytes[i + 2] & 0xff;
628
+ result += String.fromCharCode( ((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63) );
629
+ i += 3;
630
+
631
+ }
632
+ }
633
+ return result;
634
+ },
635
+
636
+ stringToBytes: function(string) {
637
+ // based on http://ciaranj.blogspot.fr/2007/11/utf8-characters-encoding-in-javascript.html
638
+
639
+ var bytes = [];
640
+
641
+ for (var n = 0; n < string.length; n++) {
642
+
643
+ var c = string.charCodeAt(n);
644
+
645
+ if (c < 128) {
646
+
647
+ bytes[bytes.length]= c;
648
+
649
+ } else if((c > 127) && (c < 2048)) {
650
+
651
+ bytes[bytes.length] = (c >> 6) | 192;
652
+ bytes[bytes.length] = (c & 63) | 128;
653
+
654
+ } else {
655
+
656
+ bytes[bytes.length] = (c >> 12) | 224;
657
+ bytes[bytes.length] = ((c >> 6) & 63) | 128;
658
+ bytes[bytes.length] = (c & 63) | 128;
659
+
660
+ }
661
+
662
+ }
663
+
664
+ return bytes;
665
+ },
666
+
667
+ bytesToHexString: function (bytes) {
668
+ var dec, hexstring, bytesAsHexString = "";
669
+ for (var i = 0; i < bytes.length; i++) {
670
+ if (bytes[i] >= 0) {
671
+ dec = bytes[i];
672
+ } else {
673
+ dec = 256 + bytes[i];
674
+ }
675
+ hexstring = dec.toString(16);
676
+ // zero padding
677
+ if (hexstring.length === 1) {
678
+ hexstring = "0" + hexstring;
679
+ }
680
+ bytesAsHexString += hexstring;
681
+ }
682
+ return bytesAsHexString;
683
+ },
684
+
685
+ // This function can be removed if record.type is changed to a String
686
+ /**
687
+ * Returns true if the record's TNF and type matches the supplied TNF and type.
688
+ *
689
+ * @record NDEF record
690
+ * @tnf 3-bit TNF (Type Name Format) - use one of the TNF_* constants
691
+ * @type byte array or String
692
+ */
693
+ isType: function(record, tnf, type) {
694
+ if (record.tnf === tnf) { // TNF is 3-bit
695
+ var recordType;
696
+ if (typeof(type) === 'string') {
697
+ recordType = type;
698
+ } else {
699
+ recordType = nfc.bytesToString(type);
700
+ }
701
+ return (nfc.bytesToString(record.type) === recordType);
702
+ }
703
+ return false;
704
+ },
705
+
706
+ /**
707
+ * Convert an ArrayBuffer to a hex string
708
+ *
709
+ * @param {ArrayBuffer} buffer
710
+ * @returns {srting} - hex representation of bytes e.g. 000407AF
711
+ */
712
+ arrayBufferToHexString: function(buffer) {
713
+ function toHexString(byte) {
714
+ return ('0' + (byte & 0xFF).toString(16)).slice(-2);
715
+ }
716
+ var typedArray = new Uint8Array(buffer);
717
+ var array = Array.from(typedArray); // need to convert to [] so our map result is not typed
718
+ var parts = array.map(function(i) { return toHexString(i) });
719
+
720
+ return parts.join('');
721
+ },
722
+
723
+ /**
724
+ * Convert a hex string to an ArrayBuffer.
725
+ *
726
+ * @param {string} hexString - hex representation of bytes
727
+ * @return {ArrayBuffer} - The bytes in an ArrayBuffer.
728
+ */
729
+ hexStringToArrayBuffer: function(hexString) {
730
+
731
+ // remove any delimiters - space, dash, or colon
732
+ hexString = hexString.replace(/[\s-:]/g, '');
733
+
734
+ // remove the leading 0x
735
+ hexString = hexString.replace(/^0x/, '');
736
+
737
+ // ensure even number of characters
738
+ if (hexString.length % 2 != 0) {
739
+ console.log('WARNING: expecting an even number of characters in the hexString');
740
+ }
741
+
742
+ // check for some non-hex characters
743
+ var bad = hexString.match(/[G-Z\s]/i);
744
+ if (bad) {
745
+ console.log('WARNING: found non-hex characters', bad);
746
+ }
747
+
748
+ // split the string into pairs of octets
749
+ var pairs = hexString.match(/[\dA-F]{2}/gi);
750
+
751
+ // convert the octets to integers
752
+ var ints = pairs.map(function(s) { return parseInt(s, 16) });
753
+
754
+ var array = new Uint8Array(ints);
755
+ return array.buffer;
756
+ }
757
+
758
+ };
759
+
760
+ // this is a module in ndef-js
761
+ var textHelper = {
762
+
763
+ decodePayload: function (data) {
764
+
765
+ var languageCodeLength = (data[0] & 0x3F), // 6 LSBs
766
+ languageCode = data.slice(1, 1 + languageCodeLength),
767
+ utf16 = (data[0] & 0x80) !== 0; // assuming UTF-16BE
768
+
769
+ // TODO need to deal with UTF in the future
770
+ if (utf16) {
771
+ console.log('WARNING: utf-16 data may not be handled properly for', languageCode);
772
+ }
773
+ // Use TextDecoder when we have enough browser support
774
+ // new TextDecoder('utf-8').decode(data.slice(languageCodeLength + 1));
775
+ // new TextDecoder('utf-16').decode(data.slice(languageCodeLength + 1));
776
+
777
+ return util.bytesToString(data.slice(languageCodeLength + 1));
778
+ },
779
+
780
+ // encode text payload
781
+ // @returns an array of bytes
782
+ encodePayload: function(text, lang, encoding) {
783
+
784
+ // ISO/IANA language code, but we're not enforcing
785
+ if (!lang) { lang = 'en'; }
786
+
787
+ var encoded = util.stringToBytes(lang + text);
788
+ encoded.unshift(lang.length);
789
+
790
+ return encoded;
791
+ }
792
+
793
+ };
794
+
795
+ // this is a module in ndef-js
796
+ var uriHelper = {
797
+ // URI identifier codes from URI Record Type Definition NFCForum-TS-RTD_URI_1.0 2006-07-24
798
+ // index in array matches code in the spec
799
+ protocols: [ "", "http://www.", "https://www.", "http://", "https://", "tel:", "mailto:", "ftp://anonymous:anonymous@", "ftp://ftp.", "ftps://", "sftp://", "smb://", "nfs://", "ftp://", "dav://", "news:", "telnet://", "imap:", "rtsp://", "urn:", "pop:", "sip:", "sips:", "tftp:", "btspp://", "btl2cap://", "btgoep://", "tcpobex://", "irdaobex://", "file://", "urn:epc:id:", "urn:epc:tag:", "urn:epc:pat:", "urn:epc:raw:", "urn:epc:", "urn:nfc:" ],
800
+
801
+ // decode a URI payload bytes
802
+ // @returns a string
803
+ decodePayload: function (data) {
804
+ var prefix = uriHelper.protocols[data[0]];
805
+ if (!prefix) { // 36 to 255 should be ""
806
+ prefix = "";
807
+ }
808
+ return prefix + util.bytesToString(data.slice(1));
809
+ },
810
+
811
+ // shorten a URI with standard prefix
812
+ // @returns an array of bytes
813
+ encodePayload: function (uri) {
814
+
815
+ var prefix,
816
+ protocolCode,
817
+ encoded;
818
+
819
+ // check each protocol, unless we've found a match
820
+ // "urn:" is the one exception where we need to keep checking
821
+ // slice so we don't check ""
822
+ uriHelper.protocols.slice(1).forEach(function(protocol) {
823
+ if ((!prefix || prefix === "urn:") && uri.indexOf(protocol) === 0) {
824
+ prefix = protocol;
825
+ }
826
+ });
827
+
828
+ if (!prefix) {
829
+ prefix = "";
830
+ }
831
+
832
+ encoded = util.stringToBytes(uri.slice(prefix.length));
833
+ protocolCode = uriHelper.protocols.indexOf(prefix);
834
+ // prepend protocol code
835
+ encoded.unshift(protocolCode);
836
+
837
+ return encoded;
838
+ }
839
+ };
840
+
841
+ // added since WP8 must call a named function, also used by iOS
842
+ // TODO consider switching NFC events from JS events to using the PG callbacks
843
+ function fireNfcTagEvent(eventType, tagAsJson) {
844
+ setTimeout(function () {
845
+ var e = document.createEvent('Events');
846
+ e.initEvent(eventType, true, false);
847
+ e.tag = JSON.parse(tagAsJson);
848
+ console.log(e.tag);
849
+ document.dispatchEvent(e);
850
+ }, 10);
851
+ }
852
+
853
+ // textHelper and uriHelper aren't exported, add a property
854
+ ndef.uriHelper = uriHelper;
855
+ ndef.textHelper = textHelper;
856
+
857
+ // create aliases
858
+ nfc.bytesToString = util.bytesToString;
859
+ nfc.stringToBytes = util.stringToBytes;
860
+ nfc.bytesToHexString = util.bytesToHexString;
861
+
862
+ // kludge some global variables for plugman js-module support
863
+ // eventually these should be replaced and referenced via the module
864
+ window.nfc = nfc;
865
+ window.ndef = ndef;
866
+ window.util = util;
867
+ window.fireNfcTagEvent = fireNfcTagEvent;
868
+
869
+ // This channel receives nfcEvent data from native code
870
+ // and fires JavaScript events.
871
+ require('cordova/channel').onCordovaReady.subscribe(function() {
872
+ require('cordova/exec')(success, null, 'NfcPlugin', 'channel', []);
873
+ function success(message) {
874
+ if (!message.type) {
875
+ console.log(message);
876
+ } else {
877
+ console.log("Received NFC data, firing '" + message.type + "' event");
878
+ var e = document.createEvent('Events');
879
+ e.initEvent(message.type);
880
+ e.tap = message.tap;
881
+ e.tag = message.tag;
882
+ document.dispatchEvent(e);
883
+ }
884
+ }
885
+ });