@spencerls/react-native-nfc 1.0.7 → 1.0.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/API.md +471 -23
- package/README.md +192 -44
- package/dist/index.d.mts +184 -132
- package/dist/index.d.ts +184 -132
- package/dist/index.js +563 -300
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +563 -301
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,21 +1,45 @@
|
|
|
1
1
|
# @spencerls/react-native-nfc
|
|
2
2
|
|
|
3
|
-
A clean, React-friendly, cross-platform NFC layer built on top of
|
|
3
|
+
A clean, React-friendly, **cross-platform** NFC layer built on top of
|
|
4
4
|
`react-native-nfc-manager`.
|
|
5
5
|
|
|
6
|
+
## 🎯 Truly Cross-Platform
|
|
7
|
+
|
|
8
|
+
Write your NFC code once and it works on **both iOS and Android**.
|
|
9
|
+
The only platform-specific code is the optional Android reader mode configuration.
|
|
10
|
+
Everything else—reading, writing, and all NFC operations—uses the exact same API.
|
|
11
|
+
|
|
6
12
|
This package provides:
|
|
7
13
|
|
|
8
14
|
- A unified NFC service (`nfcService`)
|
|
9
|
-
- High-level protocol namespaces (`nfc.
|
|
15
|
+
- High-level protocol namespaces (`nfc.tag`, `nfc.v`, `nfc.ndef`)
|
|
16
|
+
- Low-level tag modules (`nfcTag`, `nfcVTag`, `nfcNdefTag`)
|
|
10
17
|
- Automatic iOS reader restarts
|
|
11
18
|
- Safe Android reader handling
|
|
12
19
|
- Optional React hooks and provider
|
|
13
|
-
- Technology sessions for NDEF/NfcV
|
|
20
|
+
- Technology sessions for NDEF/NfcV and raw commands
|
|
21
|
+
- Builder pattern for NDEF records
|
|
14
22
|
|
|
15
23
|
The API is designed to be stable, predictable, and easy to use across iOS and Android.
|
|
16
24
|
|
|
17
25
|
---
|
|
18
26
|
|
|
27
|
+
## Platform Support
|
|
28
|
+
|
|
29
|
+
| Feature | iOS | Android |
|
|
30
|
+
|---------|-----|---------|
|
|
31
|
+
| Reader Mode* | ❌ | ✅ |
|
|
32
|
+
| NDEF Read/Write | ✅ | ✅ |
|
|
33
|
+
| NFC-V (ISO15693) | ✅ | ✅ |
|
|
34
|
+
| Technology Sessions | ✅ | ✅ |
|
|
35
|
+
| React Hooks | ✅ | ✅ |
|
|
36
|
+
|
|
37
|
+
**\*Reader Mode** is Android's background NFC scanning API. iOS uses Technology Sessions instead.
|
|
38
|
+
**Platform-specific code:** Only `enableReaderMode_ANDROID()` is Android-specific (no-op on iOS).
|
|
39
|
+
All other APIs work identically on both platforms.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
19
43
|
## Installation
|
|
20
44
|
|
|
21
45
|
```bash
|
|
@@ -35,18 +59,23 @@ Works with:
|
|
|
35
59
|
## Basic Usage (Reader Mode)
|
|
36
60
|
|
|
37
61
|
```tsx
|
|
38
|
-
import { useNfc, useNfcState } from "@spencerls/react-native-nfc";
|
|
62
|
+
import { useNfc, useNfcState, nfcService } from "@spencerls/react-native-nfc";
|
|
39
63
|
import { NfcAdapter } from "react-native-nfc-manager";
|
|
40
64
|
|
|
41
65
|
export default function ScannerScreen() {
|
|
42
66
|
const { mode } = useNfcState();
|
|
43
67
|
|
|
68
|
+
// Platform-specific: Configure Android reader mode (no-op on iOS)
|
|
69
|
+
// Call once, typically at app startup or in useEffect
|
|
70
|
+
nfcService.enableReaderMode_ANDROID(
|
|
71
|
+
NfcAdapter.FLAG_READER_NFC_V |
|
|
72
|
+
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// Cross-platform: Works identically on iOS and Android
|
|
44
76
|
useNfc((tagId) => {
|
|
45
77
|
console.log("Scanned:", tagId);
|
|
46
78
|
}, {
|
|
47
|
-
flags:
|
|
48
|
-
NfcAdapter.FLAG_READER_NFC_V |
|
|
49
|
-
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
|
|
50
79
|
cooldownMs: 800
|
|
51
80
|
});
|
|
52
81
|
|
|
@@ -63,19 +92,22 @@ export default function ScannerScreen() {
|
|
|
63
92
|
## Manual Reader Control
|
|
64
93
|
|
|
65
94
|
```tsx
|
|
66
|
-
import { useNfcReader } from "@spencerls/react-native-nfc";
|
|
95
|
+
import { useNfcReader, nfcService } from "@spencerls/react-native-nfc";
|
|
67
96
|
import { NfcAdapter } from "react-native-nfc-manager";
|
|
68
97
|
|
|
69
98
|
export default function Screen() {
|
|
70
99
|
const { start, stop } = useNfcReader();
|
|
71
100
|
|
|
101
|
+
// Platform-specific: Configure Android reader mode (no-op on iOS)
|
|
102
|
+
nfcService.enableReaderMode_ANDROID(NfcAdapter.FLAG_READER_NFC_V);
|
|
103
|
+
|
|
72
104
|
const begin = () => {
|
|
105
|
+
// Cross-platform: Works identically on iOS and Android
|
|
73
106
|
start(
|
|
74
|
-
NfcAdapter.FLAG_READER_NFC_V,
|
|
75
107
|
(tag) => {
|
|
76
108
|
console.log("Tag:", tag.id);
|
|
77
109
|
},
|
|
78
|
-
1200
|
|
110
|
+
{ cooldownMs: 1200 }
|
|
79
111
|
);
|
|
80
112
|
};
|
|
81
113
|
|
|
@@ -85,70 +117,186 @@ export default function Screen() {
|
|
|
85
117
|
|
|
86
118
|
---
|
|
87
119
|
|
|
88
|
-
##
|
|
120
|
+
## Get Basic Tag Information
|
|
89
121
|
|
|
90
|
-
|
|
91
|
-
Do not pass raw strings.
|
|
122
|
+
**Cross-platform:** Works identically on iOS and Android.
|
|
92
123
|
|
|
93
124
|
```tsx
|
|
94
125
|
import { nfc } from "@spencerls/react-native-nfc";
|
|
95
|
-
import { useNfcTechnology } from "@spencerls/react-native-nfc";
|
|
96
126
|
import { NfcTech } from "react-native-nfc-manager";
|
|
97
127
|
|
|
98
|
-
export function
|
|
99
|
-
const
|
|
128
|
+
export default function ScanTagButton() {
|
|
129
|
+
const scanTag = async () => {
|
|
130
|
+
const tag = await nfc.tag.getTag([
|
|
131
|
+
NfcTech.NfcA,
|
|
132
|
+
NfcTech.NfcV,
|
|
133
|
+
NfcTech.Ndef,
|
|
134
|
+
]);
|
|
135
|
+
console.log("Tag ID:", tag.id);
|
|
136
|
+
console.log("Tag Type:", tag.type);
|
|
137
|
+
};
|
|
100
138
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
139
|
+
return <Button title="Scan Tag" onPress={scanTag} />;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## NDEF Write with Builder
|
|
146
|
+
|
|
147
|
+
**Cross-platform:** Works identically on iOS and Android.
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import { nfc } from "@spencerls/react-native-nfc";
|
|
151
|
+
|
|
152
|
+
export default function WriteNdefButton() {
|
|
153
|
+
const writeNdef = async () => {
|
|
154
|
+
await nfc.ndef.write(
|
|
155
|
+
nfc.ndef.Builder.records((B) => [
|
|
156
|
+
B.textRecord("Hello, world!"),
|
|
157
|
+
B.uriRecord("https://www.google.com"),
|
|
158
|
+
B.jsonRecord(
|
|
159
|
+
JSON.stringify({
|
|
160
|
+
name: "John Doe",
|
|
161
|
+
age: 30,
|
|
162
|
+
email: "john.doe@example.com",
|
|
163
|
+
})
|
|
164
|
+
),
|
|
165
|
+
])
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
return <Button title="Write NDEF" onPress={writeNdef} />;
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## NDEF Read
|
|
176
|
+
|
|
177
|
+
**Cross-platform:** Works identically on iOS and Android.
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
import { nfc } from "@spencerls/react-native-nfc";
|
|
181
|
+
|
|
182
|
+
export default function ReadNdefButton() {
|
|
183
|
+
const readNdef = async () => {
|
|
184
|
+
const { message, tag } = await nfc.ndef.readFull();
|
|
185
|
+
console.log("Tag ID:", tag.id);
|
|
186
|
+
console.log("Records:", message.ndefMessage);
|
|
106
187
|
};
|
|
107
188
|
|
|
108
|
-
return <Button title="Read
|
|
189
|
+
return <Button title="Read NDEF" onPress={readNdef} />;
|
|
109
190
|
}
|
|
110
191
|
```
|
|
111
192
|
|
|
112
193
|
---
|
|
113
194
|
|
|
114
|
-
##
|
|
195
|
+
## Custom NFC-V Operations
|
|
196
|
+
|
|
197
|
+
**Cross-platform:** Works identically on iOS and Android.
|
|
115
198
|
|
|
116
199
|
```tsx
|
|
117
|
-
import {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
200
|
+
import { nfc, nfcTag, nfcVTag } from "@spencerls/react-native-nfc";
|
|
201
|
+
|
|
202
|
+
export default function ReadNfcVButton() {
|
|
203
|
+
const readCustom = async () => {
|
|
204
|
+
const data = await nfc.service.withTechnology(nfcVTag.tech, async () => {
|
|
205
|
+
const tag = await nfcTag.getTag();
|
|
206
|
+
if (!tag?.id) throw new Error("No NFC-V tag detected");
|
|
207
|
+
|
|
208
|
+
const buffer = new Uint8Array();
|
|
209
|
+
let offset = 0;
|
|
210
|
+
|
|
211
|
+
// Read blocks 0, 2, 4, 6
|
|
212
|
+
for (let i = 0; i < 8; i += 2) {
|
|
213
|
+
const block = await nfcVTag.readBlock(tag.id, i);
|
|
214
|
+
buffer.set(block, offset);
|
|
215
|
+
offset += block.length;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return buffer;
|
|
129
219
|
});
|
|
220
|
+
|
|
221
|
+
console.log("Data:", data);
|
|
130
222
|
};
|
|
131
223
|
|
|
132
|
-
return <Button title="
|
|
224
|
+
return <Button title="Read NFC-V" onPress={readCustom} />;
|
|
133
225
|
}
|
|
134
226
|
```
|
|
135
227
|
|
|
136
228
|
---
|
|
137
229
|
|
|
138
|
-
##
|
|
230
|
+
## High-Level NFC-V Operations
|
|
139
231
|
|
|
140
|
-
|
|
232
|
+
**Cross-platform:** Works identically on iOS and Android.
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
141
235
|
import { nfc } from "@spencerls/react-native-nfc";
|
|
142
236
|
|
|
143
|
-
|
|
144
|
-
|
|
237
|
+
export default function NfcVScreen() {
|
|
238
|
+
const readBlock = async () => {
|
|
239
|
+
const data = await nfc.v.readBlock(0);
|
|
240
|
+
console.log("Block 0:", data);
|
|
241
|
+
};
|
|
145
242
|
|
|
146
|
-
|
|
243
|
+
const writeBlock = async () => {
|
|
244
|
+
const data = new Uint8Array([0x01, 0x02, 0x03, 0x04]);
|
|
245
|
+
await nfc.v.writeBlock(0, data);
|
|
246
|
+
};
|
|
147
247
|
|
|
148
|
-
|
|
248
|
+
const getInfo = async () => {
|
|
249
|
+
const info = await nfc.v.getSystemInfo();
|
|
250
|
+
console.log("System Info:", info);
|
|
251
|
+
};
|
|
149
252
|
|
|
150
|
-
|
|
151
|
-
|
|
253
|
+
return (
|
|
254
|
+
<View>
|
|
255
|
+
<Button title="Read Block" onPress={readBlock} />
|
|
256
|
+
<Button title="Write Block" onPress={writeBlock} />
|
|
257
|
+
<Button title="Get Info" onPress={getInfo} />
|
|
258
|
+
</View>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## API Overview
|
|
266
|
+
|
|
267
|
+
**Cross-platform:** All APIs below work identically on iOS and Android.
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
import { nfc, nfcTag, nfcVTag, nfcNdefTag } from "@spencerls/react-native-nfc";
|
|
271
|
+
|
|
272
|
+
// High-level namespace operations (auto-manages technology sessions)
|
|
273
|
+
await nfc.tag.getTag([NfcTech.NfcV]);
|
|
274
|
+
await nfc.v.readBlock(0);
|
|
275
|
+
await nfc.v.writeBlock(0, data);
|
|
276
|
+
await nfc.v.getSystemInfo();
|
|
277
|
+
await nfc.ndef.write(records);
|
|
278
|
+
await nfc.ndef.readMessage();
|
|
279
|
+
await nfc.ndef.readFull();
|
|
280
|
+
|
|
281
|
+
// Low-level tag modules (use inside withTechnology)
|
|
282
|
+
await nfc.service.withTechnology(nfcVTag.tech, async () => {
|
|
283
|
+
const tag = await nfcTag.getTag();
|
|
284
|
+
const block = await nfcVTag.readBlock(tag.id, 0);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// NDEF Builder
|
|
288
|
+
const records = nfc.ndef.Builder.records((B) => [
|
|
289
|
+
B.textRecord("Hello"),
|
|
290
|
+
B.uriRecord("https://example.com"),
|
|
291
|
+
B.jsonRecord(JSON.stringify({ key: "value" })),
|
|
292
|
+
B.mimeRecord("text/plain", "data"),
|
|
293
|
+
B.externalRecord("example.com", "type", "payload"),
|
|
294
|
+
]);
|
|
295
|
+
|
|
296
|
+
// Service control
|
|
297
|
+
nfc.service.enableReaderMode_ANDROID(flags); // Android-only (no-op on iOS)
|
|
298
|
+
await nfc.service.startReader(onTag, options); // Cross-platform
|
|
299
|
+
await nfc.service.stopReader(); // Cross-platform
|
|
152
300
|
```
|
|
153
301
|
|
|
154
302
|
---
|