Hi folks,
I have trouble with reading NFC tag in background while my application is running.
I still receives a message in my iPhone 13, NFC tag of web Open "donator.cz" in application Safari.
But I would like to open the app Donator which is here: https://apps.apple.com/dk/app/don%C3%A1tor/id6473955033
My NFC chip scanned by "NFC Tools" is ISO 14443-3A (NXP-NTAG213) In the tag is mentioned https://donator.cz/%3C8digits-number%3E*%3Ccode%3E*text
In my Info.plist of application is:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https://donator.cz</string>
</array>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array>
<string>12FC</string>
</array>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>D2760000850101</string>
</array>
Apple CDN looks like: https://app-site-association.cdn-apple.com/a/v1/donator.cz
I have read in Apple documentation https://developer.apple.com/documentation/corenfc/adding-support-for-background-tag-reading that application should be in progress A Core NFC reader session is in progress.
How to do it in AppDelegate or SceneDelegate.
One note is that everything works properly in case of reading NFC based on button click is pressed.
My NFCHandler looks like:
//
// NFCReader.swift
// Donator
//
// Created by Petr Hracek on 22.11.2024.
//
import Foundation
import UIKit
import CoreNFC
class NFCHandler: NSObject, NFCNDEFReaderSessionDelegate {
var readerSession: NFCNDEFReaderSession?
func startBackgroundScanning() {
guard NFCNDEFReaderSession.readingAvailable else {
return
}
readerSession = NFCNDEFReaderSession(delegate: self, queue: DispatchQueue.main, invalidateAfterFirstRead: true)
readerSession?.alertMessage = "Prilozte NFC tag"
readerSession?.begin()
}
func readTag(session: NFCNDEFReaderSession , tags: [NFCNDEFTag] ) {
if tags.count > 1 {
// Restart polling in 500ms
let retryInterval = DispatchTimeInterval.milliseconds(500)
session.alertMessage = "More than 1 tag is detected, please remove all tags and try again."
DispatchQueue.global().asyncAfter(deadline: .now() + retryInterval, execute: {
session.restartPolling()
})
return
}
// Connect to the found tag and perform NDEF message reading
let tag = tags.first!
session.connect(to: tag, completionHandler: { (error: Error?) in
if nil != error {
session.alertMessage = "Unable to connect to tag."
session.invalidate()
return
}
tag.queryNDEFStatus(completionHandler: { (ndefStatus: NFCNDEFStatus, capacity: Int, error: Error?) in
if .notSupported == ndefStatus {
session.alertMessage = "Tag is not NDEF compliant"
session.invalidate()
return
} else if nil != error {
session.alertMessage = "Unable to query NDEF status of tag"
session.invalidate()
return
}
tag.readNDEF(completionHandler: { (message: NFCNDEFMessage?, error: Error?) in
var statusMessage: String
if nil != error || nil == message {
statusMessage = "Fail to read NDEF from tag"
} else {
statusMessage = "Found 1 NDEF message"
DispatchQueue.main.async {
// Process detected NFCNDEFMessage objects.
debugPrint(message!)
//self.tableView.reloadData()
}
}
session.alertMessage = statusMessage
session.invalidate()
})
})
})
}
/// - Tag: sessionBecomeActive
/// This method will called when NFC session become active
/// Tells the delegate that the session detected NFC tags with NDEF messages.
func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
debugPrint("NFC session become active======")
}
func readerSessionDidInvalidate(_ session: NFCNDEFReaderSession) {
debugPrint("NFC session invalidate======")
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
print(error)
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
for message in messages {
for record in message.records {
print("Type name format: \(record.typeNameFormat)")
print("Payload: \(record.payload)")
print("Type: \(record.type)")
print("Identifier: \(record.identifier)")
}
}
}
/// - Tag: processingNDEFTag
/// if This method is not implement then only func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) will call
/// Tells the delegate that the session detected NFC tags with NDEF messages and enables read-write capability for the session.
func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) {
self.readTag(session: session, tags: tags)
}
}