@capgo/capacitor-nfc 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,535 @@
1
+ package app.capgo.nfc;
2
+
3
+ import android.app.Activity;
4
+ import android.content.ActivityNotFoundException;
5
+ import android.content.Context;
6
+ import android.content.Intent;
7
+ import android.content.IntentFilter;
8
+ import android.nfc.FormatException;
9
+ import android.nfc.NdefMessage;
10
+ import android.nfc.NdefRecord;
11
+ import android.nfc.NfcAdapter;
12
+ import android.nfc.Tag;
13
+ import android.nfc.tech.Ndef;
14
+ import android.nfc.tech.NdefFormatable;
15
+ import android.os.Build;
16
+ import android.os.Bundle;
17
+ import android.provider.Settings;
18
+ import android.util.Log;
19
+ import com.getcapacitor.JSArray;
20
+ import com.getcapacitor.JSObject;
21
+ import com.getcapacitor.Plugin;
22
+ import com.getcapacitor.PluginCall;
23
+ import com.getcapacitor.PluginMethod;
24
+ import com.getcapacitor.annotation.CapacitorPlugin;
25
+ import java.io.IOException;
26
+ import java.lang.reflect.InvocationTargetException;
27
+ import java.lang.reflect.Method;
28
+ import java.util.Arrays;
29
+ import java.util.concurrent.ExecutorService;
30
+ import java.util.concurrent.Executors;
31
+ import java.util.concurrent.atomic.AtomicReference;
32
+ import org.json.JSONArray;
33
+ import org.json.JSONException;
34
+
35
+ @CapacitorPlugin(name = "CapacitorNfc")
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
+
81
+ @Override
82
+ protected void handleOnResume() {
83
+ super.handleOnResume();
84
+ if (readerModeRequested && !readerModeActive) {
85
+ enableReaderMode(readerModeFlags);
86
+ }
87
+ }
88
+
89
+ @PluginMethod
90
+ public void startScanning(PluginCall call) {
91
+ if (!ensureAdapterAvailable(call)) {
92
+ return;
93
+ }
94
+
95
+ readerModeFlags = call.getInt("androidReaderModeFlags", DEFAULT_READER_FLAGS);
96
+ readerModeRequested = true;
97
+ enableReaderMode(readerModeFlags);
98
+ call.resolve();
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;
116
+ }
117
+
118
+ Tag tag = lastTag.get();
119
+ if (tag == null) {
120
+ call.reject("No NFC tag available. Call startScanning and tap a tag before attempting to write.");
121
+ return;
122
+ }
123
+
124
+ try {
125
+ NdefMessage message = NfcJsonConverter.jsonArrayToMessage(records);
126
+ performWrite(call, tag, message, allowFormat);
127
+ } catch (JSONException e) {
128
+ call.reject("Invalid NDEF records payload", e);
129
+ }
130
+ }
131
+
132
+ @PluginMethod
133
+ public void erase(PluginCall call) {
134
+ Tag tag = lastTag.get();
135
+ if (tag == null) {
136
+ call.reject("No NFC tag available. Call startScanning and tap a tag before attempting to erase.");
137
+ return;
138
+ }
139
+
140
+ NdefRecord empty = new NdefRecord(NdefRecord.TNF_EMPTY, new byte[0], new byte[0], new byte[0]);
141
+ NdefMessage message = new NdefMessage(new NdefRecord[] { empty });
142
+ performWrite(call, tag, message, true);
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;
151
+ }
152
+
153
+ executor.execute(() -> {
154
+ Ndef ndef = Ndef.get(tag);
155
+ if (ndef == null) {
156
+ call.reject("Tag does not support NDEF.");
157
+ return;
158
+ }
159
+
160
+ try {
161
+ ndef.connect();
162
+ boolean success = ndef.makeReadOnly();
163
+ ndef.close();
164
+ if (success) {
165
+ call.resolve();
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;
179
+ }
180
+
181
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
182
+ call.reject("Peer-to-peer NFC sharing is not supported on Android 10 or later.");
183
+ return;
184
+ }
185
+
186
+ JSArray records = call.getArray("records");
187
+ if (records == null) {
188
+ call.reject("records is required");
189
+ return;
190
+ }
191
+
192
+ try {
193
+ NdefMessage message = NfcJsonConverter.jsonArrayToMessage(records);
194
+ Activity activity = getActivity();
195
+ if (activity == null) {
196
+ call.reject("Unable to access activity context.");
197
+ return;
198
+ }
199
+
200
+ activity.runOnUiThread(() -> {
201
+ try {
202
+ if (!isNdefPushEnabled(adapter)) {
203
+ call.reject("NDEF push is disabled on this device.");
204
+ 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
+ }
218
+
219
+ @PluginMethod
220
+ public void unshare(PluginCall call) {
221
+ if (!ensureAdapterAvailable(call)) {
222
+ return;
223
+ }
224
+
225
+ Activity activity = getActivity();
226
+ if (activity == null) {
227
+ call.reject("Unable to access activity context.");
228
+ return;
229
+ }
230
+
231
+ activity.runOnUiThread(() -> {
232
+ try {
233
+ setNdefPushMessage(adapter, null, activity);
234
+ sharedMessage = null;
235
+ call.resolve();
236
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
237
+ Log.w(TAG, "NDEF push API unavailable on this device", ex);
238
+ call.reject("Unable to clear shared message on this device.");
239
+ }
240
+ });
241
+ }
242
+
243
+ @PluginMethod
244
+ public void getStatus(PluginCall call) {
245
+ JSObject result = new JSObject();
246
+ result.put("status", getNfcStatus());
247
+ call.resolve(result);
248
+ }
249
+
250
+ @PluginMethod
251
+ public void showSettings(PluginCall call) {
252
+ Activity activity = getActivity();
253
+ if (activity == null) {
254
+ call.reject("Unable to open settings without an activity context.");
255
+ return;
256
+ }
257
+
258
+ Intent intent = new Intent(Settings.ACTION_NFC_SETTINGS);
259
+ try {
260
+ activity.startActivity(intent);
261
+ } catch (ActivityNotFoundException ex) {
262
+ Intent fallback = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
263
+ try {
264
+ activity.startActivity(fallback);
265
+ } catch (ActivityNotFoundException secondary) {
266
+ call.reject("Unable to open NFC settings on this device.");
267
+ return;
268
+ }
269
+ }
270
+ call.resolve();
271
+ }
272
+
273
+ @PluginMethod
274
+ public void getPluginVersion(PluginCall call) {
275
+ JSObject result = new JSObject();
276
+ result.put("version", PLUGIN_VERSION);
277
+ call.resolve(result);
278
+ }
279
+
280
+ private void performWrite(PluginCall call, Tag tag, NdefMessage message, boolean allowFormat) {
281
+ executor.execute(() -> {
282
+ Ndef ndef = Ndef.get(tag);
283
+ try {
284
+ if (ndef != null) {
285
+ ndef.connect();
286
+ if (!ndef.isWritable()) {
287
+ call.reject("Tag is read only.");
288
+ } else if (ndef.getMaxSize() < message.toByteArray().length) {
289
+ call.reject("Tag capacity is insufficient for the provided message.");
290
+ } else {
291
+ ndef.writeNdefMessage(message);
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.");
304
+ }
305
+ } else {
306
+ call.reject("Tag does not support NDEF.");
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;
318
+ }
319
+
320
+ Bundle extras = new Bundle();
321
+ extras.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 100);
322
+
323
+ activity.runOnUiThread(() -> {
324
+ try {
325
+ adapter.enableReaderMode(activity, readerCallback, flags, extras);
326
+ readerModeActive = true;
327
+ } catch (IllegalStateException ex) {
328
+ Log.w(TAG, "Failed to enable reader mode", ex);
329
+ }
330
+ });
331
+ }
332
+
333
+ private void disableReaderMode(boolean clearRequested) {
334
+ Activity activity = getActivity();
335
+ if (activity == null || adapter == null) {
336
+ return;
337
+ }
338
+
339
+ activity.runOnUiThread(() -> {
340
+ try {
341
+ adapter.disableReaderMode(activity);
342
+ } catch (IllegalStateException ex) {
343
+ Log.w(TAG, "Failed to disable reader mode", ex);
344
+ } finally {
345
+ readerModeActive = false;
346
+ if (clearRequested) {
347
+ readerModeRequested = false;
348
+ }
349
+ }
350
+ });
351
+ }
352
+
353
+ private void onTagDiscovered(Tag tag) {
354
+ if (tag == null) {
355
+ return;
356
+ }
357
+
358
+ Ndef ndef = Ndef.get(tag);
359
+ NdefMessage cachedMessage = null;
360
+ if (ndef != null) {
361
+ try {
362
+ cachedMessage = ndef.getCachedNdefMessage();
363
+ } catch (Exception ex) {
364
+ Log.w(TAG, "Unable to fetch cached NDEF message", ex);
365
+ }
366
+ }
367
+
368
+ lastTag.set(tag);
369
+ lastMessage.set(cachedMessage);
370
+
371
+ JSObject tagJson = NfcJsonConverter.tagToJSObject(tag, cachedMessage);
372
+ String eventType = determineEventType(tag, cachedMessage);
373
+ JSObject event = new JSObject();
374
+ event.put("type", eventType);
375
+ event.put("tag", tagJson);
376
+
377
+ Activity activity = getActivity();
378
+ if (activity == null) {
379
+ return;
380
+ }
381
+
382
+ activity.runOnUiThread(() -> emitEvents(eventType, event));
383
+ }
384
+
385
+ private void emitEvents(String eventType, JSObject payload) {
386
+ notifyListeners("nfcEvent", payload, true);
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
+ }
404
+
405
+ private String determineEventType(Tag tag, NdefMessage message) {
406
+ if (tag == null) {
407
+ return "tag";
408
+ }
409
+
410
+ if (message != null) {
411
+ if (Arrays.stream(message.getRecords()).anyMatch(record -> record.getTnf() == NdefRecord.TNF_MIME_MEDIA)) {
412
+ return "ndef-mime";
413
+ }
414
+ return "ndef";
415
+ }
416
+
417
+ if (Arrays.asList(tag.getTechList()).contains(NdefFormatable.class.getName())) {
418
+ return "ndef-formatable";
419
+ }
420
+
421
+ return "tag";
422
+ }
423
+
424
+ private boolean ensureAdapterAvailable(PluginCall call) {
425
+ if (adapter == null) {
426
+ call.reject("NFC hardware not available on this device.", "NO_NFC");
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
+ }
435
+
436
+ private String getNfcStatus() {
437
+ if (adapter == null) {
438
+ return "NO_NFC";
439
+ }
440
+ if (!adapter.isEnabled()) {
441
+ return "NFC_DISABLED";
442
+ }
443
+ return "NFC_OK";
444
+ }
445
+
446
+ private boolean isNdefPushEnabled(NfcAdapter adapter)
447
+ throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
448
+ Method method = NfcAdapter.class.getMethod("isNdefPushEnabled");
449
+ Object result = method.invoke(adapter);
450
+ return result instanceof Boolean && (Boolean) result;
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;
462
+ }
463
+
464
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
465
+ return;
466
+ }
467
+
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);
476
+ }
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);
511
+ }
512
+
513
+ private static class NfcStateReceiver extends android.content.BroadcastReceiver {
514
+ private final StateCallback callback;
515
+
516
+ NfcStateReceiver(StateCallback callback) {
517
+ this.callback = callback;
518
+ }
519
+
520
+ @Override
521
+ public void onReceive(Context context, Intent intent) {
522
+ if (intent == null || !NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(intent.getAction())) {
523
+ return;
524
+ }
525
+ int state = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF);
526
+ if (callback != null) {
527
+ callback.onStateChanged(state);
528
+ }
529
+ }
530
+ }
531
+
532
+ private interface StateCallback {
533
+ void onStateChanged(int state);
534
+ }
535
+ }
@@ -0,0 +1,135 @@
1
+ package app.capgo.nfc;
2
+
3
+ import android.nfc.NdefMessage;
4
+ import android.nfc.NdefRecord;
5
+ import android.nfc.Tag;
6
+ import android.nfc.tech.Ndef;
7
+ import com.getcapacitor.JSArray;
8
+ import com.getcapacitor.JSObject;
9
+ import java.util.Arrays;
10
+ import org.json.JSONArray;
11
+ import org.json.JSONException;
12
+
13
+ final class NfcJsonConverter {
14
+ private static final String TAG = "CapacitorNfcJson";
15
+
16
+ private NfcJsonConverter() {}
17
+
18
+ static JSObject tagToJSObject(Tag tag, NdefMessage cachedMessage) {
19
+ JSObject result = new JSObject();
20
+ if (tag != null) {
21
+ result.put("id", byteArrayToJSONArray(tag.getId()));
22
+ result.put("techTypes", techTypesToArray(tag.getTechList()));
23
+ }
24
+
25
+ if (tag != null) {
26
+ Ndef ndef = Ndef.get(tag);
27
+ if (ndef != null) {
28
+ result.put("type", translateType(ndef.getType()));
29
+ result.put("maxSize", ndef.getMaxSize());
30
+ result.put("isWritable", ndef.isWritable());
31
+ try {
32
+ result.put("canMakeReadOnly", ndef.canMakeReadOnly());
33
+ } catch (NullPointerException e) {
34
+ result.put("canMakeReadOnly", JSObject.NULL);
35
+ }
36
+ }
37
+ }
38
+
39
+ if (cachedMessage != null) {
40
+ result.put("ndefMessage", messageToJSONArray(cachedMessage));
41
+ }
42
+
43
+ return result;
44
+ }
45
+
46
+ static JSONArray messageToJSONArray(NdefMessage message) {
47
+ if (message == null) {
48
+ return null;
49
+ }
50
+
51
+ JSArray array = new JSArray();
52
+ for (NdefRecord record : message.getRecords()) {
53
+ array.put(recordToJSObject(record));
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
+ }
77
+
78
+ private static JSArray techTypesToArray(String[] techTypes) {
79
+ JSArray array = new JSArray();
80
+ if (techTypes != null) {
81
+ Arrays.stream(techTypes).forEach(array::put);
82
+ }
83
+ return array;
84
+ }
85
+
86
+ static String translateType(String type) {
87
+ if (type == null) {
88
+ return null;
89
+ }
90
+ switch (type) {
91
+ case Ndef.NFC_FORUM_TYPE_1:
92
+ return "NFC Forum Type 1";
93
+ case Ndef.NFC_FORUM_TYPE_2:
94
+ return "NFC Forum Type 2";
95
+ case Ndef.NFC_FORUM_TYPE_3:
96
+ return "NFC Forum Type 3";
97
+ case Ndef.NFC_FORUM_TYPE_4:
98
+ return "NFC Forum Type 4";
99
+ default:
100
+ return type;
101
+ }
102
+ }
103
+
104
+ static NdefMessage jsonArrayToMessage(JSONArray records) throws JSONException {
105
+ if (records == null || records.length() == 0) {
106
+ throw new JSONException("records must be a non-empty array");
107
+ }
108
+ NdefRecord[] ndefRecords = new NdefRecord[records.length()];
109
+ for (int i = 0; i < records.length(); i++) {
110
+ JSObject record = JSObject.fromJSONObject(records.getJSONObject(i));
111
+ Integer tnfValue = record.getInteger("tnf");
112
+ if (tnfValue == null) {
113
+ throw new JSONException("Each record must include a tnf field.");
114
+ }
115
+ short tnf = (short) tnfValue.intValue();
116
+ byte[] type = jsonArrayToBytes(record.optJSONArray("type"));
117
+ byte[] id = jsonArrayToBytes(record.optJSONArray("id"));
118
+ byte[] payload = jsonArrayToBytes(record.optJSONArray("payload"));
119
+ ndefRecords[i] = new NdefRecord(tnf, type, id, payload);
120
+ }
121
+ return new NdefMessage(ndefRecords);
122
+ }
123
+
124
+ static byte[] jsonArrayToBytes(JSONArray array) throws JSONException {
125
+ if (array == null) {
126
+ return new byte[0];
127
+ }
128
+ byte[] bytes = new byte[array.length()];
129
+ for (int i = 0; i < array.length(); i++) {
130
+ int value = array.getInt(i);
131
+ bytes[i] = (byte) (value & 0xFF);
132
+ }
133
+ return bytes;
134
+ }
135
+ }