react-native-nfc-manager 3.13.1 → 3.13.4

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,6 +69,12 @@ 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
+ ## Learn
73
+
74
+ We have published a React Native NFC course with [newline.co](https://www.newline.co/), check it out!
75
+ - Free course (1 hour) about basic NFC setup and concept [here](https://www.youtube.com/watch?v=rAS-DvNUFck)
76
+ - Full course (3 hours) for more (NDEF, Deep Linking, NTAG password protection, signature with UID) [here](https://www.newline.co/courses/newline-guide-to-nfcs-with-react-native)
77
+
72
78
  ## Usage
73
79
 
74
80
  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:
@@ -536,6 +536,99 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
536
536
  }
537
537
  }
538
538
 
539
+ @ReactMethod
540
+ public void mifareClassicIncrementBlock(int blockIndex, int value, Callback callback) {
541
+ synchronized(this) {
542
+ if (techRequest != null) {
543
+ try {
544
+ MifareClassic mifareTag = (MifareClassic) techRequest.getTechHandle();
545
+ if (mifareTag == null || mifareTag.getType() == MifareClassic.TYPE_UNKNOWN) {
546
+ // Not a mifare card, fail
547
+ callback.invoke("mifareClassicIncrementBlock fail: TYPE_UNKNOWN");
548
+ return;
549
+ } else if (blockIndex >= mifareTag.getBlockCount()) {
550
+ // Check if in range
551
+ String msg = String.format("mifareClassicIncrementBlock fail: invalid block %d (max %d)", blockIndex, mifareTag.getBlockCount());
552
+ callback.invoke(msg);
553
+ return;
554
+ }
555
+
556
+ mifareTag.increment(blockIndex, value);
557
+
558
+ callback.invoke(null, true);
559
+ } catch (TagLostException ex) {
560
+ callback.invoke("mifareClassicIncrementBlock fail: TAG_LOST");
561
+ } catch (Exception ex) {
562
+ callback.invoke("mifareClassicIncrementBlock fail: " + ex.toString());
563
+ }
564
+ } else {
565
+ callback.invoke(ERR_NO_TECH_REQ);
566
+ }
567
+ }
568
+ }
569
+
570
+ @ReactMethod
571
+ public void mifareClassicDecrementBlock(int blockIndex, int value, Callback callback) {
572
+ synchronized(this) {
573
+ if (techRequest != null) {
574
+ try {
575
+ MifareClassic mifareTag = (MifareClassic) techRequest.getTechHandle();
576
+ if (mifareTag == null || mifareTag.getType() == MifareClassic.TYPE_UNKNOWN) {
577
+ // Not a mifare card, fail
578
+ callback.invoke("mifareClassicDecrementBlock fail: TYPE_UNKNOWN");
579
+ return;
580
+ } else if (blockIndex >= mifareTag.getBlockCount()) {
581
+ // Check if in range
582
+ String msg = String.format("mifareClassicDecrementBlock fail: invalid block %d (max %d)", blockIndex, mifareTag.getBlockCount());
583
+ callback.invoke(msg);
584
+ return;
585
+ }
586
+
587
+ mifareTag.decrement(blockIndex, value);
588
+
589
+ callback.invoke(null, true);
590
+ } catch (TagLostException ex) {
591
+ callback.invoke("mifareClassicDecrementBlock fail: TAG_LOST");
592
+ } catch (Exception ex) {
593
+ callback.invoke("mifareClassicDecrementBlock fail: " + ex.toString());
594
+ }
595
+ } else {
596
+ callback.invoke(ERR_NO_TECH_REQ);
597
+ }
598
+ }
599
+ }
600
+
601
+ @ReactMethod
602
+ public void mifareClassicTransferBlock(int blockIndex, Callback callback) {
603
+ synchronized(this) {
604
+ if (techRequest != null) {
605
+ try {
606
+ MifareClassic mifareTag = (MifareClassic) techRequest.getTechHandle();
607
+ if (mifareTag == null || mifareTag.getType() == MifareClassic.TYPE_UNKNOWN) {
608
+ // Not a mifare card, fail
609
+ callback.invoke("mifareClassicTransferBlock fail: TYPE_UNKNOWN");
610
+ return;
611
+ } else if (blockIndex >= mifareTag.getBlockCount()) {
612
+ // Check if in range
613
+ String msg = String.format("mifareClassicTransferBlock fail: invalid block %d (max %d)", blockIndex, mifareTag.getBlockCount());
614
+ callback.invoke(msg);
615
+ return;
616
+ }
617
+
618
+ mifareTag.transfer(blockIndex);
619
+
620
+ callback.invoke(null, true);
621
+ } catch (TagLostException ex) {
622
+ callback.invoke("mifareClassicTransferBlock fail: TAG_LOST");
623
+ } catch (Exception ex) {
624
+ callback.invoke("mifareClassicTransferBlock fail: " + ex.toString());
625
+ }
626
+ } else {
627
+ callback.invoke(ERR_NO_TECH_REQ);
628
+ }
629
+ }
630
+ }
631
+
539
632
  @ReactMethod
540
633
  public void mifareUltralightReadPages(int pageOffset, Callback callback) {
541
634
  synchronized(this) {
@@ -971,11 +1064,11 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
971
1064
 
972
1065
  @ReactMethod
973
1066
  private void registerTagEvent(ReadableMap options, Callback callback) {
974
- this.isReaderModeEnabled = options.getBoolean("isReaderModeEnabled");
975
- this.readerModeFlags = options.getInt("readerModeFlags");
976
- this.readerModeDelay = options.getInt("readerModeDelay");
1067
+ isReaderModeEnabled = options.getBoolean("isReaderModeEnabled");
1068
+ readerModeFlags = options.getInt("readerModeFlags");
1069
+ readerModeDelay = options.getInt("readerModeDelay");
977
1070
 
978
- Log.d(LOG_TAG, "registerTag");
1071
+ Log.d(LOG_TAG, "registerTagEvent");
979
1072
  isForegroundEnabled = true;
980
1073
 
981
1074
  // capture all mime-based dispatch NDEF
@@ -1002,18 +1095,23 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
1002
1095
 
1003
1096
  @ReactMethod
1004
1097
  private void unregisterTagEvent(Callback callback) {
1005
- Log.d(LOG_TAG, "registerTag");
1006
- isForegroundEnabled = false;
1007
- intentFilters.clear();
1098
+ Log.d(LOG_TAG, "unregisterTagEvent");
1008
1099
  if (isResumed) {
1009
1100
  enableDisableForegroundDispatch(false);
1010
1101
  }
1102
+
1103
+ intentFilters.clear();
1104
+ isForegroundEnabled = false;
1105
+ isReaderModeEnabled = false;
1106
+ readerModeFlags = 0;
1107
+ readerModeDelay = 0;
1108
+
1011
1109
  callback.invoke();
1012
1110
  }
1013
1111
 
1014
1112
  @ReactMethod
1015
1113
  private void hasTagEventRegistration(Callback callback) {
1016
- Log.d(LOG_TAG, "isSessionAvailable");
1114
+ Log.d(LOG_TAG, "isSessionAvailable: " + isForegroundEnabled);
1017
1115
  callback.invoke(null, isForegroundEnabled);
1018
1116
  }
1019
1117
 
@@ -1061,25 +1159,36 @@ class NfcManager extends ReactContextBaseJavaModule implements ActivityEventList
1061
1159
  }
1062
1160
 
1063
1161
  if (enable) {
1064
- Log.i(LOG_TAG, "enableReaderMode");
1162
+ Log.i(LOG_TAG, "enableReaderMode: " + readerModeFlags);
1065
1163
  Bundle readerModeExtras = new Bundle();
1066
1164
  readerModeExtras.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, readerModeDelay * 1000);
1067
1165
  nfcAdapter.enableReaderMode(currentActivity, new NfcAdapter.ReaderCallback() {
1068
1166
  @Override
1069
1167
  public void onTagDiscovered(Tag tag) {
1070
- manager.tag = tag;
1071
- Log.d(LOG_TAG, "readerMode onTagDiscovered");
1072
- WritableMap nfcTag = null;
1073
- // if the tag contains NDEF, we want to report the content
1074
- if (Arrays.asList(tag.getTechList()).contains(Ndef.class.getName())) {
1075
- Ndef ndef = Ndef.get(tag);
1076
- nfcTag = ndef2React(ndef, new NdefMessage[] { ndef.getCachedNdefMessage() });
1077
- } else {
1078
- nfcTag = tag2React(tag);
1079
- }
1080
-
1081
- if (nfcTag != null) {
1082
- sendEvent("NfcManagerDiscoverTag", nfcTag);
1168
+ synchronized (this) {
1169
+ manager.tag = tag;
1170
+ Log.d(LOG_TAG, "readerMode onTagDiscovered");
1171
+ WritableMap nfcTag = null;
1172
+ // if the tag contains NDEF, we want to report the content
1173
+ if (Arrays.asList(tag.getTechList()).contains(Ndef.class.getName())) {
1174
+ Ndef ndef = Ndef.get(tag);
1175
+ nfcTag = ndef2React(ndef, new NdefMessage[] { ndef.getCachedNdefMessage() });
1176
+ } else {
1177
+ nfcTag = tag2React(tag);
1178
+ }
1179
+
1180
+ if (nfcTag != null) {
1181
+ sendEvent("NfcManagerDiscoverTag", nfcTag);
1182
+ if (techRequest!= null && !techRequest.isConnected()) {
1183
+ boolean result = techRequest.connect(tag);
1184
+ if (result) {
1185
+ techRequest.getPendingCallback().invoke(null, techRequest.getTechType());
1186
+ } else {
1187
+ // this indicates that we get a NFC tag, but none of the user required tech is matched
1188
+ techRequest.getPendingCallback().invoke(null, null);
1189
+ }
1190
+ }
1191
+ }
1083
1192
  }
1084
1193
  }
1085
1194
  }, readerModeFlags, readerModeExtras);
package/index.d.ts CHANGED
@@ -88,6 +88,7 @@ declare module 'react-native-nfc-manager' {
88
88
 
89
89
  export interface CancelTechReqOpts {
90
90
  throwOnError?: boolean = false;
91
+ delayMsAndroid?: number = 1000;
91
92
  }
92
93
 
93
94
  interface NdefHandler {
@@ -122,11 +123,26 @@ declare module 'react-native-nfc-manager' {
122
123
  block: ArrayLike<number>,
123
124
  simpliArr: any[],
124
125
  ) => Promise<void>;
126
+ mifareClassicIncrementBlock: (
127
+ block: ArrayLike<number>,
128
+ data: number,
129
+ ) => Promise<void>;
130
+ mifareClassicDecrementBlock: (
131
+ block: ArrayLike<number>,
132
+ data: number,
133
+ ) => Promise<void>;
134
+ mifareClassicTransferBlock: (
135
+ block: ArrayLike<number>,
136
+ ) => Promise<void>;
125
137
  mifareClassicGetSectorCount: () => Promise<number>;
126
138
  mifareClassicAuthenticateA: (
127
139
  sector: number,
128
140
  keys: number[],
129
141
  ) => Promise<void>;
142
+ mifareClassicAuthenticateB: (
143
+ sector: number,
144
+ keys: number[],
145
+ ) => Promise<void>;
130
146
  }
131
147
 
132
148
  interface MifareUltralightHandlerAndroid {
package/ios/NfcManager.m CHANGED
@@ -286,8 +286,12 @@ RCT_EXPORT_METHOD(requestTechnology: (NSArray *)techs options: (NSDictionary *)o
286
286
  {
287
287
  if (@available(iOS 13.0, *)) {
288
288
  if (tagSession == nil && session == nil) {
289
+ NFCPollingOption pollFlags = NFCPollingISO14443 | NFCPollingISO15693;
290
+ if ([techs containsObject:@"felica"]) {
291
+ pollFlags |= NFCPollingISO18092;
292
+ }
289
293
  tagSession = [[NFCTagReaderSession alloc]
290
- initWithPollingOption:(NFCPollingISO14443 | NFCPollingISO15693) delegate:self queue:dispatch_get_main_queue()];
294
+ initWithPollingOption:pollFlags delegate:self queue:dispatch_get_main_queue()];
291
295
  tagSession.alertMessage = [options objectForKey:@"alertMessage"];
292
296
  [tagSession beginSession];
293
297
  techRequestTypes = techs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nfc-manager",
3
- "version": "3.13.1",
3
+ "version": "3.13.4",
4
4
  "description": "A NFC module for react native.",
5
5
  "main": "src/index.js",
6
6
  "repository": {
@@ -14,5 +14,9 @@ Pod::Spec.new do |s|
14
14
  s.source_files = "ios/**/*.{h,m}"
15
15
  s.platform = :ios, "8.0"
16
16
 
17
- s.dependency "React"
17
+ s.dependency "React-Core"
18
+
19
+ s.xcconfig = {
20
+ 'OTHER_LDFLAGS': '-weak_framework CoreNFC',
21
+ }
18
22
  end
@@ -15,6 +15,8 @@ const NfcAdapter = {
15
15
  FLAG_READER_NO_PLATFORM_SOUNDS: 0x100,
16
16
  };
17
17
 
18
+ const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
19
+
18
20
  class NfcManagerAndroid extends NfcManagerBase {
19
21
  constructor() {
20
22
  super();
@@ -42,12 +44,13 @@ class NfcManagerAndroid extends NfcManagerBase {
42
44
  };
43
45
 
44
46
  cancelTechnologyRequest = async (options = {}) => {
45
- const {throwOnError = false} = options;
47
+ const {throwOnError = false, delayMsAndroid = 1000} = options;
46
48
 
47
49
  try {
48
50
  await callNative('cancelTechnologyRequest');
49
51
 
50
- if (!this.cleanUpTagRegistration) {
52
+ if (this.cleanUpTagRegistration) {
53
+ await delay(delayMsAndroid);
51
54
  await this.unregisterTagEvent();
52
55
  this.cleanUpTagRegistration = false;
53
56
  }
@@ -67,6 +67,48 @@ class MifareClassicHandlerAndroid {
67
67
  callNative('mifareClassicWriteBlock', [block, data]),
68
68
  );
69
69
  }
70
+
71
+ async mifareClassicIncrementBlock(block, value) {
72
+ if (
73
+ !value ||
74
+ Number.isNaN(value)) {
75
+ throw new Error(
76
+ `value should be a number`,
77
+ );
78
+ }
79
+
80
+ return handleNativeException(
81
+ callNative('mifareClassicIncrementBlock', [block, value]),
82
+ );
83
+ }
84
+
85
+ async mifareClassicDecrementBlock(block, value) {
86
+ if (
87
+ !value ||
88
+ Number.isNaN(value)) {
89
+ throw new Error(
90
+ `value should be a number`,
91
+ );
92
+ }
93
+
94
+ return handleNativeException(
95
+ callNative('mifareClassicDecrementBlock', [block, value]),
96
+ );
97
+ }
98
+ async mifareClassicTransferBlock(block) {
99
+ if (
100
+ !block ||
101
+ Number.isNaN(block)) {
102
+ throw new Error(
103
+ `block should be a number`,
104
+ );
105
+ }
106
+
107
+ return handleNativeException(
108
+ callNative('mifareClassicTransferBlock', [block]),
109
+ );
110
+ }
111
+
70
112
  }
71
113
 
72
114
  export {MifareClassicHandlerAndroid};