react-native-nfc-manager 4.0.0-beta.7 → 4.0.0-beta.9
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.
- package/README.md +37 -3
- package/android/src/main/java/community/revteltech/nfc/MifareClassicHandler.java +419 -0
- package/android/src/main/java/community/revteltech/nfc/MifareUltralightHandler.java +84 -0
- package/android/src/main/java/community/revteltech/nfc/NdefHandler.java +373 -0
- package/android/src/main/java/community/revteltech/nfc/NfcAdapterStateChangedReceiver.java +48 -0
- package/android/src/main/java/community/revteltech/nfc/NfcErrorCodes.java +16 -0
- package/android/src/main/java/community/revteltech/nfc/NfcManager.java +333 -1119
- package/android/src/main/java/community/revteltech/nfc/NfcManagerIOSStubBase.java +130 -0
- package/android/src/main/java/community/revteltech/nfc/NfcTechIoRouter.java +258 -0
- package/android/src/main/java/community/revteltech/nfc/TagTechnologyRequest.java +19 -7
- package/android/src/main/java/community/revteltech/nfc/Util.java +201 -0
- package/dist/ndef-lib/constants.js +67 -0
- package/dist/ndef-lib/constants.js.map +1 -0
- package/dist/ndef-lib/index.js +79 -0
- package/dist/ndef-lib/index.js.map +1 -0
- package/dist/ndef-lib/ndef-text.js +29 -0
- package/dist/ndef-lib/ndef-text.js.map +1 -0
- package/dist/ndef-lib/ndef-uri.js +40 -0
- package/dist/ndef-lib/ndef-uri.js.map +1 -0
- package/dist/ndef-lib/ndef-wifi-simple.js +100 -0
- package/dist/ndef-lib/ndef-wifi-simple.js.map +1 -0
- package/dist/ndef-lib/ndef.js +153 -0
- package/dist/ndef-lib/ndef.js.map +1 -0
- package/dist/ndef-lib/stringifier.js +155 -0
- package/dist/ndef-lib/stringifier.js.map +1 -0
- package/dist/ndef-lib/util.js +126 -0
- package/dist/ndef-lib/util.js.map +1 -0
- package/dist/specs/NativeNfcManager.js +5 -0
- package/dist/specs/NativeNfcManager.js.map +1 -0
- package/dist/src/NativeNfcManager.js +55 -0
- package/dist/src/NativeNfcManager.js.map +1 -0
- package/dist/src/NfcError.js +220 -0
- package/dist/src/NfcError.js.map +1 -0
- package/dist/src/NfcManager.js +175 -0
- package/dist/src/NfcManager.js.map +1 -0
- package/dist/src/NfcManagerAndroid.js +112 -0
- package/dist/src/NfcManagerAndroid.js.map +1 -0
- package/dist/src/NfcManagerIOS.js +119 -0
- package/dist/src/NfcManagerIOS.js.map +1 -0
- package/dist/src/NfcTech/Iso15693HandlerIOS.js +99 -0
- package/dist/src/NfcTech/Iso15693HandlerIOS.js.map +1 -0
- package/dist/src/NfcTech/IsoDepHandler.js +29 -0
- package/dist/src/NfcTech/IsoDepHandler.js.map +1 -0
- package/dist/src/NfcTech/MifareClassicHandlerAndroid.js +68 -0
- package/dist/src/NfcTech/MifareClassicHandlerAndroid.js.map +1 -0
- package/dist/src/NfcTech/MifareUltralightHandlerAndroid.js +23 -0
- package/dist/src/NfcTech/MifareUltralightHandlerAndroid.js.map +1 -0
- package/dist/src/NfcTech/NdefFormatableHandlerAndroid.js +16 -0
- package/dist/src/NfcTech/NdefFormatableHandlerAndroid.js.map +1 -0
- package/dist/src/NfcTech/NdefHandler.js +54 -0
- package/dist/src/NfcTech/NdefHandler.js.map +1 -0
- package/dist/src/NfcTech/NfcAHandler.js +16 -0
- package/dist/src/NfcTech/NfcAHandler.js.map +1 -0
- package/dist/src/NfcTech/NfcVHandler.js +33 -0
- package/dist/src/NfcTech/NfcVHandler.js.map +1 -0
- package/dist/src/index.js +53 -0
- package/dist/src/index.js.map +1 -0
- package/index.d.ts +76 -43
- package/ios/NfcManager.h +2 -10
- package/ios/NfcManager.mm +176 -434
- package/ios/RNNfcBridgeUtil.h +28 -0
- package/ios/RNNfcBridgeUtil.mm +52 -0
- package/ios/RNNfcManager+Felica.swift +61 -0
- package/ios/RNNfcManager+Iso15693.swift +895 -0
- package/ios/RNNfcManager+IsoDep.swift +145 -0
- package/ios/RNNfcManager+Mifare.swift +61 -0
- package/ios/RNNfcManager+Ndef.swift +120 -0
- package/ios/RNNfcManager.h +251 -0
- package/ios/RNNfcManager.swift +648 -0
- package/ios/RNNfcSessionDelegateProxy.swift +104 -0
- package/ios/RNNfcSwiftUtil.swift +34 -0
- package/ndef-lib/{constants.js → constants.ts} +2 -0
- package/ndef-lib/{index.js → index.ts} +23 -12
- package/ndef-lib/{ndef-text.js → ndef-text.ts} +7 -2
- package/ndef-lib/{ndef-uri.js → ndef-uri.ts} +8 -3
- package/ndef-lib/{ndef-wifi-simple.js → ndef-wifi-simple.ts} +34 -11
- package/ndef-lib/{ndef.js → ndef.ts} +49 -20
- package/ndef-lib/{stringifier.js → stringifier.ts} +27 -10
- package/ndef-lib/{util.js → util.ts} +13 -8
- package/package.json +21 -7
- package/react-native-nfc-manager.podspec +3 -2
- package/specs/NativeNfcManager.ts +17 -3
- package/src/NativeNfcManager.ts +84 -0
- package/src/{NfcError.js → NfcError.ts} +6 -17
- package/src/{NfcManager.js → NfcManager.ts} +49 -34
- package/src/{NfcManagerAndroid.js → NfcManagerAndroid.ts} +25 -8
- package/src/{NfcManagerIOS.js → NfcManagerIOS.ts} +31 -10
- package/src/NfcTech/{Iso15693HandlerIOS.js → Iso15693HandlerIOS.ts} +64 -36
- package/src/NfcTech/{IsoDepHandler.js → IsoDepHandler.ts} +8 -5
- package/src/NfcTech/{MifareClassicHandlerAndroid.js → MifareClassicHandlerAndroid.ts} +33 -24
- package/src/NfcTech/{MifareUltralightHandlerAndroid.js → MifareUltralightHandlerAndroid.ts} +14 -5
- package/src/NfcTech/{NdefFormatableHandlerAndroid.js → NdefFormatableHandlerAndroid.ts} +9 -2
- package/src/NfcTech/{NdefHandler.js → NdefHandler.ts} +19 -6
- package/src/NfcTech/{NfcAHandler.js → NfcAHandler.ts} +6 -3
- package/src/NfcTech/{NfcVHandler.js → NfcVHandler.ts} +8 -5
- package/src/__mocks__/{NativeNfcManager.js → NativeNfcManager.ts} +4 -1
- package/src/{index.js → index.ts} +1 -1
- package/android/src/main/java/community/revteltech/nfc/JsonConvert.java +0 -141
- package/android/src/main/java/community/revteltech/nfc/MifareUtil.java +0 -84
- package/ios/NfcManager+Felica.mm +0 -43
- package/ios/NfcManager+Iso15693.mm +0 -600
- package/ios/NfcManager+IsoDep.mm +0 -83
- package/ios/NfcManager+Mifare.mm +0 -43
- package/ios/Util.mm +0 -55
- package/specs/NativeNfcManager.js +0 -3
- package/specs/NativeNfcManager.js.map +0 -1
- package/src/NativeNfcManager.js +0 -37
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# react-native-nfc-manager
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/react-native-nfc-manager)
|
|
4
|
-
[](https://github.com/revtel/react-native-nfc-manager/actions/workflows/ci.yml)
|
|
5
5
|
[](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)
|
|
@@ -15,7 +15,11 @@ Made with ❤️ by [whitedogg13](https://github.com/whitedogg13) and [revteltec
|
|
|
15
15
|
## Version Notes
|
|
16
16
|
|
|
17
17
|
- `v3` only supports legacy architecture (`v3.x.y`).
|
|
18
|
-
- `v4`
|
|
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
|
+
}
|