0

Guys, I need your help, please.

What do I need: to get the tag's UID using iOS app What do I have: I have an app Flutter, which works fine on Android (I can read the tag's UID) and do nothing on iOS

Details: I have this type of cards (plastic card) card's data, Mifare Classis 1k

As you can see, this is the Mifare Classic 1k card with payload "My text with spaces"

I used flutter channels to communicate between flutter and iOS native (swift)

On iOS side I created two implementations: one for NFCTagReaderSession, another one for NFCNDEFReaderSession (I do not use it at the same time, only separated)

1. NFCTagReaderSession implementation

import UIKit
import Flutter
import CoreNFC

@available(iOS 13.0, *)
var session_tag: NFCTagReaderSession?
@available(iOS 13.0, *)
var flutterResult: FlutterResult!

@available(iOS 13.0, *)
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate, NFCTagReaderSessionDelegate {
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
        let nfcChannel = FlutterMethodChannel(name: "samples.flutter.dev/nfc", binaryMessenger: controller.binaryMessenger)
        nfcChannel.setMethodCallHandler({
            [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
            // Note: this method is invoked on the UI thread.
            guard call.method == "getNFCTag" else {
                result(FlutterMethodNotImplemented)
                return
            }
            if NFCTagReaderSession.readingAvailable {
                print("we are ready for reading");
                self?.startReadingNFC(result: result)
            } else {
                print("sorry byt not working");
            }
        })
        
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    private func startReadingNFC(result: @escaping FlutterResult) {
        flutterResult = result
        session_tag = NFCTagReaderSession(pollingOption: .iso14443, delegate: self, queue: DispatchQueue.main)
        session_tag?.alertMessage = "Hold ur phone!"
        session_tag?.begin()
    }
    
    func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
        print("Tag session active")
    }
    
    func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
        print("Did detect tag reader session")
        print(tags.count)
        if case let NFCTag.miFare(tag) = tags.first! {
            session.connect(to: tags.first!) { (error: Error?) in
                let tagUIDData = tag.identifier
                var byteData: [UInt8] = []
                tagUIDData.withUnsafeBytes { byteData.append(contentsOf: $0) }
                session.invalidate()
                print(self.hexEncodedString(byteArray: byteData))
//                DispatchQueue.main.async {
                    //flutterResult(self.hexEncodedString(byteArray: byteData))
                    
//                }
            }
        }
    }
    
    func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
        print("Tag Error: \(error.localizedDescription)")
        
    }
    
    func hexEncodedString(byteArray: [UInt8]) -> String {
        let hexDigits = Array("0123456789abcdef".utf16)
        var hexChars = [UTF16.CodeUnit]()
        hexChars.reserveCapacity(byteArray.count * 2)
        
        for byte in byteArray {
            let (index1, index2) = Int(byte).quotientAndRemainder(dividingBy: 16)
            hexChars.append(hexDigits[index1])
            hexChars.append(hexDigits[index2])
        }
        
        return String(utf16CodeUnits: hexChars, count: hexChars.count)
    }
}

When i'm pressing the button in my app, i can see the NFC reading window on my phone iOS app NFC reading window

But, when i put the card up to a phone, there is noting happened. Android Studio console Android studio console

2. NFCNDEFReaderSession

import UIKit
import Flutter
import CoreNFC

@available(iOS 13.0, *)
var session_tag: NFCNDEFReaderSession?
@available(iOS 13.0, *)
var flutterResult: FlutterResult!

@available(iOS 13.0, *)
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate, NFCNDEFReaderSessionDelegate {

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {

    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    let nfcChannel = FlutterMethodChannel(name: "samples.flutter.dev/nfc", binaryMessenger: controller.binaryMessenger)
    nfcChannel.setMethodCallHandler({
        [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
      // Note: this method is invoked on the UI thread.
      guard call.method == "getNFCTag" else {
        result(FlutterMethodNotImplemented)
        return
      }
      if NFCNDEFReaderSession.readingAvailable {
          print("we are ready for reading");
          self?.startReadingNFC(result: result)
      } else {
          print("sorry byt not working");
      }
    })

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
     func startReadingNFC(result: @escaping FlutterResult) {
        print("start reading session")
        flutterResult = result
//         session_tag = NFCNDEFReaderSession(pollingOption: [.iso14443], delegate: self, queue: DispatchQueue.main)
        session_tag = NFCNDEFReaderSession(delegate: self, queue: DispatchQueue.main, invalidateAfterFirstRead: false)
        session_tag?.alertMessage = NSLocalizedString("Hold it!", comment: "my comment")
        session_tag?.begin()
    }

    func tagReaderSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
        print("Tag session active")
    }

    func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
        print(messages)
      for message in messages {
        for record in message.records {
            print("next message")
            print(record)
        }
      }
    }

    func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) {
        if (tags.count > 0) {
            session.connect(to: tags.first!, completionHandler: { (connection_error) in
                tags.first?.readNDEF(completionHandler: { (message, error) in
                    if ((message?.records.count)! > 0) {
                        if let dataMessage = String(data: (message?.records.first!.payload)!, encoding:.utf8) {
                            session.invalidate()
                            print(dataMessage)
                        }
                    }
                })
            })
        }

    }

    func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
        print("Tag Error: \(error.localizedDescription)")
    }

    func tagReaderSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
        print("Tag Error: \(error.localizedDescription)")
//         DispatchQueue.main.async {
//             session.invalidate()
//             print(error.localizedDescription)
//             flutterResult(error.localizedDescription)
//         }
    }
}

After pressing the button in the app, NFC reading window also shows up. And with the card i can get the payload Message: My message with spaces

Both approaches start fine and open the iOS's window with "read a tag", but with NFCTagReaderSession nothing is happening. It seems like there is no card. With NFCNDEFReaderSession implementation, I can read the message "My text with spaces" but, of course, I can't read the tag's UID

Am'I doing something wrong to get the UID of the card?

Himu
  • 1
  • 2

0 Answers0