react-native-nfc-manager 3.11.5 → 3.13.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.
@@ -49,7 +49,7 @@ class MifareUtil {
49
49
  // able of reading/writing MIFARE Classic tags. I don't know why...
50
50
  // https://github.com/ikarus23/MifareClassicTool/issues/152
51
51
  boolean isLenovoP2 = Build.MANUFACTURER.equals("LENOVO")
52
- && Build.MODEL.equals("Lenovo P2a42");
52
+ && Build.MODEL.equals("Lenovo P2a42");
53
53
  File device = new File("/dev/bcm2079x-i2c");
54
54
  if (!isLenovoP2 && device.exists()) {
55
55
  return false;
@@ -70,8 +70,8 @@ class MifareUtil {
70
70
  File[] libs = libsFolder.listFiles();
71
71
  for (File lib : libs) {
72
72
  if (lib.isFile()
73
- && lib.getName().startsWith("libnfc")
74
- && lib.getName().contains("brcm")
73
+ && lib.getName().startsWith("libnfc")
74
+ && lib.getName().contains("brcm")
75
75
  // Add here other non NXP NFC libraries.
76
76
  ) {
77
77
  return false;
@@ -266,6 +266,36 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
266
266
  }
267
267
  }
268
268
 
269
+ @ReactMethod
270
+ public void formatNdef(ReadableArray rnArray, ReadableMap options, Callback callback) {
271
+ boolean readOnly = options.getBoolean("readOnly");
272
+
273
+ synchronized(this) {
274
+ if (techRequest != null) {
275
+ try {
276
+ NdefFormatable ndef = (NdefFormatable)techRequest.getTechHandle();
277
+ if (ndef == null) {
278
+ callback.invoke(ERR_API_NOT_SUPPORT);
279
+ } else {
280
+ byte[] bytes = rnArrayToBytes(rnArray);
281
+ NdefMessage msg = new NdefMessage(bytes);
282
+ if (readOnly) {
283
+ ndef.formatReadOnly(msg);
284
+ } else {
285
+ ndef.format(msg);
286
+ }
287
+ callback.invoke();
288
+ }
289
+ } catch (Exception ex) {
290
+ Log.d(LOG_TAG, ex.toString());
291
+ callback.invoke(ex.toString());
292
+ }
293
+ } else {
294
+ callback.invoke(ERR_NO_TECH_REQ);
295
+ }
296
+ }
297
+ }
298
+
269
299
  private void mifareClassicAuthenticate(char type, int sector, ReadableArray key, Callback callback) {
270
300
  if (techRequest != null) {
271
301
  try {
@@ -616,27 +646,27 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
616
646
  @ReactMethod
617
647
  public void connect(ReadableArray techs, Callback callback){
618
648
  synchronized(this) {
619
- try {
620
- techRequest = new TagTechnologyRequest(techs.toArrayList(), callback);
621
- techRequest.connect(this.tag);
622
- callback.invoke(null, null);
623
- return;
624
- } catch (Exception ex) {
625
- callback.invoke(ex.toString());
626
- }
649
+ try {
650
+ techRequest = new TagTechnologyRequest(techs.toArrayList(), callback);
651
+ techRequest.connect(this.tag);
652
+ callback.invoke(null, null);
653
+ return;
654
+ } catch (Exception ex) {
655
+ callback.invoke(ex.toString());
656
+ }
627
657
  }
628
658
  }
629
659
 
630
660
  @ReactMethod
631
661
  public void close(Callback callback){
632
662
  synchronized(this) {
633
- try {
634
- techRequest.close();
635
- callback.invoke(null, null);
636
- return;
637
- } catch (Exception ex) {
638
- callback.invoke(ex.toString());
639
- }
663
+ try {
664
+ techRequest.close();
665
+ callback.invoke(null, null);
666
+ return;
667
+ } catch (Exception ex) {
668
+ callback.invoke(ex.toString());
669
+ }
640
670
  }
641
671
  }
642
672
 
@@ -941,11 +971,11 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
941
971
 
942
972
  @ReactMethod
943
973
  private void registerTagEvent(ReadableMap options, Callback callback) {
944
- this.isReaderModeEnabled = options.getBoolean("isReaderModeEnabled");
945
- this.readerModeFlags = options.getInt("readerModeFlags");
946
- this.readerModeDelay = options.getInt("readerModeDelay");
974
+ isReaderModeEnabled = options.getBoolean("isReaderModeEnabled");
975
+ readerModeFlags = options.getInt("readerModeFlags");
976
+ readerModeDelay = options.getInt("readerModeDelay");
947
977
 
948
- Log.d(LOG_TAG, "registerTag");
978
+ Log.d(LOG_TAG, "registerTagEvent");
949
979
  isForegroundEnabled = true;
950
980
 
951
981
  // capture all mime-based dispatch NDEF
@@ -972,18 +1002,23 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
972
1002
 
973
1003
  @ReactMethod
974
1004
  private void unregisterTagEvent(Callback callback) {
975
- Log.d(LOG_TAG, "registerTag");
976
- isForegroundEnabled = false;
977
- intentFilters.clear();
1005
+ Log.d(LOG_TAG, "unregisterTagEvent");
978
1006
  if (isResumed) {
979
1007
  enableDisableForegroundDispatch(false);
980
1008
  }
1009
+
1010
+ intentFilters.clear();
1011
+ isForegroundEnabled = false;
1012
+ isReaderModeEnabled = false;
1013
+ readerModeFlags = 0;
1014
+ readerModeDelay = 0;
1015
+
981
1016
  callback.invoke();
982
1017
  }
983
1018
 
984
1019
  @ReactMethod
985
1020
  private void hasTagEventRegistration(Callback callback) {
986
- Log.d(LOG_TAG, "isSessionAvailable");
1021
+ Log.d(LOG_TAG, "isSessionAvailable: " + isForegroundEnabled);
987
1022
  callback.invoke(null, isForegroundEnabled);
988
1023
  }
989
1024
 
@@ -1031,25 +1066,36 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
1031
1066
  }
1032
1067
 
1033
1068
  if (enable) {
1034
- Log.i(LOG_TAG, "enableReaderMode");
1069
+ Log.i(LOG_TAG, "enableReaderMode: " + readerModeFlags);
1035
1070
  Bundle readerModeExtras = new Bundle();
1036
1071
  readerModeExtras.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, readerModeDelay * 1000);
1037
1072
  nfcAdapter.enableReaderMode(currentActivity, new NfcAdapter.ReaderCallback() {
1038
1073
  @Override
1039
1074
  public void onTagDiscovered(Tag tag) {
1040
- manager.tag = tag;
1041
- Log.d(LOG_TAG, "readerMode onTagDiscovered");
1042
- WritableMap nfcTag = null;
1043
- // if the tag contains NDEF, we want to report the content
1044
- if (Arrays.asList(tag.getTechList()).contains(Ndef.class.getName())) {
1045
- Ndef ndef = Ndef.get(tag);
1046
- nfcTag = ndef2React(ndef, new NdefMessage[] { ndef.getCachedNdefMessage() });
1047
- } else {
1048
- nfcTag = tag2React(tag);
1049
- }
1050
-
1051
- if (nfcTag != null) {
1052
- sendEvent("NfcManagerDiscoverTag", nfcTag);
1075
+ synchronized (this) {
1076
+ manager.tag = tag;
1077
+ Log.d(LOG_TAG, "readerMode onTagDiscovered");
1078
+ WritableMap nfcTag = null;
1079
+ // if the tag contains NDEF, we want to report the content
1080
+ if (Arrays.asList(tag.getTechList()).contains(Ndef.class.getName())) {
1081
+ Ndef ndef = Ndef.get(tag);
1082
+ nfcTag = ndef2React(ndef, new NdefMessage[] { ndef.getCachedNdefMessage() });
1083
+ } else {
1084
+ nfcTag = tag2React(tag);
1085
+ }
1086
+
1087
+ if (nfcTag != null) {
1088
+ sendEvent("NfcManagerDiscoverTag", nfcTag);
1089
+ if (techRequest!= null && !techRequest.isConnected()) {
1090
+ boolean result = techRequest.connect(tag);
1091
+ if (result) {
1092
+ techRequest.getPendingCallback().invoke(null, techRequest.getTechType());
1093
+ } else {
1094
+ // this indicates that we get a NFC tag, but none of the user required tech is matched
1095
+ techRequest.getPendingCallback().invoke(null, null);
1096
+ }
1097
+ }
1098
+ }
1053
1099
  }
1054
1100
  }
1055
1101
  }, readerModeFlags, readerModeExtras);
@@ -1077,7 +1123,7 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
1077
1123
 
1078
1124
  int flag = 0;
1079
1125
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
1080
- flag = PendingIntent.FLAG_MUTABLE;
1126
+ flag = PendingIntent.FLAG_MUTABLE;
1081
1127
  }
1082
1128
  return PendingIntent.getActivity(activity, 0, intent, flag);
1083
1129
  }
@@ -11,6 +11,7 @@ import android.nfc.tech.NfcV;
11
11
  import android.nfc.tech.NfcF;
12
12
  import android.nfc.tech.MifareClassic;
13
13
  import android.nfc.tech.MifareUltralight;
14
+ import android.nfc.tech.NdefFormatable;
14
15
  import android.nfc.tech.IsoDep;
15
16
  import android.util.Log;
16
17
  import com.facebook.react.bridge.*;
@@ -76,6 +77,8 @@ class TagTechnologyRequest {
76
77
  mTech = MifareClassic.get(tag);
77
78
  } else if (techType.equals("MifareUltralight")) {
78
79
  mTech = MifareUltralight.get(tag);
80
+ } else if (techType.equals("NdefFormatable")) {
81
+ mTech = NdefFormatable.get(tag);
79
82
  }
80
83
 
81
84
  if (mTech == null) {
@@ -39,9 +39,9 @@ public class Util {
39
39
  // mTag.getTagService(); of the Ndef object sometimes returns null
40
40
  // see http://issues.mroland.at/index.php?do=details&task_id=47
41
41
  try {
42
- json.put("canMakeReadOnly", ndef.canMakeReadOnly());
42
+ json.put("canMakeReadOnly", ndef.canMakeReadOnly());
43
43
  } catch (NullPointerException e) {
44
- json.put("canMakeReadOnly", JSONObject.NULL);
44
+ json.put("canMakeReadOnly", JSONObject.NULL);
45
45
  }
46
46
  } catch (JSONException e) {
47
47
  Log.e(TAG, "Failed to convert ndef into json: " + ndef.toString(), e);
@@ -104,16 +104,16 @@ public class Util {
104
104
  }
105
105
 
106
106
  public static String bytesToHex(byte[] bytes) {
107
- char[] hexChars = new char[bytes.length * 2];
107
+ char[] hexChars = new char[bytes.length * 2];
108
108
 
109
- for ( int j = 0; j < bytes.length; j++ ) {
110
- int v = bytes[j] & 0xFF;
109
+ for ( int j = 0; j < bytes.length; j++ ) {
110
+ int v = bytes[j] & 0xFF;
111
111
 
112
- hexChars[j * 2] = hexArray[v >>> 4];
113
- hexChars[j * 2 + 1] = hexArray[v & 0x0F];
114
- }
112
+ hexChars[j * 2] = hexArray[v >>> 4];
113
+ hexChars[j * 2 + 1] = hexArray[v & 0x0F];
114
+ }
115
115
 
116
- return new String(hexChars);
116
+ return new String(hexChars);
117
117
  }
118
118
 
119
119
  static byte[] jsonToByteArray(JSONArray json) throws JSONException {
package/index.d.ts CHANGED
@@ -22,6 +22,7 @@ declare module 'react-native-nfc-manager' {
22
22
  MifareIOS = 'mifare',
23
23
  Iso15693IOS = 'iso15693',
24
24
  FelicaIOS = 'felica',
25
+ NdefFormatable = 'NdefFormatable',
25
26
  }
26
27
 
27
28
  export enum NdefStatus {
@@ -47,6 +48,17 @@ declare module 'react-native-nfc-manager' {
47
48
  Select = 1 << 4,
48
49
  Address = 1 << 5,
49
50
  Option = 1 << 6,
51
+ CommandSpecificBit8 = 1 << 7,
52
+ }
53
+
54
+ export enum Nfc15693ResponseFlagIOS {
55
+ Error = 1 << 0,
56
+ ResponseBufferValid = 1 << 1,
57
+ FinalResponse = 1 << 2,
58
+ ProtocolExtension = 1 << 3,
59
+ BlockSecurityStatusBit5 = 1 << 4,
60
+ BlockSecurityStatusBit6 = 1 << 5,
61
+ WaitTimeExtension = 1 << 6,
50
62
  }
51
63
 
52
64
  type TNF = 0x0 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07;
@@ -76,6 +88,7 @@ declare module 'react-native-nfc-manager' {
76
88
 
77
89
  export interface CancelTechReqOpts {
78
90
  throwOnError?: boolean = false;
91
+ delayMsAndroid?: number = 1000;
79
92
  }
80
93
 
81
94
  interface NdefHandler {
@@ -93,6 +106,10 @@ declare module 'react-native-nfc-manager' {
93
106
  transceive: (bytes: number[]) => Promise<number[]>;
94
107
  }
95
108
 
109
+ interface NfcVHandler {
110
+ transceive: (bytes: number[]) => Promise<number[]>;
111
+ }
112
+
96
113
  interface IsoDepHandler {
97
114
  transceive: (bytes: number[]) => Promise<number[]>;
98
115
  }
@@ -121,6 +138,10 @@ declare module 'react-native-nfc-manager' {
121
138
  ) => Promise<void>;
122
139
  }
123
140
 
141
+ interface NdefFormatableHandlerAndroid {
142
+ formatNdef: (bytes: number[], options?: { readOnly: boolean }) => Promise<void>;
143
+ }
144
+
124
145
  /** [iOS ONLY] */
125
146
  interface Iso15693HandlerIOS {
126
147
  getSystemInfo: (
@@ -159,6 +180,11 @@ declare module 'react-native-nfc-manager' {
159
180
  customCommandCode: number;
160
181
  customRequestParameters: number[];
161
182
  }) => Promise<number[]>;
183
+ sendRequest: (params: {
184
+ flags: number;
185
+ commandCode: number;
186
+ data: number[];
187
+ }) => Promise<[number, number[]]>;
162
188
  extendedReadSingleBlock: (params: {
163
189
  flags: number;
164
190
  blockNumber: number;
@@ -201,6 +227,7 @@ declare module 'react-native-nfc-manager' {
201
227
  */
202
228
  ndefHandler: NdefHandler;
203
229
  nfcAHandler: NfcAHandler;
230
+ nfcVHandler: NfcVHandler;
204
231
  isoDepHandler: IsoDepHandler;
205
232
 
206
233
  /**
@@ -236,6 +263,7 @@ declare module 'react-native-nfc-manager' {
236
263
  setTimeout(timeout: number): Promise<void>;
237
264
  mifareClassicHandlerAndroid: MifareClassicHandlerAndroid;
238
265
  mifareUltralightHandlerAndroid: MifareUltralightHandlerAndroid;
266
+ ndefFormatableHandlerAndroid: NdefFormatableHandlerAndroid;
239
267
  }
240
268
 
241
269
  const nfcManager: NfcManager;
package/ios/NfcManager.h CHANGED
@@ -30,3 +30,8 @@
30
30
  #endif
31
31
 
32
32
  @end
33
+
34
+ extern NSString* _Nonnull getHexString(NSData * _Nonnull);
35
+ extern NSString* _Nonnull getErrorMessage(NSError * _Nonnull);
36
+ extern NSData * _Nonnull arrayToData(NSArray * _Nonnull);
37
+ extern NSArray * _Nonnull dataToArray(NSData * _Nonnull);
package/ios/NfcManager.m CHANGED
@@ -4,29 +4,6 @@
4
4
  #import "React/RCTEventDispatcher.h"
5
5
  #import "React/RCTLog.h"
6
6
 
7
- NSString* getHexString(NSData *data) {
8
- NSUInteger capacity = data.length * 2;
9
- NSMutableString *sbuf = [NSMutableString stringWithCapacity:capacity];
10
- const unsigned char *buf = data.bytes;
11
- NSInteger i;
12
- for (i=0; i<data.length; ++i) {
13
- [sbuf appendFormat:@"%02lX", (unsigned long)buf[i]];
14
- }
15
- return sbuf;
16
- }
17
-
18
- NSString* getErrorMessage(NSError *error) {
19
- NSDictionary *userInfo = [error userInfo];
20
- NSError *underlyingError = [userInfo objectForKey:NSUnderlyingErrorKey];
21
- if (underlyingError != nil) {
22
- return [NSString stringWithFormat:@"%@:%ld,%@:%ld",
23
- [error domain], (long)[error code],
24
- [underlyingError domain], (long)[underlyingError code]];
25
- }
26
- return [NSString stringWithFormat:@"%@:%ld",
27
- [error domain], (long)[error code]];
28
- }
29
-
30
7
  @implementation NfcManager {
31
8
  NSDictionary *nfcTechTypes;
32
9
  NSArray *techRequestTypes;
@@ -37,7 +14,6 @@ RCT_EXPORT_MODULE()
37
14
 
38
15
  @synthesize session;
39
16
  @synthesize tagSession;
40
- @synthesize bridge = _bridge;
41
17
 
42
18
  static NSString *const kBgNfcTagNotification = @"RNBgNfcTagNotification";
43
19
  NSArray * bgNdefRecords = nil;
@@ -112,38 +88,12 @@ continueUserActivity:(NSUserActivity *)userActivity
112
88
  ];
113
89
  }
114
90
 
115
- - (NSData *)arrayToData: (NSArray *) array
116
- {
117
- Byte bytes[[array count]];
118
- for (int i = 0; i < [array count]; i++) {
119
- bytes[i] = [[array objectAtIndex:i] integerValue];
120
- }
121
- NSData *payload = [[NSData alloc] initWithBytes:bytes length:[array count]];
122
- return payload;
123
- }
124
-
125
- + (NSArray *)dataToArray:(NSData *)data
126
- {
127
- const unsigned char *dataBuffer = data ? (const unsigned char *)[data bytes] : NULL;
128
-
129
- if (!dataBuffer)
130
- return @[];
131
-
132
- NSUInteger dataLength = [data length];
133
- NSMutableArray *array = [NSMutableArray arrayWithCapacity:dataLength];
134
-
135
- for (int i = 0; i < dataLength; ++i)
136
- [array addObject:[NSNumber numberWithInteger:dataBuffer[i]]];
137
-
138
- return array;
139
- }
140
-
141
91
  + (NSDictionary*)convertNdefRecord:(NFCNDEFPayload *) record
142
92
  {
143
93
  return @{
144
- @"id": [self dataToArray:[record identifier]],
145
- @"payload": [self dataToArray: [record payload]],
146
- @"type": [self dataToArray:[record type]],
94
+ @"id": dataToArray([record identifier]),
95
+ @"payload": dataToArray([record payload]),
96
+ @"type": dataToArray([record type]),
147
97
  @"tnf": [NSNumber numberWithInt:[record typeNameFormat]]
148
98
  };
149
99
  }
@@ -179,13 +129,13 @@ continueUserActivity:(NSUserActivity *)userActivity
179
129
  id<NFCISO7816Tag> iso7816Tag = [tag asNFCISO7816Tag];
180
130
  [tagInfo setObject:getHexString(iso7816Tag.identifier) forKey:@"id"];
181
131
  [tagInfo setObject:iso7816Tag.initialSelectedAID forKey:@"initialSelectedAID"];
182
- [tagInfo setObject:[NfcManager dataToArray:iso7816Tag.historicalBytes] forKey:@"historicalBytes"];
183
- [tagInfo setObject:[NfcManager dataToArray:iso7816Tag.applicationData] forKey:@"applicationData"];
132
+ [tagInfo setObject:dataToArray(iso7816Tag.historicalBytes) forKey:@"historicalBytes"];
133
+ [tagInfo setObject:dataToArray(iso7816Tag.applicationData) forKey:@"applicationData"];
184
134
  } else if (tag.type == NFCTagTypeISO15693) {
185
135
  id<NFCISO15693Tag> iso15693Tag = [tag asNFCISO15693Tag];
186
136
  [tagInfo setObject:getHexString(iso15693Tag.identifier) forKey:@"id"];
187
137
  [tagInfo setObject:[NSNumber numberWithUnsignedInteger:iso15693Tag.icManufacturerCode] forKey:@"icManufacturerCode"];
188
- [tagInfo setObject:[NfcManager dataToArray:iso15693Tag.icSerialNumber] forKey:@"icSerialNumber"];
138
+ [tagInfo setObject:dataToArray(iso15693Tag.icSerialNumber) forKey:@"icSerialNumber"];
189
139
  } else if (tag.type == NFCTagTypeFeliCa) {
190
140
  id<NFCFeliCaTag> felicaTag = [tag asNFCFeliCaTag];
191
141
  [tagInfo setObject:getHexString(felicaTag.currentIDm) forKey:@"idm"];
@@ -196,18 +146,17 @@ continueUserActivity:(NSUserActivity *)userActivity
196
146
  return tagInfo;
197
147
  }
198
148
 
199
- - (id<NFCNDEFTag>)getNDEFTagHandle:(id<NFCTag>)tag {
149
+ - (id<NFCNDEFTag>)getNDEFTagHandle:(id<NFCTag>)tag
150
+ API_AVAILABLE(ios(13.0)) {
200
151
  // all following types inherite from NFCNDEFTag
201
- if (@available(iOS 13.0, *)) {
202
- if (tag.type == NFCTagTypeMiFare) {
203
- return [tag asNFCMiFareTag];
204
- } else if (tag.type == NFCTagTypeISO7816Compatible) {
205
- return [tag asNFCISO7816Tag];
206
- } else if (tag.type == NFCTagTypeISO15693) {
207
- return [tag asNFCISO15693Tag];
208
- } else if (tag.type == NFCTagTypeFeliCa) {
209
- return [tag asNFCFeliCaTag];
210
- }
152
+ if (tag.type == NFCTagTypeMiFare) {
153
+ return [tag asNFCMiFareTag];
154
+ } else if (tag.type == NFCTagTypeISO7816Compatible) {
155
+ return [tag asNFCISO7816Tag];
156
+ } else if (tag.type == NFCTagTypeISO15693) {
157
+ return [tag asNFCISO15693Tag];
158
+ } else if (tag.type == NFCTagTypeFeliCa) {
159
+ return [tag asNFCFeliCaTag];
211
160
  }
212
161
 
213
162
  return nil;
@@ -235,31 +184,29 @@ continueUserActivity:(NSUserActivity *)userActivity
235
184
  }
236
185
 
237
186
  - (void)tagReaderSession:(NFCTagReaderSession *)session didDetectTags:(NSArray<__kindof id<NFCTag>> *)tags
238
- {
187
+ API_AVAILABLE(ios(13.0)) {
239
188
  NSLog(@"NFCTag didDetectTags");
240
- if (@available(iOS 13.0, *)) {
241
- if (techRequestCallback != nil) {
242
- for (id<NFCTag> tag in tags) {
243
- NSString * tagType = [self getRNTechName:tag];
244
-
245
- for (NSString* requestType in techRequestTypes) {
246
- // here we treat Ndef is a special case, because all specific tech types
247
- // inherites from NFCNDEFTag, so we simply allow it to connect
248
- if ([tagType isEqualToString:requestType] || [requestType isEqualToString:@"Ndef"]) {
249
- RCTResponseSenderBlock pendingCallback = techRequestCallback;
250
- techRequestCallback = nil;
251
-
252
- [tagSession connectToTag:tag
253
- completionHandler:^(NSError *error) {
254
- if (error != nil) {
255
- pendingCallback(@[getErrorMessage(error)]);
256
- return;
257
- }
258
-
259
- pendingCallback(@[[NSNull null], requestType]);
260
- }];
261
- return;
262
- }
189
+ if (techRequestCallback != nil) {
190
+ for (id<NFCTag> tag in tags) {
191
+ NSString * tagType = [self getRNTechName:tag];
192
+
193
+ for (NSString* requestType in techRequestTypes) {
194
+ // here we treat Ndef is a special case, because all specific tech types
195
+ // inherites from NFCNDEFTag, so we simply allow it to connect
196
+ if ([tagType isEqualToString:requestType] || [requestType isEqualToString:@"Ndef"]) {
197
+ RCTResponseSenderBlock pendingCallback = techRequestCallback;
198
+ techRequestCallback = nil;
199
+
200
+ [tagSession connectToTag:tag
201
+ completionHandler:^(NSError *error) {
202
+ if (error != nil) {
203
+ pendingCallback(@[getErrorMessage(error)]);
204
+ return;
205
+ }
206
+
207
+ pendingCallback(@[[NSNull null], requestType]);
208
+ }];
209
+ return;
263
210
  }
264
211
  }
265
212
  }
@@ -267,7 +214,7 @@ continueUserActivity:(NSUserActivity *)userActivity
267
214
  }
268
215
 
269
216
  - (void)tagReaderSession:(NFCTagReaderSession *)session didInvalidateWithError:(NSError *)error
270
- {
217
+ API_AVAILABLE(ios(13.0)) {
271
218
  NSLog(@"NFCTag didInvalidateWithError");
272
219
  if (techRequestCallback) {
273
220
  techRequestCallback(@[getErrorMessage(error)]);
@@ -280,7 +227,7 @@ continueUserActivity:(NSUserActivity *)userActivity
280
227
  }
281
228
 
282
229
  - (void)tagReaderSessionDidBecomeActive:(NFCTagReaderSession *)session
283
- {
230
+ API_AVAILABLE(ios(13.0)) {
284
231
  NSLog(@"NFCTag didBecomeActive");
285
232
  }
286
233
 
@@ -499,7 +446,7 @@ RCT_EXPORT_METHOD(writeNdefMessage:(NSArray*)bytes callback:(nonnull RCTResponse
499
446
  }
500
447
 
501
448
  if (ndefTag) {
502
- NSData *data = [self arrayToData:bytes];
449
+ NSData *data = arrayToData(bytes);
503
450
  NFCNDEFMessage *ndefMsg = [NFCNDEFMessage ndefMessageWithData:data];
504
451
  if (!ndefMsg) {
505
452
  callback(@[@"invalid ndef msg"]);
@@ -568,8 +515,8 @@ RCT_EXPORT_METHOD(queryNDEFStatus:(nonnull RCTResponseSenderBlock)callback)
568
515
  } else {
569
516
  callback(@[[NSNull null],
570
517
  @{
571
- @"status": [[NSNumber alloc] initWithInt:status],
572
- @"capacity": [[NSNumber alloc] initWithInt:capacity]
518
+ @"status": [[NSNumber alloc] initWithInt:(int)status],
519
+ @"capacity": [[NSNumber alloc] initWithInt:(int)capacity]
573
520
  }
574
521
  ]);
575
522
  }
@@ -591,7 +538,7 @@ RCT_EXPORT_METHOD(sendMifareCommand:(NSArray *)bytes callback: (nonnull RCTRespo
591
538
  if (tagSession != nil) {
592
539
  if (tagSession.connectedTag) {
593
540
  id<NFCMiFareTag> mifareTag = [tagSession.connectedTag asNFCMiFareTag];
594
- NSData *data = [self arrayToData:bytes];
541
+ NSData *data = arrayToData(bytes);
595
542
  NSLog(@"input bytes: %@", getHexString(data));
596
543
  if (mifareTag) {
597
544
  [mifareTag sendMiFareCommand:data
@@ -599,7 +546,7 @@ RCT_EXPORT_METHOD(sendMifareCommand:(NSArray *)bytes callback: (nonnull RCTRespo
599
546
  if (error) {
600
547
  callback(@[getErrorMessage(error), [NSNull null]]);
601
548
  } else {
602
- callback(@[[NSNull null], [NfcManager dataToArray:response]]);
549
+ callback(@[[NSNull null], dataToArray(response)]);
603
550
  }
604
551
  }];
605
552
  return;
@@ -622,7 +569,7 @@ RCT_EXPORT_METHOD(sendFelicaCommand:(NSArray *)bytes callback: (nonnull RCTRespo
622
569
  if (tagSession != nil) {
623
570
  if (tagSession.connectedTag) {
624
571
  id<NFCFeliCaTag> felicaTag = [tagSession.connectedTag asNFCFeliCaTag];
625
- NSData *data = [self arrayToData:bytes];
572
+ NSData *data = arrayToData(bytes);
626
573
  NSLog(@"input bytes: %@", getHexString(data));
627
574
  if (felicaTag) {
628
575
  [felicaTag sendFeliCaCommandPacket:data
@@ -630,7 +577,7 @@ RCT_EXPORT_METHOD(sendFelicaCommand:(NSArray *)bytes callback: (nonnull RCTRespo
630
577
  if (error) {
631
578
  callback(@[getErrorMessage(error), [NSNull null]]);
632
579
  } else {
633
- callback(@[[NSNull null], [NfcManager dataToArray:response]]);
580
+ callback(@[[NSNull null], dataToArray(response)]);
634
581
  }
635
582
  }];
636
583
  return;
@@ -653,14 +600,14 @@ RCT_EXPORT_METHOD(sendCommandAPDUBytes:(NSArray *)bytes callback: (nonnull RCTRe
653
600
  if (tagSession != nil) {
654
601
  if (tagSession.connectedTag) {
655
602
  id<NFCISO7816Tag> iso7816Tag = [tagSession.connectedTag asNFCISO7816Tag];
656
- NSData *data = [self arrayToData:bytes];
603
+ NSData *data = arrayToData(bytes);
657
604
  NFCISO7816APDU *apdu = [[NFCISO7816APDU alloc] initWithData:data];
658
605
  if (iso7816Tag) {
659
606
  [iso7816Tag sendCommandAPDU:apdu completionHandler:^(NSData* response, uint8_t sw1, uint8_t sw2, NSError* error) {
660
607
  if (error) {
661
608
  callback(@[getErrorMessage(error), [NSNull null]]);
662
609
  } else {
663
- callback(@[[NSNull null], [NfcManager dataToArray:response], [NSNumber numberWithInt:sw1], [NSNumber numberWithInt:sw2]]);
610
+ callback(@[[NSNull null], dataToArray(response), [NSNumber numberWithInt:sw1], [NSNumber numberWithInt:sw2]]);
664
611
  }
665
612
  }];
666
613
  return;
@@ -688,7 +635,7 @@ RCT_EXPORT_METHOD(sendCommandAPDU:(NSDictionary *)apduData callback: (nonnull RC
688
635
  NSNumber *p1 = [apduData objectForKey:@"p1"];
689
636
  NSNumber *p2 = [apduData objectForKey:@"p2"];
690
637
  NSArray *dataArray = [apduData objectForKey:@"data"];
691
- NSData *data = [self arrayToData:dataArray];
638
+ NSData *data = arrayToData(dataArray);
692
639
  NSNumber *le = [apduData objectForKey:@"le"];
693
640
 
694
641
  /*
@@ -701,7 +648,7 @@ RCT_EXPORT_METHOD(sendCommandAPDU:(NSDictionary *)apduData callback: (nonnull RC
701
648
  if (error) {
702
649
  callback(@[getErrorMessage(error), [NSNull null]]);
703
650
  } else {
704
- callback(@[[NSNull null], [NfcManager dataToArray:response], [NSNumber numberWithInt:sw1], [NSNumber numberWithInt:sw2]]);
651
+ callback(@[[NSNull null], dataToArray(response), [NSNumber numberWithInt:sw1], [NSNumber numberWithInt:sw2]]);
705
652
  }
706
653
  }];
707
654
  return;
@@ -758,7 +705,7 @@ RCT_EXPORT_METHOD(isTagSessionAvailable:(nonnull RCTResponseSenderBlock)callback
758
705
  // ---------------------------
759
706
  RCT_EXPORT_METHOD(iso15693_getSystemInfo:(nonnull NSNumber *)flags callback:(nonnull RCTResponseSenderBlock)callback)
760
707
  {
761
- if (@available(iOS 13.0, *)) {
708
+ if (@available(iOS 14.0, *)) {
762
709
  if (!tagSession || !tagSession.connectedTag) {
763
710
  callback(@[@"Not connected", [NSNull null]]);
764
711
  return;
@@ -794,7 +741,7 @@ RCT_EXPORT_METHOD(iso15693_getSystemInfo:(nonnull NSNumber *)flags callback:(non
794
741
 
795
742
  RCT_EXPORT_METHOD(iso15693_readSingleBlock:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
796
743
  {
797
- if (@available(iOS 13.0, *)) {
744
+ if (@available(iOS 14.0, *)) {
798
745
  if (!tagSession || !tagSession.connectedTag) {
799
746
  callback(@[@"Not connected", [NSNull null]]);
800
747
  return;
@@ -817,7 +764,7 @@ RCT_EXPORT_METHOD(iso15693_readSingleBlock:(NSDictionary *)options callback:(non
817
764
  return;
818
765
  }
819
766
 
820
- callback(@[[NSNull null], [NfcManager dataToArray:resp]]);
767
+ callback(@[[NSNull null], dataToArray(resp)]);
821
768
  }];
822
769
  } else {
823
770
  callback(@[@"Not support in this device", [NSNull null]]);
@@ -826,7 +773,7 @@ RCT_EXPORT_METHOD(iso15693_readSingleBlock:(NSDictionary *)options callback:(non
826
773
 
827
774
  RCT_EXPORT_METHOD(iso15693_readMultipleBlocks:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
828
775
  {
829
- if (@available(iOS 13.0, *)) {
776
+ if (@available(iOS 14.0, *)) {
830
777
  if (!tagSession || !tagSession.connectedTag) {
831
778
  callback(@[@"Not connected", [NSNull null]]);
832
779
  return;
@@ -853,7 +800,7 @@ RCT_EXPORT_METHOD(iso15693_readMultipleBlocks:(NSDictionary *)options callback:(
853
800
  }
854
801
  NSMutableArray *blocks = [NSMutableArray arrayWithCapacity:[dataBlocks count]];
855
802
  [dataBlocks enumerateObjectsUsingBlock:^(NSData *blockData, NSUInteger idx, BOOL *stop) {
856
- [blocks addObject:[NfcManager dataToArray:blockData]];
803
+ [blocks addObject:dataToArray(blockData)];
857
804
  }];
858
805
  callback(@[[NSNull null], blocks]);
859
806
  }];
@@ -864,7 +811,7 @@ RCT_EXPORT_METHOD(iso15693_readMultipleBlocks:(NSDictionary *)options callback:(
864
811
 
865
812
  RCT_EXPORT_METHOD(iso15693_writeSingleBlock:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
866
813
  {
867
- if (@available(iOS 13.0, *)) {
814
+ if (@available(iOS 14.0, *)) {
868
815
  if (!tagSession || !tagSession.connectedTag) {
869
816
  callback(@[@"Not connected", [NSNull null]]);
870
817
  return;
@@ -878,7 +825,7 @@ RCT_EXPORT_METHOD(iso15693_writeSingleBlock:(NSDictionary *)options callback:(no
878
825
 
879
826
  RequestFlag flags = [[options objectForKey:@"flags"] unsignedIntValue];
880
827
  uint8_t blockNumber = [[options objectForKey:@"blockNumber"] unsignedIntValue];
881
- NSData *dataBlock = [self arrayToData:[options mutableArrayValueForKey:@"dataBlock"]];
828
+ NSData *dataBlock = arrayToData([options mutableArrayValueForKey:@"dataBlock"]);
882
829
 
883
830
  [tag writeSingleBlockWithRequestFlags:flags
884
831
  blockNumber:blockNumber
@@ -898,7 +845,7 @@ RCT_EXPORT_METHOD(iso15693_writeSingleBlock:(NSDictionary *)options callback:(no
898
845
 
899
846
  RCT_EXPORT_METHOD(iso15693_lockBlock:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
900
847
  {
901
- if (@available(iOS 13.0, *)) {
848
+ if (@available(iOS 14.0, *)) {
902
849
  if (!tagSession || !tagSession.connectedTag) {
903
850
  callback(@[@"Not connected", [NSNull null]]);
904
851
  return;
@@ -930,7 +877,7 @@ RCT_EXPORT_METHOD(iso15693_lockBlock:(NSDictionary *)options callback:(nonnull R
930
877
 
931
878
  RCT_EXPORT_METHOD(iso15693_writeAFI:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
932
879
  {
933
- if (@available(iOS 13.0, *)) {
880
+ if (@available(iOS 14.0, *)) {
934
881
  if (!tagSession || !tagSession.connectedTag) {
935
882
  callback(@[@"Not connected", [NSNull null]]);
936
883
  return;
@@ -962,7 +909,7 @@ RCT_EXPORT_METHOD(iso15693_writeAFI:(NSDictionary *)options callback:(nonnull RC
962
909
 
963
910
  RCT_EXPORT_METHOD(iso15693_lockAFI:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
964
911
  {
965
- if (@available(iOS 13.0, *)) {
912
+ if (@available(iOS 14.0, *)) {
966
913
  if (!tagSession || !tagSession.connectedTag) {
967
914
  callback(@[@"Not connected", [NSNull null]]);
968
915
  return;
@@ -992,7 +939,7 @@ RCT_EXPORT_METHOD(iso15693_lockAFI:(NSDictionary *)options callback:(nonnull RCT
992
939
 
993
940
  RCT_EXPORT_METHOD(iso15693_writeDSFID:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
994
941
  {
995
- if (@available(iOS 13.0, *)) {
942
+ if (@available(iOS 14.0, *)) {
996
943
  if (!tagSession || !tagSession.connectedTag) {
997
944
  callback(@[@"Not connected", [NSNull null]]);
998
945
  return;
@@ -1024,7 +971,7 @@ RCT_EXPORT_METHOD(iso15693_writeDSFID:(NSDictionary *)options callback:(nonnull
1024
971
 
1025
972
  RCT_EXPORT_METHOD(iso15693_lockDSFID:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
1026
973
  {
1027
- if (@available(iOS 13.0, *)) {
974
+ if (@available(iOS 14.0, *)) {
1028
975
  if (!tagSession || !tagSession.connectedTag) {
1029
976
  callback(@[@"Not connected", [NSNull null]]);
1030
977
  return;
@@ -1055,7 +1002,7 @@ RCT_EXPORT_METHOD(iso15693_lockDSFID:(NSDictionary *)options callback:(nonnull R
1055
1002
 
1056
1003
  RCT_EXPORT_METHOD(iso15693_resetToReady:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
1057
1004
  {
1058
- if (@available(iOS 13.0, *)) {
1005
+ if (@available(iOS 14.0, *)) {
1059
1006
  if (!tagSession || !tagSession.connectedTag) {
1060
1007
  callback(@[@"Not connected", [NSNull null]]);
1061
1008
  return;
@@ -1085,7 +1032,7 @@ RCT_EXPORT_METHOD(iso15693_resetToReady:(NSDictionary *)options callback:(nonnul
1085
1032
 
1086
1033
  RCT_EXPORT_METHOD(iso15693_select:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
1087
1034
  {
1088
- if (@available(iOS 13.0, *)) {
1035
+ if (@available(iOS 14.0, *)) {
1089
1036
  if (!tagSession || !tagSession.connectedTag) {
1090
1037
  callback(@[@"Not connected", [NSNull null]]);
1091
1038
  return;
@@ -1115,7 +1062,7 @@ RCT_EXPORT_METHOD(iso15693_select:(NSDictionary *)options callback:(nonnull RCTR
1115
1062
 
1116
1063
  RCT_EXPORT_METHOD(iso15693_stayQuiet:(nonnull RCTResponseSenderBlock)callback)
1117
1064
  {
1118
- if (@available(iOS 13.0, *)) {
1065
+ if (@available(iOS 14.0, *)) {
1119
1066
  if (!tagSession || !tagSession.connectedTag) {
1120
1067
  callback(@[@"Not connected", [NSNull null]]);
1121
1068
  return;
@@ -1142,7 +1089,7 @@ RCT_EXPORT_METHOD(iso15693_stayQuiet:(nonnull RCTResponseSenderBlock)callback)
1142
1089
 
1143
1090
  RCT_EXPORT_METHOD(iso15693_customCommand:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
1144
1091
  {
1145
- if (@available(iOS 13.0, *)) {
1092
+ if (@available(iOS 14.0, *)) {
1146
1093
  if (!tagSession || !tagSession.connectedTag) {
1147
1094
  callback(@[@"Not connected", [NSNull null]]);
1148
1095
  return;
@@ -1156,7 +1103,7 @@ RCT_EXPORT_METHOD(iso15693_customCommand:(NSDictionary *)options callback:(nonnu
1156
1103
 
1157
1104
  RequestFlag flags = [[options objectForKey:@"flags"] unsignedIntValue];
1158
1105
  NSInteger customCommandCode = [[options objectForKey:@"customCommandCode"] integerValue];
1159
- NSData *customRequestParameters = [self arrayToData:[options mutableArrayValueForKey:@"customRequestParameters"]];
1106
+ NSData *customRequestParameters = arrayToData([options mutableArrayValueForKey:@"customRequestParameters"]);
1160
1107
 
1161
1108
  [tag customCommandWithRequestFlag:flags
1162
1109
  customCommandCode: customCommandCode
@@ -1167,7 +1114,40 @@ RCT_EXPORT_METHOD(iso15693_customCommand:(NSDictionary *)options callback:(nonnu
1167
1114
  return;
1168
1115
  }
1169
1116
 
1170
- callback(@[[NSNull null], [NfcManager dataToArray:resp]]);
1117
+ callback(@[[NSNull null], dataToArray(resp)]);
1118
+ }];
1119
+ } else {
1120
+ callback(@[@"Not support in this device", [NSNull null]]);
1121
+ }
1122
+ }
1123
+
1124
+ RCT_EXPORT_METHOD(iso15693_sendRequest:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
1125
+ {
1126
+ if (@available(iOS 14.0, *)) {
1127
+ if (!tagSession || !tagSession.connectedTag) {
1128
+ callback(@[@"Not connected", [NSNull null]]);
1129
+ return;
1130
+ }
1131
+
1132
+ id<NFCISO15693Tag> tag = [tagSession.connectedTag asNFCISO15693Tag];
1133
+ if (!tag) {
1134
+ callback(@[@"incorrect tag type", [NSNull null]]);
1135
+ return;
1136
+ }
1137
+
1138
+ NSInteger flags = [[options objectForKey:@"flags"] integerValue];
1139
+ NSInteger commandCode = [[options objectForKey:@"commandCode"] integerValue];
1140
+ NSData *data = arrayToData([options mutableArrayValueForKey:@"data"]);
1141
+
1142
+ [tag sendRequestWithFlag:flags
1143
+ commandCode:commandCode
1144
+ data:data
1145
+ completionHandler:^(NFCISO15693ResponseFlag responseFlag, NSData *resp, NSError *error) {
1146
+ if (error) {
1147
+ callback(@[getErrorMessage(error), [NSNull null]]);
1148
+ return;
1149
+ }
1150
+ callback(@[[NSNull null], [NSNumber numberWithLong:responseFlag], dataToArray(resp)]);
1171
1151
  }];
1172
1152
  } else {
1173
1153
  callback(@[@"Not support in this device", [NSNull null]]);
@@ -1176,7 +1156,7 @@ RCT_EXPORT_METHOD(iso15693_customCommand:(NSDictionary *)options callback:(nonnu
1176
1156
 
1177
1157
  RCT_EXPORT_METHOD(iso15693_extendedReadSingleBlock:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
1178
1158
  {
1179
- if (@available(iOS 13.0, *)) {
1159
+ if (@available(iOS 14.0, *)) {
1180
1160
  if (!tagSession || !tagSession.connectedTag) {
1181
1161
  callback(@[@"Not connected", [NSNull null]]);
1182
1162
  return;
@@ -1199,7 +1179,7 @@ RCT_EXPORT_METHOD(iso15693_extendedReadSingleBlock:(NSDictionary *)options callb
1199
1179
  return;
1200
1180
  }
1201
1181
 
1202
- callback(@[[NSNull null], [NfcManager dataToArray:resp]]);
1182
+ callback(@[[NSNull null], dataToArray(resp)]);
1203
1183
  }];
1204
1184
  } else {
1205
1185
  callback(@[@"Not support in this device", [NSNull null]]);
@@ -1208,7 +1188,7 @@ RCT_EXPORT_METHOD(iso15693_extendedReadSingleBlock:(NSDictionary *)options callb
1208
1188
 
1209
1189
  RCT_EXPORT_METHOD(iso15693_extendedWriteSingleBlock:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
1210
1190
  {
1211
- if (@available(iOS 13.0, *)) {
1191
+ if (@available(iOS 14.0, *)) {
1212
1192
  if (!tagSession || !tagSession.connectedTag) {
1213
1193
  callback(@[@"Not connected", [NSNull null]]);
1214
1194
  return;
@@ -1222,7 +1202,7 @@ RCT_EXPORT_METHOD(iso15693_extendedWriteSingleBlock:(NSDictionary *)options call
1222
1202
 
1223
1203
  RequestFlag flags = [[options objectForKey:@"flags"] unsignedIntValue];
1224
1204
  uint16_t blockNumber = [[options objectForKey:@"blockNumber"] unsignedIntValue];
1225
- NSData *dataBlock = [self arrayToData:[options mutableArrayValueForKey:@"dataBlock"]];
1205
+ NSData *dataBlock = arrayToData([options mutableArrayValueForKey:@"dataBlock"]);
1226
1206
 
1227
1207
  [tag extendedWriteSingleBlockWithRequestFlags:flags
1228
1208
  blockNumber:blockNumber
@@ -1242,7 +1222,7 @@ RCT_EXPORT_METHOD(iso15693_extendedWriteSingleBlock:(NSDictionary *)options call
1242
1222
 
1243
1223
  RCT_EXPORT_METHOD(iso15693_extendedLockBlock:(NSDictionary *)options callback:(nonnull RCTResponseSenderBlock)callback)
1244
1224
  {
1245
- if (@available(iOS 13.0, *)) {
1225
+ if (@available(iOS 14.0, *)) {
1246
1226
  if (!tagSession || !tagSession.connectedTag) {
1247
1227
  callback(@[@"Not connected", [NSNull null]]);
1248
1228
  return;
package/ios/Util.m ADDED
@@ -0,0 +1,55 @@
1
+ //
2
+ // Util.m
3
+ // react-native-nfc-manager
4
+ //
5
+ // Created by Richie Hsieh on 2022/1/27.
6
+ //
7
+
8
+ #import <Foundation/Foundation.h>
9
+
10
+ NSString* getHexString(NSData *data) {
11
+ NSUInteger capacity = data.length * 2;
12
+ NSMutableString *sbuf = [NSMutableString stringWithCapacity:capacity];
13
+ const unsigned char *buf = data.bytes;
14
+ NSInteger i;
15
+ for (i=0; i<data.length; ++i) {
16
+ [sbuf appendFormat:@"%02lX", (unsigned long)buf[i]];
17
+ }
18
+ return sbuf;
19
+ }
20
+
21
+ NSString* getErrorMessage(NSError *error) {
22
+ NSDictionary *userInfo = [error userInfo];
23
+ NSError *underlyingError = [userInfo objectForKey:NSUnderlyingErrorKey];
24
+ if (underlyingError != nil) {
25
+ return [NSString stringWithFormat:@"%@:%ld,%@:%ld",
26
+ [error domain], (long)[error code],
27
+ [underlyingError domain], (long)[underlyingError code]];
28
+ }
29
+ return [NSString stringWithFormat:@"%@:%ld",
30
+ [error domain], (long)[error code]];
31
+ }
32
+
33
+ NSData * arrayToData(NSArray *array) {
34
+ Byte bytes[[array count]];
35
+ for (int i = 0; i < [array count]; i++) {
36
+ bytes[i] = [[array objectAtIndex:i] integerValue];
37
+ }
38
+ NSData *payload = [[NSData alloc] initWithBytes:bytes length:[array count]];
39
+ return payload;
40
+ }
41
+
42
+ NSArray * dataToArray(NSData *data) {
43
+ const unsigned char *dataBuffer = data ? (const unsigned char *)[data bytes] : NULL;
44
+
45
+ if (!dataBuffer)
46
+ return @[];
47
+
48
+ NSUInteger dataLength = [data length];
49
+ NSMutableArray *array = [NSMutableArray arrayWithCapacity:dataLength];
50
+
51
+ for (int i = 0; i < dataLength; ++i)
52
+ [array addObject:[NSNumber numberWithInteger:dataBuffer[i]]];
53
+
54
+ return array;
55
+ }
package/ndef-lib/index.js CHANGED
@@ -87,8 +87,8 @@ const ExtraTypeRecord = {
87
87
  androidApplicationRecord(packageName, id = []) {
88
88
  return PrimitiveRecord.externalTypeRecord(
89
89
  'android.com:pkg',
90
- id,
91
90
  packageName,
91
+ id,
92
92
  );
93
93
  },
94
94
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nfc-manager",
3
- "version": "3.11.5",
3
+ "version": "3.13.2",
4
4
  "description": "A NFC module for react native.",
5
5
  "main": "src/index.js",
6
6
  "repository": {
package/src/NfcManager.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  } from './NativeNfcManager';
8
8
  import {NdefHandler, NdefStatus} from './NfcTech/NdefHandler';
9
9
  import {NfcAHandler} from './NfcTech/NfcAHandler';
10
+ import {NfcVHandler} from './NfcTech/NfcVHandler';
10
11
  import {IsoDepHandler} from './NfcTech/IsoDepHandler';
11
12
  import {
12
13
  handleNativeException,
@@ -33,6 +34,7 @@ const NfcTech = {
33
34
  MifareIOS: 'mifare',
34
35
  Iso15693IOS: 'iso15693',
35
36
  FelicaIOS: 'felica',
37
+ NdefFormatable: 'NdefFormatable',
36
38
  };
37
39
 
38
40
  const DEFAULT_REGISTER_TAG_EVENT_OPTIONS = {
@@ -124,6 +126,13 @@ class NfcManagerBase {
124
126
  return this._nfcAHandler;
125
127
  }
126
128
 
129
+ get nfcVHandler() {
130
+ if (!this._nfcVHandler) {
131
+ this._nfcVHandler = new NfcVHandler();
132
+ }
133
+ return this._nfcVHandler;
134
+ }
135
+
127
136
  get isoDepHandler() {
128
137
  if (!this._isoDepHandler) {
129
138
  this._isoDepHandler = new IsoDepHandler();
@@ -2,6 +2,7 @@ import {callNative} from './NativeNfcManager';
2
2
  import {NfcManagerBase} from './NfcManager';
3
3
  import {MifareClassicHandlerAndroid} from './NfcTech/MifareClassicHandlerAndroid';
4
4
  import {MifareUltralightHandlerAndroid} from './NfcTech/MifareUltralightHandlerAndroid';
5
+ import {NdefFormatableHandlerAndroid} from './NfcTech/NdefFormatableHandlerAndroid';
5
6
  import {handleNativeException, buildNfcExceptionAndroid} from './NfcError';
6
7
 
7
8
  const NfcAdapter = {
@@ -14,6 +15,8 @@ const NfcAdapter = {
14
15
  FLAG_READER_NO_PLATFORM_SOUNDS: 0x100,
15
16
  };
16
17
 
18
+ const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
19
+
17
20
  class NfcManagerAndroid extends NfcManagerBase {
18
21
  constructor() {
19
22
  super();
@@ -41,12 +44,13 @@ class NfcManagerAndroid extends NfcManagerBase {
41
44
  };
42
45
 
43
46
  cancelTechnologyRequest = async (options = {}) => {
44
- const {throwOnError = false} = options;
47
+ const {throwOnError = false, delayMsAndroid = 1000} = options;
45
48
 
46
49
  try {
47
50
  await callNative('cancelTechnologyRequest');
48
51
 
49
- if (!this.cleanUpTagRegistration) {
52
+ if (this.cleanUpTagRegistration) {
53
+ await delay(delayMsAndroid);
50
54
  await this.unregisterTagEvent();
51
55
  this.cleanUpTagRegistration = false;
52
56
  }
@@ -111,6 +115,16 @@ class NfcManagerAndroid extends NfcManagerBase {
111
115
  return this._mifareUltralightHandlerAndroid;
112
116
  }
113
117
 
118
+ // -------------------------------------
119
+ // (android) NfcTech.NdefFormatable API
120
+ // -------------------------------------
121
+ get ndefFormatableHandlerAndroid() {
122
+ if (!this._ndefFormatableHandlerAndroid) {
123
+ this._ndefFormatableHandlerAndroid = new NdefFormatableHandlerAndroid(this);
124
+ }
125
+ return this._ndefFormatableHandlerAndroid;
126
+ }
127
+
114
128
  // -------------------------------------
115
129
  // Android private
116
130
  // -------------------------------------
@@ -8,6 +8,7 @@ import {
8
8
  } from './NfcManager';
9
9
  import {
10
10
  Nfc15693RequestFlagIOS,
11
+ Nfc15693ResponseFlagIOS,
11
12
  Iso15693HandlerIOS,
12
13
  } from './NfcTech/Iso15693HandlerIOS';
13
14
  import {handleNativeException} from './NfcError';
@@ -30,6 +31,8 @@ class NfcManagerIOS extends NfcManagerBase {
30
31
  for (const t of tech) {
31
32
  if (t === NfcTech.NfcA) {
32
33
  techList.push(NfcTech.MifareIOS);
34
+ } else if (t === NfcTech.NfcV) {
35
+ techList.push(NfcTech.Iso15693IOS);
33
36
  } else {
34
37
  techList.push(t);
35
38
  }
@@ -145,4 +148,4 @@ class NfcManagerIOS extends NfcManagerBase {
145
148
  }
146
149
  }
147
150
 
148
- export {NfcManagerIOS, Nfc15693RequestFlagIOS};
151
+ export {NfcManagerIOS, Nfc15693RequestFlagIOS, Nfc15693ResponseFlagIOS};
@@ -8,6 +8,17 @@ const Nfc15693RequestFlagIOS = {
8
8
  Select: 1 << 4,
9
9
  Address: 1 << 5,
10
10
  Option: 1 << 6,
11
+ CommandSpecificBit8: 1 << 7,
12
+ };
13
+
14
+ const Nfc15693ResponseFlagIOS = {
15
+ Error: 1 << 0,
16
+ ResponseBufferValid: 1 << 1,
17
+ FinalResponse: 1 << 2,
18
+ ProtocolExtension: 1 << 3,
19
+ BlockSecurityStatusBit5: 1 << 4,
20
+ BlockSecurityStatusBit6: 1 << 5,
21
+ WaitTimeExtension: 1 << 6
11
22
  };
12
23
 
13
24
  class Iso15693HandlerIOS {
@@ -87,6 +98,15 @@ class Iso15693HandlerIOS {
87
98
  );
88
99
  }
89
100
 
101
+ // https://developer.apple.com/documentation/corenfc/nfciso15693tag/3551933-sendrequestwithflag?language=objc
102
+ sendRequest({flags, commandCode, data}) {
103
+ return handleNativeException(
104
+ callNative('iso15693_sendRequest', [
105
+ {flags, commandCode, data},
106
+ ]),
107
+ );
108
+ }
109
+
90
110
  extendedReadSingleBlock({flags, blockNumber}) {
91
111
  return handleNativeException(
92
112
  callNative('iso15693_extendedReadSingleBlock', [{flags, blockNumber}]),
@@ -108,4 +128,4 @@ class Iso15693HandlerIOS {
108
128
  }
109
129
  }
110
130
 
111
- export {Nfc15693RequestFlagIOS, Iso15693HandlerIOS};
131
+ export {Nfc15693RequestFlagIOS, Nfc15693ResponseFlagIOS, Iso15693HandlerIOS};
@@ -0,0 +1,16 @@
1
+ import {callNative} from '../NativeNfcManager';
2
+ import {handleNativeException} from '../NfcError';
3
+
4
+ class NdefFormatableHandlerAndroid {
5
+ async formatNdef(bytes, options={}) {
6
+ const defaultOptions = { readOnly: false };
7
+ return handleNativeException(
8
+ callNative('formatNdef', [
9
+ bytes,
10
+ {...defaultOptions, ...options}
11
+ ])
12
+ );
13
+ }
14
+ }
15
+
16
+ export {NdefFormatableHandlerAndroid};
@@ -0,0 +1,39 @@
1
+ import {Platform} from 'react-native';
2
+ import {callNative, NativeNfcManager} from '../NativeNfcManager';
3
+ import {handleNativeException} from '../NfcError';
4
+
5
+ class NfcVHandler {
6
+ async transceive(bytes) {
7
+ if (!Array.isArray(bytes)) {
8
+ throw new Error(
9
+ 'IsoDepHandler.transceive only takes input as a byte array',
10
+ );
11
+ }
12
+
13
+ if (Platform.OS === 'ios') {
14
+ const [flags, commandCode, ...data] = bytes;
15
+ return handleNativeException(
16
+ new Promise((resolve, reject) => {
17
+ NativeNfcManager.iso15693_sendRequest(
18
+ {
19
+ flags,
20
+ commandCode,
21
+ data,
22
+ },
23
+ (err, responseFlag, response) => {
24
+ if (err) {
25
+ reject(err);
26
+ } else {
27
+ resolve([responseFlag, ...response]);
28
+ }
29
+ },
30
+ );
31
+ }),
32
+ );
33
+ }
34
+
35
+ return handleNativeException(callNative('transceive', [bytes]));
36
+ }
37
+ }
38
+
39
+ export {NfcVHandler};
package/src/index.js CHANGED
@@ -4,6 +4,7 @@ import {NfcEvents, NfcTech, NdefStatus} from './NfcManager';
4
4
  import {NfcAdapter, NfcManagerAndroid} from './NfcManagerAndroid';
5
5
  import {
6
6
  Nfc15693RequestFlagIOS,
7
+ Nfc15693ResponseFlagIOS,
7
8
  NfcManagerIOS,
8
9
  } from './NfcManagerIOS';
9
10
  import * as NfcError from './NfcError';
@@ -26,6 +27,7 @@ export {
26
27
  NfcEvents,
27
28
  NfcAdapter,
28
29
  Nfc15693RequestFlagIOS,
30
+ Nfc15693ResponseFlagIOS,
29
31
  Ndef,
30
32
  NdefStatus,
31
33
  NfcError,