From b3ff7d459c07d99bf888741fc7a98d53b7b831f4 Mon Sep 17 00:00:00 2001 From: Shogo Iwano Date: Fri, 22 Dec 2023 11:00:24 +0900 Subject: [PATCH 1/3] Fix missing 'id' field in FeliCa card reading on iOS --- ios/Classes/SwiftFlutterNfcKitPlugin.swift | 2 ++ lib/flutter_nfc_kit.dart | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ios/Classes/SwiftFlutterNfcKitPlugin.swift b/ios/Classes/SwiftFlutterNfcKitPlugin.swift index 50b6f6f..0ebf864 100644 --- a/ios/Classes/SwiftFlutterNfcKitPlugin.swift +++ b/ios/Classes/SwiftFlutterNfcKitPlugin.swift @@ -508,6 +508,7 @@ public class SwiftFlutterNfcKitPlugin: NSObject, FlutterPlugin, NFCTagReaderSess case let .feliCa(tag): result["type"] = "iso18092" result["standard"] = "ISO 18092 (FeliCa)" + result["id"] = "unknown" result["systemCode"] = tag.currentSystemCode.hexEncodedString() result["manufacturer"] = tag.currentIDm.hexEncodedString() case let .iso15693(tag): @@ -518,6 +519,7 @@ public class SwiftFlutterNfcKitPlugin: NSObject, FlutterPlugin, NFCTagReaderSess default: result["type"] = "unknown" result["standard"] = "unknown" + result["id"] = "unknown" } session.connect(to: firstTag) { (error: Error?) in diff --git a/lib/flutter_nfc_kit.dart b/lib/flutter_nfc_kit.dart index 28ba264..22ca0bb 100644 --- a/lib/flutter_nfc_kit.dart +++ b/lib/flutter_nfc_kit.dart @@ -69,7 +69,7 @@ class NFCTag { /// The standard that the tag complies with (can be `unknown`) final String standard; - /// Tag ID + /// Tag ID (can be `unknown`) final String id; /// ATQA (Type A only, Android only) From ca7b5166259b1f6289e1d6c5cd0a133d80249c1c Mon Sep 17 00:00:00 2001 From: Shogo Iwano Date: Fri, 22 Dec 2023 18:00:10 +0900 Subject: [PATCH 2/3] Set the IDm to the `id` and the PMm to the `manufacturer` on iOS --- ios/Classes/SwiftFlutterNfcKitPlugin.swift | 28 +++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/ios/Classes/SwiftFlutterNfcKitPlugin.swift b/ios/Classes/SwiftFlutterNfcKitPlugin.swift index 0ebf864..56fe074 100644 --- a/ios/Classes/SwiftFlutterNfcKitPlugin.swift +++ b/ios/Classes/SwiftFlutterNfcKitPlugin.swift @@ -508,9 +508,8 @@ public class SwiftFlutterNfcKitPlugin: NSObject, FlutterPlugin, NFCTagReaderSess case let .feliCa(tag): result["type"] = "iso18092" result["standard"] = "ISO 18092 (FeliCa)" - result["id"] = "unknown" + result["id"] = tag.currentIDm.hexEncodedString() result["systemCode"] = tag.currentSystemCode.hexEncodedString() - result["manufacturer"] = tag.currentIDm.hexEncodedString() case let .iso15693(tag): result["type"] = "iso15693" result["standard"] = "ISO 15693" @@ -557,10 +556,27 @@ public class SwiftFlutterNfcKitPlugin: NSObject, FlutterPlugin, NFCTagReaderSess result["ndefCapacity"] = capacity } // ignore error, just return with ndef disabled - let jsonData = try! JSONSerialization.data(withJSONObject: result) - let jsonString = String(data: jsonData, encoding: .utf8) - self.result?(jsonString) - self.result = nil + switch self.tag { + case let .feliCa(tag): + tag.polling(systemCode: tag.currentSystemCode, requestCode: .noRequest, timeSlot: .max16) { (pmm: Data, _: Data, error: Error?) in + if let error = error { + self.result?(FlutterError(code: "500", message: "Communication error on connect", details: error.localizedDescription)) + self.result = nil + } else { + result["manufacturer"] = pmm.hexEncodedString() + + let jsonData = try! JSONSerialization.data(withJSONObject: result) + let jsonString = String(data: jsonData, encoding: .utf8) + self.result?(jsonString) + self.result = nil + } + } + default: + let jsonData = try! JSONSerialization.data(withJSONObject: result) + let jsonString = String(data: jsonData, encoding: .utf8) + self.result?(jsonString) + self.result = nil + } } } else { let jsonData = try! JSONSerialization.data(withJSONObject: result) From ce8cf350745c4fc167fe1b6c1e34fbfe99076394 Mon Sep 17 00:00:00 2001 From: rostopira Date: Wed, 21 Feb 2024 15:08:45 +0200 Subject: [PATCH 3/3] Add "iosRestartPolling" method --- ios/Classes/SwiftFlutterNfcKitPlugin.swift | 7 +++++++ lib/flutter_nfc_kit.dart | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/ios/Classes/SwiftFlutterNfcKitPlugin.swift b/ios/Classes/SwiftFlutterNfcKitPlugin.swift index 56fe074..cb7f73e 100644 --- a/ios/Classes/SwiftFlutterNfcKitPlugin.swift +++ b/ios/Classes/SwiftFlutterNfcKitPlugin.swift @@ -50,6 +50,13 @@ public class SwiftFlutterNfcKitPlugin: NSObject, FlutterPlugin, NFCTagReaderSess } else { result("not_supported") } + } else if call.method == "restartPolling" { + if let session = session { + self.result = result + session.restartPolling() + } else { + result(FlutterError(code: "404", message: "No active session", details: nil)) + } } else if call.method == "poll" { if session != nil { result(FlutterError(code: "406", message: "Cannot invoke poll in a active session", details: nil)) diff --git a/lib/flutter_nfc_kit.dart b/lib/flutter_nfc_kit.dart index 22ca0bb..a4c98f9 100644 --- a/lib/flutter_nfc_kit.dart +++ b/lib/flutter_nfc_kit.dart @@ -343,6 +343,13 @@ class FlutterNfcKit { return NFCTag.fromJson(jsonDecode(data)); } + /// Works only on iOS + /// Calls NFCTagReaderSession.restartPolling() + /// Call this if you have received "Tag connection lost" exception + /// This will allow to reconnect to tag without closing system popup + static Future iosRestartPolling() async => + await _channel.invokeMethod("restartPolling"); + /// Transceive data with the card / tag in the format of APDU (iso7816) or raw commands (other technologies). /// The [capdu] can be either of type Uint8List or hex string. /// Return value will be in the same type of [capdu].