react-native-nfc-manager 3.11.4 → 3.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -69,7 +69,7 @@ We have a full featured NFC utility app using this library available for downloa
69
69
 
70
70
  It also open sourced in this repo: [React Native NFC ReWriter App](https://github.com/revtel/react-native-nfc-rewriter)
71
71
 
72
- ## Usage
72
+ ## Usage
73
73
 
74
74
  The simplest (and most common) use case for this library is to read `NFC` tags containing `NDEF`, which can be achieved via the following codes:
75
75
 
@@ -118,6 +118,7 @@ export default App;
118
118
  ```
119
119
 
120
120
  Pleaes notice when running above codes, iOS and Android has different behaviors:
121
+
121
122
  - iOS will pop up a system scanning UI
122
123
  - Android provides **NO** system scanning UI
123
124
 
@@ -130,7 +131,7 @@ There's an alterntaive style to scan NFC tags through `NfcManager.registerTagEve
130
131
  ```javascript
131
132
  import NfcManager, {NfcTech} from 'react-native-nfc-manager';
132
133
 
133
- // The following function resolves to a NFC Tag object using old event listener approach.
134
+ // The following function resolves to a NFC Tag object using old event listener approach.
134
135
  // You can call it like this:
135
136
  // `const nfcTag = await listenToNfcEventOnce()`
136
137
 
@@ -140,10 +141,10 @@ function listenToNfcEventOnce() {
140
141
  NfcManager.setEventListener(NfcEvents.SessionClosed, null);
141
142
  };
142
143
 
143
- return new Promise(resolve => {
144
+ return new Promise((resolve) => {
144
145
  let tagFound = null;
145
146
 
146
- NfcManager.setEventListener(NfcEvents.DiscoverTag, tag => {
147
+ NfcManager.setEventListener(NfcEvents.DiscoverTag, (tag) => {
147
148
  tagFound = tag;
148
149
  resolve(tagFound);
149
150
  NfcManager.unregisterTagEvent();
@@ -168,6 +169,7 @@ As you can see, the above approach is more verbose and hard-to-read, so we recom
168
169
  In higher level, there're 4 steps to use this library:
169
170
 
170
171
  1. request your particular NFC technologies through `NfcManager.requestTechnology`, for example:
172
+
171
173
  - `Ndef`
172
174
  - `NfcA`
173
175
  - `NfcB` (Android-only)
@@ -181,6 +183,7 @@ In higher level, there're 4 steps to use this library:
181
183
  - `FelicaIOS` (ios-only)
182
184
 
183
185
  2. select the proper NFC technology handler, which is implemented as getter in main `NfcManager` object, for example:
186
+
184
187
  - `ndefHandler` (for `Ndef` tech)
185
188
  - `nfcAHandler` (for `NfcA` tech)
186
189
  - `isoDepHandler` (for `IsoDep` tech)
@@ -189,7 +192,7 @@ In higher level, there're 4 steps to use this library:
189
192
  - `mifareUltralightHandlerAndroid` (for `mifareUltralight` tech)
190
193
  - ... and so on
191
194
 
192
- 3. call specific methods on the NFC technology handler (for example `NfcManager.ndefHandler.writeNdefMessage`). To view all available methods for some tech handler, check out the [API List]((index.d.ts))
195
+ 3. call specific methods on the NFC technology handler (for example `NfcManager.ndefHandler.writeNdefMessage`). To view all available methods for some tech handler, check out the [API List](index.d.ts)
193
196
 
194
197
  4. clean up your tech registration through `NfcManager.cancelTechnology`
195
198
 
@@ -210,8 +213,7 @@ async function writeNdef({type, value}) {
210
213
  const bytes = Ndef.encodeMessage([Ndef.textRecord('Hello NFC')]);
211
214
 
212
215
  if (bytes) {
213
- await NfcManager
214
- .ndefHandler // STEP 2
216
+ await NfcManager.ndefHandler // STEP 2
215
217
  .writeNdefMessage(bytes); // STEP 3
216
218
  result = true;
217
219
  }
@@ -243,8 +245,7 @@ async function readMifare() {
243
245
  const readLength = 60;
244
246
  const mifarePagesRead = await Promise.all(
245
247
  [...Array(readLength).keys()].map(async (_, i) => {
246
- const pages = await NfcManager
247
- .mifareUltralightHandlerAndroid // STEP 2
248
+ const pages = await NfcManager.mifareUltralightHandlerAndroid // STEP 2
248
249
  .mifareUltralightReadPages(i * 4); // STEP 3
249
250
  mifarePages.push(pages);
250
251
  }),
@@ -286,6 +287,8 @@ After installing this npm package, add the [config plugin](https://docs.expo.io/
286
287
 
287
288
  Next, rebuild your app as described in the ["Adding custom native code"](https://docs.expo.io/workflow/customizing/) guide.
288
289
 
290
+ > Notice: This Config Plugin will ensure the minimum Android SDK version is 31.
291
+
289
292
  #### Props
290
293
 
291
294
  The plugin provides props for extra customization. Every time you change the props or plugins, you'll need to rebuild (and `prebuild`) the native app. If no extra properties are added, defaults will be used.
@@ -312,4 +315,3 @@ The plugin provides props for extra customization. Every time you change the pro
312
315
  }
313
316
  }
314
317
  ```
315
-
@@ -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
 
@@ -1077,7 +1107,7 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
1077
1107
 
1078
1108
  int flag = 0;
1079
1109
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
1080
- flag = PendingIntent.FLAG_MUTABLE;
1110
+ flag = PendingIntent.FLAG_MUTABLE;
1081
1111
  }
