NFCTagReaderSession queues behind the first. So the interesting question is not how
to open one — it is how to be certain it closed.
A leaked session keeps the iOS scanning sheet up and holds Android’s NFC controller.
Neither symptom appears where the leak is. Both appear two screens later, as NFC
having “randomly stopped working”.
Three ways in
withTag
One tag, scoped. Reach for this.
openSession
Several tags, your own UI.
onTag
Continuous. Kiosks and doors.
withTag — one tag, and the session closes itself
openSession — several tags, with your own UI between them
await using closes the session when the block ends, however it ends. Without
explicit resource management in your toolchain, a finally does the same job:
onTag — continuous, for a kiosk or a door
onTag returns a Subscription, not a promise, so a failure has nothing to reject
into — that is what onError is for. Leaving it out makes a stream that dies
silently.
In a component, use useNfcTagStream: it ties the
stream’s lifetime to the mount and to screen focus, which is the part that is easy
to get wrong.
Options, in full
Every entry point takes the sameScanOptions.
TagTech[]
required
Which technologies you are willing to accept. A tag carrying none of them is never surfaced. On
iOS this also decides the reader session’s polling options.
number
Your own deadline. Rejects with
timeout — which is deliberately not sessionTimeout, iOS’s
own 60-second cap that no library can extend.AbortSignal
Rejects with
aborted when the signal fires. Aborting before the call reaches the radio does not
touch the radio at all.IosScanOptions
AndroidScanOptions
SessionConfig
Cancelling and timing out
Two deadlines exist and they are not the same thing, which is why they have different codes:aborted is not userCancelled. The first is your signal; the second is the user dismissing the
sheet. Collapsing the two — which the library this one replaces did — makes it impossible for an
app to decide whether to show a message.Availability, before you offer the feature
nfc.capabilities also reports what the platform can do beyond tags: hce,
observeMode, pollingFrames, vas, backgroundReading, and tagLost, which
says whether tag removal is delivered by the platform or polled for.
Tags that arrive without a session
A tag tapped while your app is closed or backgrounded does not come through reader mode at all — it arrives as an Android intent, and it needs manifest configuration you have to opt into.withTag does.
The full picture, including the Android 17 permission that decides whether the tag
arrives at all, is in Background tag reading.
Next
Tags
What you can do with the thing a session hands you.
Error reference
Every code a session can reject with.