react-native-nfc-manager 4.0.0-beta.6 → 4.0.0-beta.8

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 (107) hide show
  1. package/README.md +38 -4
  2. package/android/src/main/java/community/revteltech/nfc/MifareClassicHandler.java +419 -0
  3. package/android/src/main/java/community/revteltech/nfc/MifareUltralightHandler.java +84 -0
  4. package/android/src/main/java/community/revteltech/nfc/NdefHandler.java +373 -0
  5. package/android/src/main/java/community/revteltech/nfc/NfcAdapterStateChangedReceiver.java +48 -0
  6. package/android/src/main/java/community/revteltech/nfc/NfcErrorCodes.java +16 -0
  7. package/android/src/main/java/community/revteltech/nfc/NfcManager.java +339 -1125
  8. package/android/src/main/java/community/revteltech/nfc/NfcManagerIOSStubBase.java +130 -0
  9. package/android/src/main/java/community/revteltech/nfc/NfcTechIoRouter.java +258 -0
  10. package/android/src/main/java/community/revteltech/nfc/TagTechnologyRequest.java +19 -7
  11. package/android/src/main/java/community/revteltech/nfc/Util.java +201 -0
  12. package/dist/ndef-lib/constants.js +67 -0
  13. package/dist/ndef-lib/constants.js.map +1 -0
  14. package/dist/ndef-lib/index.js +79 -0
  15. package/dist/ndef-lib/index.js.map +1 -0
  16. package/dist/ndef-lib/ndef-text.js +29 -0
  17. package/dist/ndef-lib/ndef-text.js.map +1 -0
  18. package/dist/ndef-lib/ndef-uri.js +40 -0
  19. package/dist/ndef-lib/ndef-uri.js.map +1 -0
  20. package/dist/ndef-lib/ndef-wifi-simple.js +100 -0
  21. package/dist/ndef-lib/ndef-wifi-simple.js.map +1 -0
  22. package/dist/ndef-lib/ndef.js +153 -0
  23. package/dist/ndef-lib/ndef.js.map +1 -0
  24. package/dist/ndef-lib/stringifier.js +155 -0
  25. package/dist/ndef-lib/stringifier.js.map +1 -0
  26. package/dist/ndef-lib/util.js +126 -0
  27. package/dist/ndef-lib/util.js.map +1 -0
  28. package/dist/specs/NativeNfcManager.js +5 -0
  29. package/dist/specs/NativeNfcManager.js.map +1 -0
  30. package/dist/src/NativeNfcManager.js +55 -0
  31. package/dist/src/NativeNfcManager.js.map +1 -0
  32. package/dist/src/NfcError.js +220 -0
  33. package/dist/src/NfcError.js.map +1 -0
  34. package/dist/src/NfcManager.js +175 -0
  35. package/dist/src/NfcManager.js.map +1 -0
  36. package/dist/src/NfcManagerAndroid.js +112 -0
  37. package/dist/src/NfcManagerAndroid.js.map +1 -0
  38. package/dist/src/NfcManagerIOS.js +119 -0
  39. package/dist/src/NfcManagerIOS.js.map +1 -0
  40. package/dist/src/NfcTech/Iso15693HandlerIOS.js +99 -0
  41. package/dist/src/NfcTech/Iso15693HandlerIOS.js.map +1 -0
  42. package/dist/src/NfcTech/IsoDepHandler.js +29 -0
  43. package/dist/src/NfcTech/IsoDepHandler.js.map +1 -0
  44. package/dist/src/NfcTech/MifareClassicHandlerAndroid.js +68 -0
  45. package/dist/src/NfcTech/MifareClassicHandlerAndroid.js.map +1 -0
  46. package/dist/src/NfcTech/MifareUltralightHandlerAndroid.js +23 -0
  47. package/dist/src/NfcTech/MifareUltralightHandlerAndroid.js.map +1 -0
  48. package/dist/src/NfcTech/NdefFormatableHandlerAndroid.js +16 -0
  49. package/dist/src/NfcTech/NdefFormatableHandlerAndroid.js.map +1 -0
  50. package/dist/src/NfcTech/NdefHandler.js +54 -0
  51. package/dist/src/NfcTech/NdefHandler.js.map +1 -0
  52. package/dist/src/NfcTech/NfcAHandler.js +16 -0
  53. package/dist/src/NfcTech/NfcAHandler.js.map +1 -0
  54. package/dist/src/NfcTech/NfcVHandler.js +33 -0
  55. package/dist/src/NfcTech/NfcVHandler.js.map +1 -0
  56. package/dist/src/index.js +53 -0
  57. package/dist/src/index.js.map +1 -0
  58. package/index.d.ts +76 -43
  59. package/ios/NfcManager.h +2 -10
  60. package/ios/NfcManager.mm +176 -434
  61. package/ios/RNNfcBridgeUtil.h +28 -0
  62. package/ios/RNNfcBridgeUtil.mm +52 -0
  63. package/ios/RNNfcManager+Felica.swift +61 -0
  64. package/ios/RNNfcManager+Iso15693.swift +895 -0
  65. package/ios/RNNfcManager+IsoDep.swift +145 -0
  66. package/ios/RNNfcManager+Mifare.swift +61 -0
  67. package/ios/RNNfcManager+Ndef.swift +120 -0
  68. package/ios/RNNfcManager.h +251 -0
  69. package/ios/RNNfcManager.swift +648 -0
  70. package/ios/RNNfcSessionDelegateProxy.swift +104 -0
  71. package/ios/RNNfcSwiftUtil.swift +34 -0
  72. package/ndef-lib/{constants.js → constants.ts} +2 -0
  73. package/ndef-lib/{index.js → index.ts} +23 -12
  74. package/ndef-lib/{ndef-text.js → ndef-text.ts} +7 -2
  75. package/ndef-lib/{ndef-uri.js → ndef-uri.ts} +8 -3
  76. package/ndef-lib/{ndef-wifi-simple.js → ndef-wifi-simple.ts} +34 -11
  77. package/ndef-lib/{ndef.js → ndef.ts} +49 -20
  78. package/ndef-lib/{stringifier.js → stringifier.ts} +27 -10
  79. package/ndef-lib/{util.js → util.ts} +13 -8
  80. package/package.json +21 -7
  81. package/react-native-nfc-manager.podspec +3 -2
  82. package/specs/NativeNfcManager.ts +17 -4
  83. package/src/NativeNfcManager.ts +84 -0
  84. package/src/{NfcError.js → NfcError.ts} +6 -17
  85. package/src/{NfcManager.js → NfcManager.ts} +49 -34
  86. package/src/{NfcManagerAndroid.js → NfcManagerAndroid.ts} +25 -8
  87. package/src/{NfcManagerIOS.js → NfcManagerIOS.ts} +31 -10
  88. package/src/NfcTech/{Iso15693HandlerIOS.js → Iso15693HandlerIOS.ts} +64 -36
  89. package/src/NfcTech/{IsoDepHandler.js → IsoDepHandler.ts} +8 -5
  90. package/src/NfcTech/{MifareClassicHandlerAndroid.js → MifareClassicHandlerAndroid.ts} +33 -24
  91. package/src/NfcTech/{MifareUltralightHandlerAndroid.js → MifareUltralightHandlerAndroid.ts} +14 -5
  92. package/src/NfcTech/{NdefFormatableHandlerAndroid.js → NdefFormatableHandlerAndroid.ts} +9 -2
  93. package/src/NfcTech/{NdefHandler.js → NdefHandler.ts} +19 -6
  94. package/src/NfcTech/{NfcAHandler.js → NfcAHandler.ts} +6 -3
  95. package/src/NfcTech/{NfcVHandler.js → NfcVHandler.ts} +8 -5
  96. package/src/__mocks__/{NativeNfcManager.js → NativeNfcManager.ts} +4 -1
  97. package/src/{index.js → index.ts} +1 -1
  98. package/android/src/main/java/community/revteltech/nfc/JsonConvert.java +0 -141
  99. package/android/src/main/java/community/revteltech/nfc/MifareUtil.java +0 -84
  100. package/ios/NfcManager+Felica.mm +0 -43
  101. package/ios/NfcManager+Iso15693.mm +0 -600
  102. package/ios/NfcManager+IsoDep.mm +0 -83
  103. package/ios/NfcManager+Mifare.mm +0 -43
  104. package/ios/Util.mm +0 -55
  105. package/specs/NativeNfcManager.js +0 -3
  106. package/specs/NativeNfcManager.js.map +0 -1
  107. package/src/NativeNfcManager.js +0 -37
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # react-native-nfc-manager
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/react-native-nfc-manager.svg?style=flat)](https://www.npmjs.com/package/react-native-nfc-manager)
4
- [![build](https://api.travis-ci.org/whitedogg13/react-native-nfc-manager.svg?branch=master)](https://travis-ci.org/whitedogg13/react-native-nfc-manager)
4
+ [![CI](https://github.com/revtel/react-native-nfc-manager/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/revtel/react-native-nfc-manager/actions/workflows/ci.yml)
5
5
  [![issues](https://img.shields.io/github/issues/whitedogg13/react-native-nfc-manager.svg?style=flat)](https://github.com/whitedogg13/react-native-nfc-manager/issues)
6
6
 
7
7
  Bring NFC feature to React Native. Inspired by [phonegap-nfc](https://github.com/chariotsolutions/phonegap-nfc) and [react-native-ble-manager](https://github.com/innoveit/react-native-ble-manager)
@@ -14,8 +14,12 @@ Made with ❤️ by [whitedogg13](https://github.com/whitedogg13) and [revteltec
14
14
 
15
15
  ## Version Notes
16
16
 
17
- - `v3` only supports legacy architecture (latest release is `v3.16.2`).
18
- - `v4` supports new architecture (still in beta, latest release is `v4.0.0-beta.3`) .
17
+ - `v3` only supports legacy architecture (`v3.x.y`).
18
+ - `v4` targets the New Architecture and remains beta (`v4.0.0-beta.x`). Its support floor is React Native 0.76 with the New Architecture enabled; React Native 0.82 and newer are New Architecture only.
19
+
20
+ ## Support Policy
21
+
22
+ - See [Support Policy](./docs/SUPPORT_POLICY.md) for official React Native version window, architecture targets, and verification matrix.
19
23
 
20
24
  ## Table of Contents
21
25
 
@@ -28,6 +32,7 @@ Made with ❤️ by [whitedogg13](https://github.com/whitedogg13) and [revteltec
28
32
  7. [API](#api)
29
33
  8. [App demo](#appdemo)
30
34
  9. [Learn](#learn)
35
+ 10. [Development Example](#development-example)
31
36
 
32
37
  ## Installation
33
38
 
@@ -36,6 +41,9 @@ Made with ❤️ by [whitedogg13](https://github.com/whitedogg13) and [revteltec
36
41
  ```shell
37
42
  npm i --save react-native-nfc-manager
38
43
  ```
44
+
45
+ To evaluate the v4 beta, install an explicit `4.0.0-beta.x` version rather than relying on the default npm tag.
46
+
39
47
  ### iOS
40
48
 
41
49
  This library use native-modules, so you will need to do `pod install` for iOS:
@@ -43,6 +51,9 @@ This library use native-modules, so you will need to do `pod install` for iOS:
43
51
  ```shell
44
52
  cd ios && pod install && cd ..
45
53
  ```
54
+
55
+ Minimum Swift language version for iOS native sources is **Swift 5.7**.
56
+
46
57
  ### Android
47
58
 
48
59
  It should be properly auto-linked, so you don't need to do anything.
@@ -197,6 +208,28 @@ export default App;
197
208
 
198
209
  Check the full documentation that contains `examples`, `faq` and other topics like `Expo` in our [Wiki](https://github.com/revtel/react-native-nfc-manager/wiki)
199
210
 
211
+ ## Development Example
212
+
213
+ <a name="development-example"></a>
214
+
215
+ For local library development and physical-device NFC testing, use the React Native 0.84 New Architecture example app in [`example/`](./example). See [example/README.md](./example/README.md).
216
+
217
+ The example Jest suite mocks the native module and verifies application interactions only. It does not verify NFC hardware. Android and iOS compiler builds and physical-device checks are separate release gates.
218
+
219
+ ### Build (TypeScript)
220
+
221
+ This project now uses a TypeScript build flow and emits distributable JavaScript to [`dist/`](./dist):
222
+
223
+ ```shell
224
+ npm run build
225
+ ```
226
+
227
+ For package publishing, `prepack` runs the build automatically.
228
+
229
+ ### Routine CI
230
+
231
+ Routine CI uses Node.js 22 and runs dependency installation, the TypeScript build, lint, root Jest tests, and type checking. It deliberately does not run Android or iOS builds.
232
+
200
233
  ## Nfc Compatibility
201
234
 
202
235
  <a name="nfccompatibility"></a>
@@ -215,6 +248,8 @@ Check the full documentation that contains `examples`, `faq` and other topics li
215
248
  | `Iso15693IOS` | ❌ | ✅ |
216
249
  | `FelicaIOS` | ❌ | ✅ |
217
250
 
251
+ This table describes the intended platform API availability. It is not a record of the devices, OS versions, or tag technologies verified for a particular release; see the [Support Policy](./docs/SUPPORT_POLICY.md) for evidence labels and limitations.
252
+
218
253
  ## Usage concept
219
254
 
220
255
  <a name="usageconcept"></a>
@@ -293,4 +328,3 @@ We have a full featured NFC utility app using this library available for downloa
293
328
  We have published a React Native NFC course with [newline.co](https://www.newline.co/), check it out!
294
329
  - Free course (1 hour) about basic NFC setup and concept [here](https://www.youtube.com/watch?v=rAS-DvNUFck)
295
330
  - Full course (3 hours) for more (NDEF, Deep Linking, NTAG password protection, signature with UID) [here](https://www.newline.co/courses/newline-guide-to-nfcs-with-react-native)
296
-
@@ -0,0 +1,419 @@
1
+ package community.revteltech.nfc;
2
+
3
+ import static community.revteltech.nfc.NfcErrorCodes.*;
4
+
5
+ import android.nfc.TagLostException;
6
+ import android.nfc.tech.MifareClassic;
7
+
8
+ import com.facebook.react.bridge.Arguments;
9
+ import com.facebook.react.bridge.Callback;
10
+ import com.facebook.react.bridge.ReadableArray;
11
+ import com.facebook.react.bridge.WritableArray;
12
+
13
+ import java.util.Locale;
14
+
15
+ class MifareClassicHandler {
16
+ private MifareClassicHandler() {
17
+ }
18
+
19
+ static void putConstants(java.util.Map<String, Object> constants) {
20
+ constants.put("MIFARE_BLOCK_SIZE", MifareClassic.BLOCK_SIZE);
21
+ }
22
+
23
+ static void authenticate(
24
+ TagTechnologyRequest techRequest,
25
+ char type,
26
+ int sector,
27
+ ReadableArray key,
28
+ Callback callback
29
+ ) {
30
+ if (techRequest == null) {
31
+ callback.invoke(ERR_NO_TECH_REQ);
32
+ return;
33
+ }
34
+
35
+ try {
36
+ MifareClassic mifareTag = (MifareClassic) techRequest.getTechHandle();
37
+ if (mifareTag == null || mifareTag.getType() == MifareClassic.TYPE_UNKNOWN) {
38
+ callback.invoke("mifareClassicAuthenticate fail: TYPE_UNKNOWN");
39
+ return;
40
+ } else if (sector >= mifareTag.getSectorCount()) {
41
+ String msg = String.format(
42
+ Locale.US,
43
+ "mifareClassicAuthenticate fail: invalid sector %d (max %d)",
44
+ sector,
45
+ mifareTag.getSectorCount()
46
+ );
47
+ callback.invoke(msg);
48
+ return;
49
+ } else if (key.size() != 6) {
50
+ String msg = String.format(
51
+ Locale.US,
52
+ "mifareClassicAuthenticate fail: invalid key (needs length 6 but has %d characters)",
53
+ key.size()
54
+ );
55
+ callback.invoke(msg);
56
+ return;
57
+ }
58
+
59
+ boolean result;
60
+ if (type == 'A') {
61
+ result = mifareTag.authenticateSectorWithKeyA(sector, rnArrayToBytes(key));
62
+ } else {
63
+ result = mifareTag.authenticateSectorWithKeyB(sector, rnArrayToBytes(key));
64
+ }
65
+
66
+ if (!result) {
67
+ callback.invoke("mifareClassicAuthenticate fail: AUTH_FAIL");
68
+ return;
69
+ }
70
+
71
+ callback.invoke(null, true);
72
+ } catch (TagLostException ex) {
73
+ callback.invoke("mifareClassicAuthenticate fail: TAG_LOST");
74
+ } catch (Exception ex) {
75
+ callback.invoke("mifareClassicAuthenticate fail: " + ex);
76
+ }
77
+ }
78
+
79
+ static void getBlockCountInSector(
80
+ TagTechnologyRequest techRequest,
81
+ int sectorIndex,
82
+ Callback callback
83
+ ) {
84
+ if (techRequest == null) {
85
+ callback.invoke(ERR_NO_TECH_REQ);
86
+ return;
87
+ }
88
+
89
+ try {
90
+ MifareClassic mifareTag = getValidMifareClassic(techRequest, callback, "mifareClassicGetBlockCountInSector");
91
+ if (mifareTag == null) {
92
+ return;
93
+ }
94
+ if (sectorIndex >= mifareTag.getSectorCount()) {
95
+ String msg = String.format(
96
+ Locale.US,
97
+ "mifareClassicGetBlockCountInSector fail: invalid sector %d (max %d)",
98
+ sectorIndex,
99
+ mifareTag.getSectorCount()
100
+ );
101
+ callback.invoke(msg);
102
+ return;
103
+ }
104
+
105
+ callback.invoke(null, mifareTag.getBlockCountInSector(sectorIndex));
106
+ } catch (Exception ex) {
107
+ callback.invoke("mifareClassicGetBlockCountInSector fail: " + ex);
108
+ }
109
+ }
110
+
111
+ static void getSectorCount(TagTechnologyRequest techRequest, Callback callback) {
112
+ if (techRequest == null) {
113
+ callback.invoke(ERR_NO_TECH_REQ);
114
+ return;
115
+ }
116
+
117
+ try {
118
+ MifareClassic mifareTag = getValidMifareClassic(techRequest, callback, "mifareClassicGetSectorCount");
119
+ if (mifareTag == null) {
120
+ return;
121
+ }
122
+
123
+ callback.invoke(null, mifareTag.getSectorCount());
124
+ } catch (Exception ex) {
125
+ callback.invoke("mifareClassicGetSectorCount fail: " + ex);
126
+ }
127
+ }
128
+
129
+ static void sectorToBlock(
130
+ TagTechnologyRequest techRequest,
131
+ int sectorIndex,
132
+ Callback callback
133
+ ) {
134
+ if (techRequest == null) {
135
+ callback.invoke(ERR_NO_TECH_REQ);
136
+ return;
137
+ }
138
+
139
+ try {
140
+ MifareClassic mifareTag = getValidMifareClassic(techRequest, callback, "mifareClassicSectorToBlock");
141
+ if (mifareTag == null) {
142
+ return;
143
+ }
144
+ if (sectorIndex >= mifareTag.getSectorCount()) {
145
+ String msg = String.format(
146
+ Locale.US,
147
+ "mifareClassicSectorToBlock fail: invalid sector %d (max %d)",
148
+ sectorIndex,
149
+ mifareTag.getSectorCount()
150
+ );
151
+ callback.invoke(msg);
152
+ return;
153
+ }
154
+
155
+ callback.invoke(null, mifareTag.sectorToBlock(sectorIndex));
156
+ } catch (Exception ex) {
157
+ callback.invoke("mifareClassicSectorToBlock fail: " + ex);
158
+ }
159
+ }
160
+
161
+ static void readBlock(
162
+ TagTechnologyRequest techRequest,
163
+ int blockIndex,
164
+ Callback callback
165
+ ) {
166
+ if (techRequest == null) {
167
+ callback.invoke(ERR_NO_TECH_REQ);
168
+ return;
169
+ }
170
+
171
+ try {
172
+ MifareClassic mifareTag = getValidMifareClassic(techRequest, callback, "mifareClassicReadBlock");
173
+ if (mifareTag == null) {
174
+ return;
175
+ }
176
+ if (blockIndex >= mifareTag.getBlockCount()) {
177
+ String msg = String.format(
178
+ Locale.US,
179
+ "mifareClassicReadBlock fail: invalid block %d (max %d)",
180
+ blockIndex,
181
+ mifareTag.getBlockCount()
182
+ );
183
+ callback.invoke(msg);
184
+ return;
185
+ }
186
+
187
+ byte[] buffer = mifareTag.readBlock(blockIndex);
188
+ WritableArray result = bytesToRnArray(buffer);
189
+ callback.invoke(null, result);
190
+ } catch (TagLostException ex) {
191
+ callback.invoke("mifareClassicReadBlock fail: TAG_LOST");
192
+ } catch (Exception ex) {
193
+ callback.invoke("mifareClassicReadBlock fail: " + ex);
194
+ }
195
+ }
196
+
197
+ static void readSector(
198
+ TagTechnologyRequest techRequest,
199
+ int sectorIndex,
200
+ Callback callback
201
+ ) {
202
+ if (techRequest == null) {
203
+ callback.invoke(ERR_NO_TECH_REQ);
204
+ return;
205
+ }
206
+
207
+ try {
208
+ MifareClassic mifareTag = getValidMifareClassic(techRequest, callback, "mifareClassicReadSector");
209
+ if (mifareTag == null) {
210
+ return;
211
+ }
212
+ if (sectorIndex >= mifareTag.getSectorCount()) {
213
+ String msg = String.format(
214
+ Locale.US,
215
+ "mifareClassicReadSector fail: invalid sector %d (max %d)",
216
+ sectorIndex,
217
+ mifareTag.getSectorCount()
218
+ );
219
+ callback.invoke(msg);
220
+ return;
221
+ }
222
+
223
+ WritableArray result = Arguments.createArray();
224
+ int blocks = mifareTag.getBlockCountInSector(sectorIndex);
225
+ for (int i = 0; i < blocks; i++) {
226
+ byte[] buffer = mifareTag.readBlock(mifareTag.sectorToBlock(sectorIndex) + i);
227
+ appendBytesToRnArray(result, buffer);
228
+ }
229
+
230
+ callback.invoke(null, result);
231
+ } catch (TagLostException ex) {
232
+ callback.invoke("mifareClassicReadSector fail: TAG_LOST");
233
+ } catch (Exception ex) {
234
+ callback.invoke("mifareClassicReadSector fail: " + ex);
235
+ }
236
+ }
237
+
238
+ static void writeBlock(
239
+ TagTechnologyRequest techRequest,
240
+ int blockIndex,
241
+ ReadableArray block,
242
+ Callback callback
243
+ ) {
244
+ if (techRequest == null) {
245
+ callback.invoke(ERR_NO_TECH_REQ);
246
+ return;
247
+ }
248
+
249
+ try {
250
+ MifareClassic mifareTag = getValidMifareClassic(techRequest, callback, "mifareClassicWriteBlock");
251
+ if (mifareTag == null) {
252
+ return;
253
+ }
254
+ if (blockIndex >= mifareTag.getBlockCount()) {
255
+ String msg = String.format(
256
+ Locale.US,
257
+ "mifareClassicWriteBlock fail: invalid block %d (max %d)",
258
+ blockIndex,
259
+ mifareTag.getBlockCount()
260
+ );
261
+ callback.invoke(msg);
262
+ return;
263
+ }
264
+ if (block.size() != MifareClassic.BLOCK_SIZE) {
265
+ String msg = String.format(
266
+ Locale.US,
267
+ "mifareClassicWriteBlock fail: invalid block size %d (should be %d)",
268
+ block.size(),
269
+ MifareClassic.BLOCK_SIZE
270
+ );
271
+ callback.invoke(msg);
272
+ return;
273
+ }
274
+
275
+ byte[] buffer = rnArrayToBytes(block);
276
+ mifareTag.writeBlock(blockIndex, buffer);
277
+ callback.invoke(null, true);
278
+ } catch (TagLostException ex) {
279
+ callback.invoke("mifareClassicWriteBlock fail: TAG_LOST");
280
+ } catch (Exception ex) {
281
+ callback.invoke("mifareClassicWriteBlock fail: " + ex);
282
+ }
283
+ }
284
+
285
+ static void incrementBlock(
286
+ TagTechnologyRequest techRequest,
287
+ int blockIndex,
288
+ int value,
289
+ Callback callback
290
+ ) {
291
+ if (techRequest == null) {
292
+ callback.invoke(ERR_NO_TECH_REQ);
293
+ return;
294
+ }
295
+
296
+ try {
297
+ MifareClassic mifareTag = getValidMifareClassic(techRequest, callback, "mifareClassicIncrementBlock");
298
+ if (mifareTag == null) {
299
+ return;
300
+ }
301
+ if (blockIndex >= mifareTag.getBlockCount()) {
302
+ String msg = String.format(
303
+ Locale.US,
304
+ "mifareClassicIncrementBlock fail: invalid block %d (max %d)",
305
+ blockIndex,
306
+ mifareTag.getBlockCount()
307
+ );
308
+ callback.invoke(msg);
309
+ return;
310
+ }
311
+
312
+ mifareTag.increment(blockIndex, value);
313
+ callback.invoke(null, true);
314
+ } catch (TagLostException ex) {
315
+ callback.invoke("mifareClassicIncrementBlock fail: TAG_LOST");
316
+ } catch (Exception ex) {
317
+ callback.invoke("mifareClassicIncrementBlock fail: " + ex);
318
+ }
319
+ }
320
+
321
+ static void decrementBlock(
322
+ TagTechnologyRequest techRequest,
323
+ int blockIndex,
324
+ int value,
325
+ Callback callback
326
+ ) {
327
+ if (techRequest == null) {
328
+ callback.invoke(ERR_NO_TECH_REQ);
329
+ return;
330
+ }
331
+
332
+ try {
333
+ MifareClassic mifareTag = getValidMifareClassic(techRequest, callback, "mifareClassicDecrementBlock");
334
+ if (mifareTag == null) {
335
+ return;
336
+ }
337
+ if (blockIndex >= mifareTag.getBlockCount()) {
338
+ String msg = String.format(
339
+ Locale.US,
340
+ "mifareClassicDecrementBlock fail: invalid block %d (max %d)",
341
+ blockIndex,
342
+ mifareTag.getBlockCount()
343
+ );
344
+ callback.invoke(msg);
345
+ return;
346
+ }
347
+
348
+ mifareTag.decrement(blockIndex, value);
349
+ callback.invoke(null, true);
350
+ } catch (TagLostException ex) {
351
+ callback.invoke("mifareClassicDecrementBlock fail: TAG_LOST");
352
+ } catch (Exception ex) {
353
+ callback.invoke("mifareClassicDecrementBlock fail: " + ex);
354
+ }
355
+ }
356
+
357
+ static void transferBlock(
358
+ TagTechnologyRequest techRequest,
359
+ int blockIndex,
360
+ Callback callback
361
+ ) {
362
+ if (techRequest == null) {
363
+ callback.invoke(ERR_NO_TECH_REQ);
364
+ return;
365
+ }
366
+
367
+ try {
368
+ MifareClassic mifareTag = getValidMifareClassic(techRequest, callback, "mifareClassicTransferBlock");
369
+ if (mifareTag == null) {
370
+ return;
371
+ }
372
+ if (blockIndex >= mifareTag.getBlockCount()) {
373
+ String msg = String.format(
374
+ Locale.US,
375
+ "mifareClassicTransferBlock fail: invalid block %d (max %d)",
376
+ blockIndex,
377
+ mifareTag.getBlockCount()
378
+ );
379
+ callback.invoke(msg);
380
+ return;
381
+ }
382
+
383
+ mifareTag.transfer(blockIndex);
384
+ callback.invoke(null, true);
385
+ } catch (TagLostException ex) {
386
+ callback.invoke("mifareClassicTransferBlock fail: TAG_LOST");
387
+ } catch (Exception ex) {
388
+ callback.invoke("mifareClassicTransferBlock fail: " + ex);
389
+ }
390
+ }
391
+
392
+ private static MifareClassic getValidMifareClassic(TagTechnologyRequest techRequest, Callback callback, String opName) {
393
+ MifareClassic mifareTag = (MifareClassic) techRequest.getTechHandle();
394
+ if (mifareTag == null || mifareTag.getType() == MifareClassic.TYPE_UNKNOWN) {
395
+ callback.invoke(opName + " fail: TYPE_UNKNOWN");
396
+ return null;
397
+ }
398
+ return mifareTag;
399
+ }
400
+
401
+ private static byte[] rnArrayToBytes(ReadableArray rArray) {
402
+ byte[] bytes = new byte[rArray.size()];
403
+ for (int i = 0; i < rArray.size(); i++) {
404
+ bytes[i] = (byte) (rArray.getInt(i) & 0xff);
405
+ }
406
+ return bytes;
407
+ }
408
+
409
+ private static WritableArray bytesToRnArray(byte[] bytes) {
410
+ return appendBytesToRnArray(Arguments.createArray(), bytes);
411
+ }
412
+
413
+ private static WritableArray appendBytesToRnArray(WritableArray value, byte[] bytes) {
414
+ for (byte aByte : bytes) {
415
+ value.pushInt((aByte & 0xFF));
416
+ }
417
+ return value;
418
+ }
419
+ }
@@ -0,0 +1,84 @@
1
+ package community.revteltech.nfc;
2
+
3
+ import static community.revteltech.nfc.NfcErrorCodes.*;
4
+
5
+ import android.nfc.TagLostException;
6
+ import android.nfc.tech.MifareUltralight;
7
+
8
+ import com.facebook.react.bridge.Arguments;
9
+ import com.facebook.react.bridge.Callback;
10
+ import com.facebook.react.bridge.ReadableArray;
11
+ import com.facebook.react.bridge.WritableArray;
12
+
13
+ class MifareUltralightHandler {
14
+ private MifareUltralightHandler() {
15
+ }
16
+
17
+ static void putConstants(java.util.Map<String, Object> constants) {
18
+ constants.put("MIFARE_ULTRALIGHT_PAGE_SIZE", MifareUltralight.PAGE_SIZE);
19
+ constants.put("MIFARE_ULTRALIGHT_TYPE", MifareUltralight.TYPE_ULTRALIGHT);
20
+ constants.put("MIFARE_ULTRALIGHT_TYPE_C", MifareUltralight.TYPE_ULTRALIGHT_C);
21
+ constants.put("MIFARE_ULTRALIGHT_TYPE_UNKNOWN", MifareUltralight.TYPE_UNKNOWN);
22
+ }
23
+
24
+ static void readPages(
25
+ TagTechnologyRequest techRequest,
26
+ int pageOffset,
27
+ Callback callback
28
+ ) {
29
+ if (techRequest == null) {
30
+ callback.invoke(ERR_NO_TECH_REQ);
31
+ return;
32
+ }
33
+
34
+ try {
35
+ MifareUltralight techHandle = (MifareUltralight) techRequest.getTechHandle();
36
+ byte[] resultBytes = techHandle.readPages(pageOffset);
37
+ WritableArray resultRnArray = bytesToRnArray(resultBytes);
38
+ callback.invoke(null, resultRnArray);
39
+ } catch (TagLostException ex) {
40
+ callback.invoke("mifareUltralight fail: TAG_LOST");
41
+ } catch (Exception ex) {
42
+ callback.invoke("mifareUltralight fail: " + ex);
43
+ }
44
+ }
45
+
46
+ static void writePage(
47
+ TagTechnologyRequest techRequest,
48
+ int pageOffset,
49
+ ReadableArray rnArray,
50
+ Callback callback
51
+ ) {
52
+ if (techRequest == null) {
53
+ callback.invoke(ERR_NO_TECH_REQ);
54
+ return;
55
+ }
56
+
57
+ try {
58
+ byte[] bytes = rnArrayToBytes(rnArray);
59
+ MifareUltralight techHandle = (MifareUltralight) techRequest.getTechHandle();
60
+ techHandle.writePage(pageOffset, bytes);
61
+ callback.invoke();
62
+ } catch (TagLostException ex) {
63
+ callback.invoke("mifareUltralight fail: TAG_LOST");
64
+ } catch (Exception ex) {
65
+ callback.invoke("mifareUltralight fail: " + ex);
66
+ }
67
+ }
68
+
69
+ private static byte[] rnArrayToBytes(ReadableArray rArray) {
70
+ byte[] bytes = new byte[rArray.size()];
71
+ for (int i = 0; i < rArray.size(); i++) {
72
+ bytes[i] = (byte) (rArray.getInt(i) & 0xff);
73
+ }
74
+ return bytes;
75
+ }
76
+
77
+ private static WritableArray bytesToRnArray(byte[] bytes) {
78
+ WritableArray value = Arguments.createArray();
79
+ for (byte aByte : bytes) {
80
+ value.pushInt((aByte & 0xFF));
81
+ }
82
+ return value;
83
+ }
84
+ }