1082
1112
  return PendingIntent.getActivity(activity, 0, intent, flag);
1083
1113
  }
@@ -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/app.plugin.js CHANGED
@@ -85,6 +85,14 @@ function withNfc(config, props = {}) {
85
85
  config = withIosNfcEntitlement(config);
86
86
  config = withIosNfcSelectIdentifiers(config, {selectIdentifiers});
87
87
  config = withIosNfcSystemCodes(config, {systemCodes});
88
+
89
+ // We start to support Android 12 from v3.11.1, and you will need to update compileSdkVersion to 31,
90
+ // otherwise the build will fail:
91
+ config = AndroidConfig.Version.withBuildScriptExtMinimumVersion(config, {
92
+ name: 'compileSdkVersion',
93
+ minVersion: 31,
94
+ });
95
+
88
96
  if (nfcPermission !== false) {
89
97
  config = withIosPermission(config, props);
90
98
  config = AndroidConfig.Permissions.withPermissions(config, [
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;
@@ -93,6 +105,10 @@ declare module 'react-native-nfc-manager' {
93
105
  transceive: (bytes: number[]) => Promise<number[]>;
94
106
  }
95
107
 
108
+ interface NfcVHandler {
109
+ transceive: (bytes: number[]) => Promise<number[]>;
110
+ }
111
+
96
112
  interface IsoDepHandler {
97
113
  transceive: (bytes: number[]) => Promise<number[]>;
98
114
  }
@@ -121,6 +137,10 @@ declare module 'react-native-nfc-manager' {
121
137
  ) => Promise<void>;
122
138
  }
123
139
 
140
+ interface NdefFormatableHandlerAndroid {
141
+ formatNdef: (bytes: number[], options?: { readOnly: boolean }) => Promise<void>;
142
+ }
143
+
124
144
  /** [iOS ONLY] */
125
145
  interface Iso15693HandlerIOS {
126
146
  getSystemInfo: (
@@ -159,6 +179,11 @@ declare module 'react-native-nfc-manager' {
159
179
  customCommandCode: number;
160
180
  customRequestParameters: number[];
161
181
  }) => Promise<number[]>;
182
+ sendRequest: (params: {
183
+ flags: number;
184
+ commandCode: number;
185
+ data: number[];
186
+ }) => Promise<[number, number[]]>;
162
187
  extendedReadSingleBlock: (params: {
163
188
  flags: number;
164
189
  blockNumber: number;
@@ -201,6 +226,7 @@ declare module 'react-native-nfc-manager' {
201
226
  */
202
227
  ndefHandler: NdefHandler;
203
228
  nfcAHandler: NfcAHandler;
229
+ nfcVHandler: NfcVHandler;
204
230
  isoDepHandler: IsoDepHandler;
205
231
 
206
232
  /**
@@ -236,6 +262,7 @@ declare module 'react-native-nfc-manager' {
236
262
  setTimeout(timeout: number): Promise<void>;
237
263
  mifareClassicHandlerAndroid: MifareClassicHandlerAndroid;
238
264
  mifareUltralightHandlerAndroid: MifareUltralightHandlerAndroid;
265
+ ndefFormatableHandlerAndroid: NdefFormatableHandlerAndroid;
239
266
  }
240
267
 
241
268
  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.4",
3
+ "version": "3.13.1",
4
4
  "description": "A NFC module for react native.",
5
5
  "main": "src/index.js",
6
6
  "repository": {
@@ -62,7 +62,7 @@
62
62
  "typescript": "^4.1.3"
63
63
  },
64
64
  "dependencies": {
65
- "@expo/config-plugins": "^3.0.6"
65
+ "@expo/config-plugins": "^4.0.16"
66
66
  },
67
67
  "scripts": {
68
68
  "lint": "eslint .",
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 = {
@@ -111,6 +112,16 @@ class NfcManagerAndroid extends NfcManagerBase {
111
112
  return this._mifareUltralightHandlerAndroid;
112
113
  }
113
114
 
115
+ // -------------------------------------
116
+ // (android) NfcTech.NdefFormatable API
117
+ // -------------------------------------
118
+ get ndefFormatableHandlerAndroid() {
119
+ if (!this._ndefFormatableHandlerAndroid) {
120
+ this._ndefFormatableHandlerAndroid = new NdefFormatableHandlerAndroid(this);
121
+ }
122
+ return this._ndefFormatableHandlerAndroid;
123
+ }
124
+
114
125
  // -------------------------------------
115
126
  // Android private
116
127
  // -------------------------------------
@@ -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,