@capgo/capacitor-nfc 7.0.0 → 7.0.2
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.
|
@@ -34,502 +34,503 @@ import org.json.JSONException;
|
|
|
34
34
|
|
|
35
35
|
@CapacitorPlugin(name = "CapacitorNfc")
|
|
36
36
|
public class CapacitorNfcPlugin extends Plugin {
|
|
37
|
-
private static final String TAG = "CapacitorNfcPlugin";
|
|
38
|
-
private static final String PLUGIN_VERSION = "0.0.1";
|
|
39
|
-
private static final int DEFAULT_READER_FLAGS =
|
|
40
|
-
NfcAdapter.FLAG_READER_NFC_A |
|
|
41
|
-
NfcAdapter.FLAG_READER_NFC_B |
|
|
42
|
-
NfcAdapter.FLAG_READER_NFC_F |
|
|
43
|
-
NfcAdapter.FLAG_READER_NFC_V |
|
|
44
|
-
NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK |
|
|
45
|
-
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS;
|
|
46
|
-
|
|
47
|
-
private NfcAdapter adapter;
|
|
48
|
-
private final AtomicReference<Tag> lastTag = new AtomicReference<>(null);
|
|
49
|
-
private final AtomicReference<NdefMessage> lastMessage = new AtomicReference<>(null);
|
|
50
|
-
private boolean readerModeRequested = false;
|
|
51
|
-
private boolean readerModeActive = false;
|
|
52
|
-
private int readerModeFlags = DEFAULT_READER_FLAGS;
|
|
53
|
-
private NdefMessage sharedMessage = null;
|
|
54
|
-
private NfcStateReceiver stateReceiver;
|
|
55
|
-
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
56
|
-
|
|
57
|
-
private final NfcAdapter.ReaderCallback readerCallback = this::onTagDiscovered;
|
|
58
|
-
|
|
59
|
-
@Override
|
|
60
|
-
public void load() {
|
|
61
|
-
adapter = NfcAdapter.getDefaultAdapter(getContext());
|
|
62
|
-
registerStateReceiver();
|
|
63
|
-
emitStateChange(adapter != null && adapter.isEnabled() ? NfcAdapter.STATE_ON : NfcAdapter.STATE_OFF);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
@Override
|
|
67
|
-
protected void handleOnDestroy() {
|
|
68
|
-
super.handleOnDestroy();
|
|
69
|
-
unregisterStateReceiver();
|
|
70
|
-
executor.shutdownNow();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
@Override
|
|
74
|
-
protected void handleOnPause() {
|
|
75
|
-
super.handleOnPause();
|
|
76
|
-
if (readerModeActive) {
|
|
77
|
-
disableReaderMode(false);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
37
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
38
|
+
private static final String TAG = "CapacitorNfcPlugin";
|
|
39
|
+
private static final String PLUGIN_VERSION = "0.0.1";
|
|
40
|
+
private static final int DEFAULT_READER_FLAGS =
|
|
41
|
+
NfcAdapter.FLAG_READER_NFC_A |
|
|
42
|
+
NfcAdapter.FLAG_READER_NFC_B |
|
|
43
|
+
NfcAdapter.FLAG_READER_NFC_F |
|
|
44
|
+
NfcAdapter.FLAG_READER_NFC_V |
|
|
45
|
+
NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK |
|
|
46
|
+
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS;
|
|
47
|
+
|
|
48
|
+
private NfcAdapter adapter;
|
|
49
|
+
private final AtomicReference<Tag> lastTag = new AtomicReference<>(null);
|
|
50
|
+
private final AtomicReference<NdefMessage> lastMessage = new AtomicReference<>(null);
|
|
51
|
+
private boolean readerModeRequested = false;
|
|
52
|
+
private boolean readerModeActive = false;
|
|
53
|
+
private int readerModeFlags = DEFAULT_READER_FLAGS;
|
|
54
|
+
private NdefMessage sharedMessage = null;
|
|
55
|
+
private NfcStateReceiver stateReceiver;
|
|
56
|
+
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
57
|
+
|
|
58
|
+
private final NfcAdapter.ReaderCallback readerCallback = this::onTagDiscovered;
|
|
88
59
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
60
|
+
@Override
|
|
61
|
+
public void load() {
|
|
62
|
+
adapter = NfcAdapter.getDefaultAdapter(getContext());
|
|
63
|
+
registerStateReceiver();
|
|
64
|
+
emitStateChange(adapter != null && adapter.isEnabled() ? NfcAdapter.STATE_ON : NfcAdapter.STATE_OFF);
|
|
93
65
|
}
|
|
94
66
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
@PluginMethod
|
|
102
|
-
public void stopScanning(PluginCall call) {
|
|
103
|
-
readerModeRequested = false;
|
|
104
|
-
disableReaderMode(true);
|
|
105
|
-
call.resolve();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
@PluginMethod
|
|
109
|
-
public void write(PluginCall call) {
|
|
110
|
-
JSONArray records = call.getArray("records");
|
|
111
|
-
boolean allowFormat = call.getBoolean("allowFormat", true);
|
|
112
|
-
|
|
113
|
-
if (records == null) {
|
|
114
|
-
call.reject("records is required");
|
|
115
|
-
return;
|
|
67
|
+
@Override
|
|
68
|
+
protected void handleOnDestroy() {
|
|
69
|
+
super.handleOnDestroy();
|
|
70
|
+
unregisterStateReceiver();
|
|
71
|
+
executor.shutdownNow();
|
|
116
72
|
}
|
|
117
73
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
74
|
+
@Override
|
|
75
|
+
protected void handleOnPause() {
|
|
76
|
+
super.handleOnPause();
|
|
77
|
+
if (readerModeActive) {
|
|
78
|
+
disableReaderMode(false);
|
|
79
|
+
}
|
|
122
80
|
}
|
|
123
81
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
82
|
+
@Override
|
|
83
|
+
protected void handleOnResume() {
|
|
84
|
+
super.handleOnResume();
|
|
85
|
+
if (readerModeRequested && !readerModeActive) {
|
|
86
|
+
enableReaderMode(readerModeFlags);
|
|
87
|
+
}
|
|
129
88
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
89
|
+
|
|
90
|
+
@PluginMethod
|
|
91
|
+
public void startScanning(PluginCall call) {
|
|
92
|
+
if (!ensureAdapterAvailable(call)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
readerModeFlags = call.getInt("androidReaderModeFlags", DEFAULT_READER_FLAGS);
|
|
97
|
+
readerModeRequested = true;
|
|
98
|
+
enableReaderMode(readerModeFlags);
|
|
99
|
+
call.resolve();
|
|
138
100
|
}
|
|
139
101
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
@PluginMethod
|
|
146
|
-
public void makeReadOnly(PluginCall call) {
|
|
147
|
-
Tag tag = lastTag.get();
|
|
148
|
-
if (tag == null) {
|
|
149
|
-
call.reject("No NFC tag available. Scan a tag before attempting to lock it.");
|
|
150
|
-
return;
|
|
102
|
+
@PluginMethod
|
|
103
|
+
public void stopScanning(PluginCall call) {
|
|
104
|
+
readerModeRequested = false;
|
|
105
|
+
disableReaderMode(true);
|
|
106
|
+
call.resolve();
|
|
151
107
|
}
|
|
152
108
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
109
|
+
@PluginMethod
|
|
110
|
+
public void write(PluginCall call) {
|
|
111
|
+
JSONArray records = call.getArray("records");
|
|
112
|
+
boolean allowFormat = call.getBoolean("allowFormat", true);
|
|
113
|
+
|
|
114
|
+
if (records == null) {
|
|
115
|
+
call.reject("records is required");
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
Tag tag = lastTag.get();
|
|
120
|
+
if (tag == null) {
|
|
121
|
+
call.reject("No NFC tag available. Call startScanning and tap a tag before attempting to write.");
|
|
122
|
+
return;
|
|
158
123
|
}
|
|
159
124
|
|
|
160
125
|
try {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
} else {
|
|
167
|
-
call.reject("Failed to make the tag read only.");
|
|
168
|
-
}
|
|
169
|
-
} catch (IOException e) {
|
|
170
|
-
call.reject("Failed to make the tag read only.", e);
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
@PluginMethod
|
|
176
|
-
public void share(PluginCall call) {
|
|
177
|
-
if (!ensureAdapterAvailable(call)) {
|
|
178
|
-
return;
|
|
126
|
+
NdefMessage message = NfcJsonConverter.jsonArrayToMessage(records);
|
|
127
|
+
performWrite(call, tag, message, allowFormat);
|
|
128
|
+
} catch (JSONException e) {
|
|
129
|
+
call.reject("Invalid NDEF records payload", e);
|
|
130
|
+
}
|
|
179
131
|
}
|
|
180
132
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
133
|
+
@PluginMethod
|
|
134
|
+
public void erase(PluginCall call) {
|
|
135
|
+
Tag tag = lastTag.get();
|
|
136
|
+
if (tag == null) {
|
|
137
|
+
call.reject("No NFC tag available. Call startScanning and tap a tag before attempting to erase.");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
NdefRecord empty = new NdefRecord(NdefRecord.TNF_EMPTY, new byte[0], new byte[0], new byte[0]);
|
|
142
|
+
NdefMessage message = new NdefMessage(new NdefRecord[] { empty });
|
|
143
|
+
performWrite(call, tag, message, true);
|
|
184
144
|
}
|
|
185
145
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
146
|
+
@PluginMethod
|
|
147
|
+
public void makeReadOnly(PluginCall call) {
|
|
148
|
+
Tag tag = lastTag.get();
|
|
149
|
+
if (tag == null) {
|
|
150
|
+
call.reject("No NFC tag available. Scan a tag before attempting to lock it.");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
executor.execute(() -> {
|
|
155
|
+
Ndef ndef = Ndef.get(tag);
|
|
156
|
+
if (ndef == null) {
|
|
157
|
+
call.reject("Tag does not support NDEF.");
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
ndef.connect();
|
|
163
|
+
boolean success = ndef.makeReadOnly();
|
|
164
|
+
ndef.close();
|
|
165
|
+
if (success) {
|
|
166
|
+
call.resolve();
|
|
167
|
+
} else {
|
|
168
|
+
call.reject("Failed to make the tag read only.");
|
|
169
|
+
}
|
|
170
|
+
} catch (IOException e) {
|
|
171
|
+
call.reject("Failed to make the tag read only.", e);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
190
174
|
}
|
|
191
175
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
176
|
+
@PluginMethod
|
|
177
|
+
public void share(PluginCall call) {
|
|
178
|
+
if (!ensureAdapterAvailable(call)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
199
181
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (!isNdefPushEnabled(adapter)) {
|
|
203
|
-
call.reject("NDEF push is disabled on this device.");
|
|
182
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
183
|
+
call.reject("Peer-to-peer NFC sharing is not supported on Android 10 or later.");
|
|
204
184
|
return;
|
|
205
|
-
|
|
206
|
-
setNdefPushMessage(adapter, message, activity);
|
|
207
|
-
sharedMessage = message;
|
|
208
|
-
call.resolve();
|
|
209
|
-
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
|
|
210
|
-
Log.w(TAG, "NDEF push API unavailable on this device", ex);
|
|
211
|
-
call.reject("NDEF push is not available on this device.");
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
} catch (JSONException e) {
|
|
215
|
-
call.reject("Invalid NDEF records payload", e);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
185
|
+
}
|
|
218
186
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
187
|
+
JSArray records = call.getArray("records");
|
|
188
|
+
if (records == null) {
|
|
189
|
+
call.reject("records is required");
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
224
192
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
193
|
+
try {
|
|
194
|
+
NdefMessage message = NfcJsonConverter.jsonArrayToMessage(records);
|
|
195
|
+
Activity activity = getActivity();
|
|
196
|
+
if (activity == null) {
|
|
197
|
+
call.reject("Unable to access activity context.");
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
activity.runOnUiThread(() -> {
|
|
202
|
+
try {
|
|
203
|
+
if (!isNdefPushEnabled(adapter)) {
|
|
204
|
+
call.reject("NDEF push is disabled on this device.");
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
setNdefPushMessage(adapter, message, activity);
|
|
208
|
+
sharedMessage = message;
|
|
209
|
+
call.resolve();
|
|
210
|
+
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
|
|
211
|
+
Log.w(TAG, "NDEF push API unavailable on this device", ex);
|
|
212
|
+
call.reject("NDEF push is not available on this device.");
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
} catch (JSONException e) {
|
|
216
|
+
call.reject("Invalid NDEF records payload", e);
|
|
217
|
+
}
|
|
229
218
|
}
|
|
230
219
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if (activity == null) {
|
|
254
|
-
call.reject("Unable to open settings without an activity context.");
|
|
255
|
-
return;
|
|
220
|
+
@PluginMethod
|
|
221
|
+
public void unshare(PluginCall call) {
|
|
222
|
+
if (!ensureAdapterAvailable(call)) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
Activity activity = getActivity();
|
|
227
|
+
if (activity == null) {
|
|
228
|
+
call.reject("Unable to access activity context.");
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
activity.runOnUiThread(() -> {
|
|
233
|
+
try {
|
|
234
|
+
setNdefPushMessage(adapter, null, activity);
|
|
235
|
+
sharedMessage = null;
|
|
236
|
+
call.resolve();
|
|
237
|
+
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
|
|
238
|
+
Log.w(TAG, "NDEF push API unavailable on this device", ex);
|
|
239
|
+
call.reject("Unable to clear shared message on this device.");
|
|
240
|
+
}
|
|
241
|
+
});
|
|
256
242
|
}
|
|
257
243
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
try {
|
|
264
|
-
activity.startActivity(fallback);
|
|
265
|
-
} catch (ActivityNotFoundException secondary) {
|
|
266
|
-
call.reject("Unable to open NFC settings on this device.");
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
244
|
+
@PluginMethod
|
|
245
|
+
public void getStatus(PluginCall call) {
|
|
246
|
+
JSObject result = new JSObject();
|
|
247
|
+
result.put("status", getNfcStatus());
|
|
248
|
+
call.resolve(result);
|
|
269
249
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
private void performWrite(PluginCall call, Tag tag, NdefMessage message, boolean allowFormat) {
|
|
281
|
-
executor.execute(() -> {
|
|
282
|
-
Ndef ndef = Ndef.get(tag);
|
|
250
|
+
|
|
251
|
+
@PluginMethod
|
|
252
|
+
public void showSettings(PluginCall call) {
|
|
253
|
+
Activity activity = getActivity();
|
|
254
|
+
if (activity == null) {
|
|
255
|
+
call.reject("Unable to open settings without an activity context.");
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
Intent intent = new Intent(Settings.ACTION_NFC_SETTINGS);
|
|
283
260
|
try {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
call.resolve();
|
|
293
|
-
}
|
|
294
|
-
ndef.close();
|
|
295
|
-
} else if (allowFormat) {
|
|
296
|
-
NdefFormatable formatable = NdefFormatable.get(tag);
|
|
297
|
-
if (formatable != null) {
|
|
298
|
-
formatable.connect();
|
|
299
|
-
formatable.format(message);
|
|
300
|
-
formatable.close();
|
|
301
|
-
call.resolve();
|
|
302
|
-
} else {
|
|
303
|
-
call.reject("Tag does not support NDEF formatting.");
|
|
261
|
+
activity.startActivity(intent);
|
|
262
|
+
} catch (ActivityNotFoundException ex) {
|
|
263
|
+
Intent fallback = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
|
|
264
|
+
try {
|
|
265
|
+
activity.startActivity(fallback);
|
|
266
|
+
} catch (ActivityNotFoundException secondary) {
|
|
267
|
+
call.reject("Unable to open NFC settings on this device.");
|
|
268
|
+
return;
|
|
304
269
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
308
|
-
} catch (IOException | FormatException e) {
|
|
309
|
-
call.reject("Failed to write NDEF message.", e);
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
private void enableReaderMode(int flags) {
|
|
315
|
-
Activity activity = getActivity();
|
|
316
|
-
if (activity == null || adapter == null) {
|
|
317
|
-
return;
|
|
270
|
+
}
|
|
271
|
+
call.resolve();
|
|
318
272
|
}
|
|
319
273
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
274
|
+
@PluginMethod
|
|
275
|
+
public void getPluginVersion(PluginCall call) {
|
|
276
|
+
JSObject result = new JSObject();
|
|
277
|
+
result.put("version", PLUGIN_VERSION);
|
|
278
|
+
call.resolve(result);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
private void performWrite(PluginCall call, Tag tag, NdefMessage message, boolean allowFormat) {
|
|
282
|
+
executor.execute(() -> {
|
|
283
|
+
Ndef ndef = Ndef.get(tag);
|
|
284
|
+
try {
|
|
285
|
+
if (ndef != null) {
|
|
286
|
+
ndef.connect();
|
|
287
|
+
if (!ndef.isWritable()) {
|
|
288
|
+
call.reject("Tag is read only.");
|
|
289
|
+
} else if (ndef.getMaxSize() < message.toByteArray().length) {
|
|
290
|
+
call.reject("Tag capacity is insufficient for the provided message.");
|
|
291
|
+
} else {
|
|
292
|
+
ndef.writeNdefMessage(message);
|
|
293
|
+
call.resolve();
|
|
294
|
+
}
|
|
295
|
+
ndef.close();
|
|
296
|
+
} else if (allowFormat) {
|
|
297
|
+
NdefFormatable formatable = NdefFormatable.get(tag);
|
|
298
|
+
if (formatable != null) {
|
|
299
|
+
formatable.connect();
|
|
300
|
+
formatable.format(message);
|
|
301
|
+
formatable.close();
|
|
302
|
+
call.resolve();
|
|
303
|
+
} else {
|
|
304
|
+
call.reject("Tag does not support NDEF formatting.");
|
|
305
|
+
}
|
|
306
|
+
} else {
|
|
307
|
+
call.reject("Tag does not support NDEF.");
|
|
308
|
+
}
|
|
309
|
+
} catch (IOException | FormatException e) {
|
|
310
|
+
call.reject("Failed to write NDEF message.", e);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
337
313
|
}
|
|
338
314
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
315
|
+
private void enableReaderMode(int flags) {
|
|
316
|
+
Activity activity = getActivity();
|
|
317
|
+
if (activity == null || adapter == null) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
Bundle extras = new Bundle();
|
|
322
|
+
extras.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 100);
|
|
323
|
+
|
|
324
|
+
activity.runOnUiThread(() -> {
|
|
325
|
+
try {
|
|
326
|
+
adapter.enableReaderMode(activity, readerCallback, flags, extras);
|
|
327
|
+
readerModeActive = true;
|
|
328
|
+
} catch (IllegalStateException ex) {
|
|
329
|
+
Log.w(TAG, "Failed to enable reader mode", ex);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
356
332
|
}
|
|
357
333
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
334
|
+
private void disableReaderMode(boolean clearRequested) {
|
|
335
|
+
Activity activity = getActivity();
|
|
336
|
+
if (activity == null || adapter == null) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
activity.runOnUiThread(() -> {
|
|
341
|
+
try {
|
|
342
|
+
adapter.disableReaderMode(activity);
|
|
343
|
+
} catch (IllegalStateException ex) {
|
|
344
|
+
Log.w(TAG, "Failed to disable reader mode", ex);
|
|
345
|
+
} finally {
|
|
346
|
+
readerModeActive = false;
|
|
347
|
+
if (clearRequested) {
|
|
348
|
+
readerModeRequested = false;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
});
|
|
366
352
|
}
|
|
367
353
|
|
|
368
|
-
|
|
369
|
-
|
|
354
|
+
private void onTagDiscovered(Tag tag) {
|
|
355
|
+
if (tag == null) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
370
358
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
359
|
+
Ndef ndef = Ndef.get(tag);
|
|
360
|
+
NdefMessage cachedMessage = null;
|
|
361
|
+
if (ndef != null) {
|
|
362
|
+
try {
|
|
363
|
+
cachedMessage = ndef.getCachedNdefMessage();
|
|
364
|
+
} catch (Exception ex) {
|
|
365
|
+
Log.w(TAG, "Unable to fetch cached NDEF message", ex);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
376
368
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
369
|
+
lastTag.set(tag);
|
|
370
|
+
lastMessage.set(cachedMessage);
|
|
381
371
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
switch (eventType) {
|
|
388
|
-
case "tag":
|
|
389
|
-
notifyListeners("tagDiscovered", payload, true);
|
|
390
|
-
break;
|
|
391
|
-
case "ndef":
|
|
392
|
-
notifyListeners("ndefDiscovered", payload, true);
|
|
393
|
-
break;
|
|
394
|
-
case "ndef-mime":
|
|
395
|
-
notifyListeners("ndefMimeDiscovered", payload, true);
|
|
396
|
-
break;
|
|
397
|
-
case "ndef-formatable":
|
|
398
|
-
notifyListeners("ndefFormatableDiscovered", payload, true);
|
|
399
|
-
break;
|
|
400
|
-
default:
|
|
401
|
-
break;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
372
|
+
JSObject tagJson = NfcJsonConverter.tagToJSObject(tag, cachedMessage);
|
|
373
|
+
String eventType = determineEventType(tag, cachedMessage);
|
|
374
|
+
JSObject event = new JSObject();
|
|
375
|
+
event.put("type", eventType);
|
|
376
|
+
event.put("tag", tagJson);
|
|
404
377
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
378
|
+
Activity activity = getActivity();
|
|
379
|
+
if (activity == null) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
409
382
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
383
|
+
activity.runOnUiThread(() -> emitEvents(eventType, event));
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
private void emitEvents(String eventType, JSObject payload) {
|
|
387
|
+
notifyListeners("nfcEvent", payload, true);
|
|
388
|
+
switch (eventType) {
|
|
389
|
+
case "tag":
|
|
390
|
+
notifyListeners("tagDiscovered", payload, true);
|
|
391
|
+
break;
|
|
392
|
+
case "ndef":
|
|
393
|
+
notifyListeners("ndefDiscovered", payload, true);
|
|
394
|
+
break;
|
|
395
|
+
case "ndef-mime":
|
|
396
|
+
notifyListeners("ndefMimeDiscovered", payload, true);
|
|
397
|
+
break;
|
|
398
|
+
case "ndef-formatable":
|
|
399
|
+
notifyListeners("ndefFormatableDiscovered", payload, true);
|
|
400
|
+
break;
|
|
401
|
+
default:
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
415
404
|
}
|
|
416
405
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
406
|
+
private String determineEventType(Tag tag, NdefMessage message) {
|
|
407
|
+
if (tag == null) {
|
|
408
|
+
return "tag";
|
|
409
|
+
}
|
|
420
410
|
|
|
421
|
-
|
|
422
|
-
|
|
411
|
+
if (message != null) {
|
|
412
|
+
if (Arrays.stream(message.getRecords()).anyMatch((record) -> record.getTnf() == NdefRecord.TNF_MIME_MEDIA)) {
|
|
413
|
+
return "ndef-mime";
|
|
414
|
+
}
|
|
415
|
+
return "ndef";
|
|
416
|
+
}
|
|
423
417
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
return false;
|
|
428
|
-
}
|
|
429
|
-
if (!adapter.isEnabled()) {
|
|
430
|
-
call.reject("NFC is currently disabled.", "NFC_DISABLED");
|
|
431
|
-
return false;
|
|
432
|
-
}
|
|
433
|
-
return true;
|
|
434
|
-
}
|
|
418
|
+
if (Arrays.asList(tag.getTechList()).contains(NdefFormatable.class.getName())) {
|
|
419
|
+
return "ndef-formatable";
|
|
420
|
+
}
|
|
435
421
|
|
|
436
|
-
|
|
437
|
-
if (adapter == null) {
|
|
438
|
-
return "NO_NFC";
|
|
422
|
+
return "tag";
|
|
439
423
|
}
|
|
440
|
-
|
|
441
|
-
|
|
424
|
+
|
|
425
|
+
private boolean ensureAdapterAvailable(PluginCall call) {
|
|
426
|
+
if (adapter == null) {
|
|
427
|
+
call.reject("NFC hardware not available on this device.", "NO_NFC");
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
if (!adapter.isEnabled()) {
|
|
431
|
+
call.reject("NFC is currently disabled.", "NFC_DISABLED");
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
return true;
|
|
442
435
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
private void setNdefPushMessage(NfcAdapter adapter, NdefMessage message, Activity activity)
|
|
454
|
-
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
|
455
|
-
Method method = NfcAdapter.class.getMethod("setNdefPushMessage", NdefMessage.class, Activity.class, Activity[].class);
|
|
456
|
-
method.invoke(adapter, message, activity, new Activity[0]);
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
private void registerStateReceiver() {
|
|
460
|
-
if (stateReceiver != null) {
|
|
461
|
-
return;
|
|
436
|
+
|
|
437
|
+
private String getNfcStatus() {
|
|
438
|
+
if (adapter == null) {
|
|
439
|
+
return "NO_NFC";
|
|
440
|
+
}
|
|
441
|
+
if (!adapter.isEnabled()) {
|
|
442
|
+
return "NFC_DISABLED";
|
|
443
|
+
}
|
|
444
|
+
return "NFC_OK";
|
|
462
445
|
}
|
|
463
446
|
|
|
464
|
-
|
|
465
|
-
|
|
447
|
+
private boolean isNdefPushEnabled(NfcAdapter adapter) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
|
448
|
+
Method method = NfcAdapter.class.getMethod("isNdefPushEnabled");
|
|
449
|
+
Object result = method.invoke(adapter);
|
|
450
|
+
return result instanceof Boolean && (Boolean) result;
|
|
466
451
|
}
|
|
467
452
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
453
|
+
private void setNdefPushMessage(NfcAdapter adapter, NdefMessage message, Activity activity)
|
|
454
|
+
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
|
455
|
+
Method method = NfcAdapter.class.getMethod("setNdefPushMessage", NdefMessage.class, Activity.class, Activity[].class);
|
|
456
|
+
method.invoke(adapter, message, activity, new Activity[0]);
|
|
471
457
|
}
|
|
472
458
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
459
|
+
private void registerStateReceiver() {
|
|
460
|
+
if (stateReceiver != null) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
477
467
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
468
|
+
Context context = getContext();
|
|
469
|
+
if (context == null) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
stateReceiver = new NfcStateReceiver(this::emitStateChange);
|
|
474
|
+
IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
|
|
475
|
+
context.registerReceiver(stateReceiver, filter);
|
|
485
476
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
477
|
+
|
|
478
|
+
private void unregisterStateReceiver() {
|
|
479
|
+
if (stateReceiver == null) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
Context context = getContext();
|
|
483
|
+
if (context != null) {
|
|
484
|
+
context.unregisterReceiver(stateReceiver);
|
|
485
|
+
}
|
|
486
|
+
stateReceiver = null;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
private void emitStateChange(int state) {
|
|
490
|
+
String status;
|
|
491
|
+
boolean enabled;
|
|
492
|
+
switch (state) {
|
|
493
|
+
case NfcAdapter.STATE_ON:
|
|
494
|
+
status = "NFC_OK";
|
|
495
|
+
enabled = true;
|
|
496
|
+
break;
|
|
497
|
+
case NfcAdapter.STATE_OFF:
|
|
498
|
+
status = adapter == null ? "NO_NFC" : "NFC_DISABLED";
|
|
499
|
+
enabled = false;
|
|
500
|
+
break;
|
|
501
|
+
default:
|
|
502
|
+
status = getNfcStatus();
|
|
503
|
+
enabled = adapter != null && adapter.isEnabled();
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
JSObject payload = new JSObject();
|
|
508
|
+
payload.put("status", status);
|
|
509
|
+
payload.put("enabled", enabled);
|
|
510
|
+
notifyListeners("nfcStateChange", payload, true);
|
|
505
511
|
}
|
|
506
512
|
|
|
507
|
-
|
|
508
|
-
payload.put("status", status);
|
|
509
|
-
payload.put("enabled", enabled);
|
|
510
|
-
notifyListeners("nfcStateChange", payload, true);
|
|
511
|
-
}
|
|
513
|
+
private static class NfcStateReceiver extends android.content.BroadcastReceiver {
|
|
512
514
|
|
|
513
|
-
|
|
514
|
-
private final StateCallback callback;
|
|
515
|
+
private final StateCallback callback;
|
|
515
516
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
517
|
+
NfcStateReceiver(StateCallback callback) {
|
|
518
|
+
this.callback = callback;
|
|
519
|
+
}
|
|
519
520
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
521
|
+
@Override
|
|
522
|
+
public void onReceive(Context context, Intent intent) {
|
|
523
|
+
if (intent == null || !NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(intent.getAction())) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
int state = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF);
|
|
527
|
+
if (callback != null) {
|
|
528
|
+
callback.onStateChanged(state);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
529
531
|
}
|
|
530
|
-
}
|
|
531
532
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
533
|
+
private interface StateCallback {
|
|
534
|
+
void onStateChanged(int state);
|
|
535
|
+
}
|
|
535
536
|
}
|
|
@@ -11,125 +11,126 @@ import org.json.JSONArray;
|
|
|
11
11
|
import org.json.JSONException;
|
|
12
12
|
|
|
13
13
|
final class NfcJsonConverter {
|
|
14
|
-
private static final String TAG = "CapacitorNfcJson";
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
private static final String TAG = "CapacitorNfcJson";
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
JSObject result = new JSObject();
|
|
20
|
-
if (tag != null) {
|
|
21
|
-
result.put("id", byteArrayToJSONArray(tag.getId()));
|
|
22
|
-
result.put("techTypes", techTypesToArray(tag.getTechList()));
|
|
23
|
-
}
|
|
17
|
+
private NfcJsonConverter() {}
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
result.put("isWritable", ndef.isWritable());
|
|
31
|
-
try {
|
|
32
|
-
result.put("canMakeReadOnly", ndef.canMakeReadOnly());
|
|
33
|
-
} catch (NullPointerException e) {
|
|
34
|
-
result.put("canMakeReadOnly", JSObject.NULL);
|
|
19
|
+
static JSObject tagToJSObject(Tag tag, NdefMessage cachedMessage) {
|
|
20
|
+
JSObject result = new JSObject();
|
|
21
|
+
if (tag != null) {
|
|
22
|
+
result.put("id", byteArrayToJSONArray(tag.getId()));
|
|
23
|
+
result.put("techTypes", techTypesToArray(tag.getTechList()));
|
|
35
24
|
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
25
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
26
|
+
if (tag != null) {
|
|
27
|
+
Ndef ndef = Ndef.get(tag);
|
|
28
|
+
if (ndef != null) {
|
|
29
|
+
result.put("type", translateType(ndef.getType()));
|
|
30
|
+
result.put("maxSize", ndef.getMaxSize());
|
|
31
|
+
result.put("isWritable", ndef.isWritable());
|
|
32
|
+
try {
|
|
33
|
+
result.put("canMakeReadOnly", ndef.canMakeReadOnly());
|
|
34
|
+
} catch (NullPointerException e) {
|
|
35
|
+
result.put("canMakeReadOnly", JSObject.NULL);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
if (cachedMessage != null) {
|
|
41
|
+
result.put("ndefMessage", messageToJSONArray(cachedMessage));
|
|
42
|
+
}
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
if (message == null) {
|
|
48
|
-
return null;
|
|
44
|
+
return result;
|
|
49
45
|
}
|
|
50
46
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return array;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static JSObject recordToJSObject(NdefRecord record) {
|
|
59
|
-
JSObject obj = new JSObject();
|
|
60
|
-
obj.put("tnf", record.getTnf());
|
|
61
|
-
obj.put("type", byteArrayToJSONArray(record.getType()));
|
|
62
|
-
obj.put("id", byteArrayToJSONArray(record.getId()));
|
|
63
|
-
obj.put("payload", byteArrayToJSONArray(record.getPayload()));
|
|
64
|
-
return obj;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static JSONArray byteArrayToJSONArray(byte[] bytes) {
|
|
68
|
-
if (bytes == null) {
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
JSArray array = new JSArray();
|
|
72
|
-
for (byte aByte : bytes) {
|
|
73
|
-
array.put(aByte & 0xFF);
|
|
74
|
-
}
|
|
75
|
-
return array;
|
|
76
|
-
}
|
|
47
|
+
static JSONArray messageToJSONArray(NdefMessage message) {
|
|
48
|
+
if (message == null) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
77
51
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
52
|
+
JSArray array = new JSArray();
|
|
53
|
+
for (NdefRecord record : message.getRecords()) {
|
|
54
|
+
array.put(recordToJSObject(record));
|
|
55
|
+
}
|
|
56
|
+
return array;
|
|
82
57
|
}
|
|
83
|
-
return array;
|
|
84
|
-
}
|
|
85
58
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
59
|
+
static JSObject recordToJSObject(NdefRecord record) {
|
|
60
|
+
JSObject obj = new JSObject();
|
|
61
|
+
obj.put("tnf", record.getTnf());
|
|
62
|
+
obj.put("type", byteArrayToJSONArray(record.getType()));
|
|
63
|
+
obj.put("id", byteArrayToJSONArray(record.getId()));
|
|
64
|
+
obj.put("payload", byteArrayToJSONArray(record.getPayload()));
|
|
65
|
+
return obj;
|
|
89
66
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return type;
|
|
67
|
+
|
|
68
|
+
static JSONArray byteArrayToJSONArray(byte[] bytes) {
|
|
69
|
+
if (bytes == null) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
JSArray array = new JSArray();
|
|
73
|
+
for (byte aByte : bytes) {
|
|
74
|
+
array.put(aByte & 0xFF);
|
|
75
|
+
}
|
|
76
|
+
return array;
|
|
101
77
|
}
|
|
102
|
-
}
|
|
103
78
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
79
|
+
private static JSArray techTypesToArray(String[] techTypes) {
|
|
80
|
+
JSArray array = new JSArray();
|
|
81
|
+
if (techTypes != null) {
|
|
82
|
+
Arrays.stream(techTypes).forEach(array::put);
|
|
83
|
+
}
|
|
84
|
+
return array;
|
|
107
85
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
86
|
+
|
|
87
|
+
static String translateType(String type) {
|
|
88
|
+
if (type == null) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
switch (type) {
|
|
92
|
+
case Ndef.NFC_FORUM_TYPE_1:
|
|
93
|
+
return "NFC Forum Type 1";
|
|
94
|
+
case Ndef.NFC_FORUM_TYPE_2:
|
|
95
|
+
return "NFC Forum Type 2";
|
|
96
|
+
case Ndef.NFC_FORUM_TYPE_3:
|
|
97
|
+
return "NFC Forum Type 3";
|
|
98
|
+
case Ndef.NFC_FORUM_TYPE_4:
|
|
99
|
+
return "NFC Forum Type 4";
|
|
100
|
+
default:
|
|
101
|
+
return type;
|
|
102
|
+
}
|
|
120
103
|
}
|
|
121
|
-
return new NdefMessage(ndefRecords);
|
|
122
|
-
}
|
|
123
104
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
105
|
+
static NdefMessage jsonArrayToMessage(JSONArray records) throws JSONException {
|
|
106
|
+
if (records == null || records.length() == 0) {
|
|
107
|
+
throw new JSONException("records must be a non-empty array");
|
|
108
|
+
}
|
|
109
|
+
NdefRecord[] ndefRecords = new NdefRecord[records.length()];
|
|
110
|
+
for (int i = 0; i < records.length(); i++) {
|
|
111
|
+
JSObject record = JSObject.fromJSONObject(records.getJSONObject(i));
|
|
112
|
+
Integer tnfValue = record.getInteger("tnf");
|
|
113
|
+
if (tnfValue == null) {
|
|
114
|
+
throw new JSONException("Each record must include a tnf field.");
|
|
115
|
+
}
|
|
116
|
+
short tnf = (short) tnfValue.intValue();
|
|
117
|
+
byte[] type = jsonArrayToBytes(record.optJSONArray("type"));
|
|
118
|
+
byte[] id = jsonArrayToBytes(record.optJSONArray("id"));
|
|
119
|
+
byte[] payload = jsonArrayToBytes(record.optJSONArray("payload"));
|
|
120
|
+
ndefRecords[i] = new NdefRecord(tnf, type, id, payload);
|
|
121
|
+
}
|
|
122
|
+
return new NdefMessage(ndefRecords);
|
|
127
123
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
124
|
+
|
|
125
|
+
static byte[] jsonArrayToBytes(JSONArray array) throws JSONException {
|
|
126
|
+
if (array == null) {
|
|
127
|
+
return new byte[0];
|
|
128
|
+
}
|
|
129
|
+
byte[] bytes = new byte[array.length()];
|
|
130
|
+
for (int i = 0; i < array.length(); i++) {
|
|
131
|
+
int value = array.getInt(i);
|
|
132
|
+
bytes[i] = (byte) (value & 0xFF);
|
|
133
|
+
}
|
|
134
|
+
return bytes;
|
|
132
135
|
}
|
|
133
|
-
return bytes;
|
|
134
|
-
}
|
|
135
136
|
}
|
package/dist/esm/web.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAY5C,MAAM,OAAO,eAAgB,SAAQ,SAAS;IACpC,WAAW,CAAC,MAAc;QAChC,MAAM,IAAI,CAAC,aAAa,CAAC,gBAAgB,MAAM,6CAA6C,CAAC,CAAC;IAChG,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAA+B;QACjD,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAyB;QACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAyB;QACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAClC,CAAC;
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAY5C,MAAM,OAAO,eAAgB,SAAQ,SAAS;IACpC,WAAW,CAAC,MAAc;QAChC,MAAM,IAAI,CAAC,aAAa,CAAC,gBAAgB,MAAM,6CAA6C,CAAC,CAAC;IAChG,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAA+B;QACjD,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAyB;QACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAyB;QACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAClC,CAAC;IAWD,KAAK,CAAC,WAAW,CAAC,SAAiB,EAAE,aAAuC;QAC1E,IAAI,CAAC,WAAW,CAAC,eAAe,SAAS,GAAG,CAAC,CAAC;IAChD,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type {\n CapacitorNfcPlugin,\n NfcStateChangeEvent,\n NfcEvent,\n ShareTagOptions,\n StartScanningOptions,\n WriteTagOptions,\n PluginListenerHandle,\n} from './definitions';\n\nexport class CapacitorNfcWeb extends WebPlugin implements CapacitorNfcPlugin {\n private unsupported(method: string): never {\n throw this.unimplemented(`CapacitorNfc.${method} is not available in a browser environment.`);\n }\n\n async startScanning(_options?: StartScanningOptions): Promise<void> {\n this.unsupported('startScanning');\n }\n\n async stopScanning(): Promise<void> {\n this.unsupported('stopScanning');\n }\n\n async write(_options: WriteTagOptions): Promise<void> {\n this.unsupported('write');\n }\n\n async erase(): Promise<void> {\n this.unsupported('erase');\n }\n\n async makeReadOnly(): Promise<void> {\n this.unsupported('makeReadOnly');\n }\n\n async share(_options: ShareTagOptions): Promise<void> {\n this.unsupported('share');\n }\n\n async unshare(): Promise<void> {\n this.unsupported('unshare');\n }\n\n async getStatus(): Promise<{ status: 'NO_NFC' }> {\n return { status: 'NO_NFC' };\n }\n\n async showSettings(): Promise<void> {\n this.unsupported('showSettings');\n }\n\n async getPluginVersion(): Promise<{ version: string }> {\n return { version: '0.0.0-web' };\n }\n\n addListener(eventName: 'nfcEvent', listenerFunc: (event: NfcEvent) => void): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'tagDiscovered' | 'ndefDiscovered' | 'ndefMimeDiscovered' | 'ndefFormatableDiscovered',\n listenerFunc: (event: NfcEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'nfcStateChange',\n listenerFunc: (event: NfcStateChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n async addListener(eventName: string, _listenerFunc: (..._args: any[]) => any): Promise<PluginListenerHandle> {\n this.unsupported(`addListener(${eventName})`);\n }\n}\n"]}
|
package/package.json
CHANGED