After following the reproduction steps below, there is no response on the screen, the reader session does not start, and the following error log is displayed. How can I run coreNFC's "NFCNDEFReaderSession.begin()" in a flutter project to successfully start the reader session and display the reading screen?
By the way, even if you create a project from Xcode rather than flutter, and use either of the two frameworks (UIkit or swiftUI), if you follow the steps below to reproduce it, it will be read and displayed on the screen without any problems, and a reader session will start to read it. .
[Development PC] MacOS Ventura version 13.5 [IDE] Android Studio Giraffe (Flutter) Xcode15.1 (UIkit) [Execution terminal] iOS 17.3.1 iPhone11 pro
[procedure]
・Create a flutter project.
・Added "Near Field Communication Tag Reading (release)"
XCode>Projects>Targets>Runner>signing&Capabilities
・Added "Privacy - NFC Scan Usage Description"
XCode>Project>Targets>Runner>info
・Run the app from the actual device
・In AppDelegate, "getTagID" is called from flutter to iOS using native code access and transitions to NFCViewController. -Then, onClickButton(beginScanning) is pressed in NFCViewController, but session?.begin() is not executed because readingAvailable=false.
[Code]
@available(iOS 13.0, *)
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let rfidChannel = FlutterMethodChannel(name: "rfid_native_code/rfid", binaryMessenger: controller.binaryMessenger)
rfidChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
// This method is invoked on the UI thread.
guard call.method == "getTagID" else {
result(FlutterMethodNotImplemented)
return
}
let nextController = controller.storyboard?.instantiateViewController(withIdentifier: "NFCViewController")
controller.present(nextController!, animated: true, completion: nil)
result("call nfc")
})
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
class NFCViewController: UIViewController, NFCNDEFReaderSessionDelegate {
var detectedMessages = [NFCNDEFMessage]()
var session: NFCNDEFReaderSession?
public func beginScanning() {
guard NFCNDEFReaderSession.readingAvailable else {
print("@@@ beginScanning: readingAvailable = false")
return
}
session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)
session?.alertMessage = "Hold your iPhone near an item to see details about that item."
session?.begin()
}
func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
DispatchQueue.main.async {
self.detectedMessages.append(contentsOf: messages)
}
}
func addMessage(fromUserActivity message: NFCNDEFMessage) {
DispatchQueue.main.async {
self.detectedMessages.append(message)
}
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
if let readerError = error as? NFCReaderError {
if (readerError.code != .readerSessionInvalidationErrorFirstNDEFTagRead)
&& (readerError.code != .readerSessionInvalidationErrorUserCanceled) {
let alertController = UIAlertController(
title: "Session Invalidated",
message: error.localizedDescription,
preferredStyle: .alert
)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
DispatchQueue.main.async {
}
}
}
self.session = nil
}
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func onClickButton(_ sender: Any) {
self.beginScanning()
}
}