You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat: unify NDEF discovery control and fix iOS session cleanup - #239
iOS poll() always waits for queryNDEFStatus before returning, including for apps that only exchange raw commands. In an instrumented downstream build with a CanoKey Canary, this query added about 220 ms after detection; skipping it reduced the same settings read from about 1.28 s to 1.06 s. These are small-sample latency measurements, not success-rate measurements.
Add a shared checkNDEF option (default true) to control automatic NDEF discovery on both Android and iOS:
final tag =awaitFlutterNfcKit.poll(checkNDEF:false);
On Android, this sets the existing FLAG_READER_SKIP_NDEF_CHECK; platform NDEF methods are unavailable for that session. On iOS, it skips queryNDEFStatus and leaves NDEF capability metadata at its defaults, while preserving raw commands and FeliCa PMm collection. Explicit iOS NDEF methods still contact the tag. Web ignores the option.
Retain androidCheckNDEF with @Deprecated for source compatibility. When explicitly supplied, it overrides checkNDEF on Android only; legacy Android-only calls keep their previous behavior. New callers need only checkNDEF. Document these semantics and precedence in the README and API docs.
Also fix reader lifecycle gaps exposed during repeated scans: invalidation currently skips cleanup once a successful poll has consumed its result, and failed connections leave the reader active. Clean up both cases, serialize discovery/setup state on main, and guard delayed discovery, connection, NDEF and FeliCa callbacks against replaced sessions. This retains the stale-invalidation protection introduced in #235.
Validation:
flutter test: 5 tests covering defaults, shared opt-out, legacy Android-only behavior, override precedence in both directions, and raw commands after polling. Added tests to the existing stable/beta CI workflow.
dart analyze, Dart format checks and git diff --check: passed.
cd example && flutter build ios --debug --no-codesign: passed.
The latency measurements and scan/recovery trials used the instrumented downstream prototype. This upstream extraction has been compiled, but has not had a separate on-device test; Android validation here covers channel flags, not physical NFC hardware.
Summary by CodeRabbit
New Features
Added the checkNDEF option to control automatic NDEF discovery on Android and iOS. It defaults to enabled; when disabled, polling skips the initial NDEF check while raw transceive remains available. The deprecated androidCheckNDEF option remains as an Android-only override.
Bug Fixes
Improved iOS NFC session cleanup and handling of invalidated sessions, failed connections, and delayed callbacks.
Documentation
Clarified NDEF discovery behavior and its effects on metadata and NFC operations.
Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 0 remain after this review.
📝 Walkthrough
The poll API adds checkNDEF, enabled by default, and keeps androidCheckNDEF as a deprecated Android-only override. The iOS plugin applies the option during tag polling and updates reader-session lifecycle and callback handling. Documentation and tests cover the API and polling behavior.
Changes: NDEF Polling
Layer / File(s)
Summary
Expose and validate the NDEF-discovery option lib/flutter_nfc_kit.dart, README.md, test/poll_test.dart, .github/workflows/test.yml, CHANGELOG.md
poll accepts and forwards checkNDEF, which defaults to true. The nullable deprecated androidCheckNDEF overrides it on Android. Documentation describes platform behavior, tests cover option precedence and polling calls, and the workflow runs flutter test.
The plugin creates reader sessions on the main queue. It clears pending results and reader state during finish, invalidation, and poll failure, and checks session identity before processing callbacks or retrying tag detection.
Handle iOS tag polling results ios/flutter_nfc_kit/Sources/flutter_nfc_kit/FlutterNfcKitPlugin.swift
The plugin conditionally queries NDEF status, preserves FeliCa manufacturer metadata retrieval when NDEF discovery is skipped, and returns poll metadata or errors through guarded completion paths.
sequenceDiagram
participant FlutterNfcKit
participant iOSPlugin
participant ReaderSession
participant NFCTag
FlutterNfcKit->>iOSPlugin: poll with checkNDEF
iOSPlugin->>ReaderSession: create and begin session
ReaderSession->>iOSPlugin: detect tag and complete connection
iOSPlugin->>NFCTag: query NDEF status when enabled and supported
NFCTag->>iOSPlugin: return NDEF metadata
iOSPlugin->>NFCTag: retrieve FeliCa manufacturer metadata
NFCTag->>iOSPlugin: return FeliCa metadata
iOSPlugin->>FlutterNfcKit: deliver poll result or error
Loading
Merge Risk:⚪ Minimal · up to c0b51
The option’s documented iOS NDEF behavior remains supported by the inspected code. No identified issue prevents merging after normal checks.
Pre-merge checks: 4 · 1
Failed checks: 1 warning
Check name
Status
Explanation
Resolution
Docstring Coverage
Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 1 files. (4 skipped: 4…
Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed checks: 4 passed
Check name
Status
Explanation
Description Check
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
The title clearly summarizes the two main changes: unified NDEF discovery control and iOS session cleanup fixes.
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage
Explanation
Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 1 files. (4 skipped: 4 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
Commit to this branch
Create a new PR
🧪 Generate unit tests (beta)
Commit to this branch
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
dangfan
changed the title
feat(ios): add optional NDEF discovery and fix session cleanup
feat: unify NDEF discovery control and fix iOS session cleanup
Oct 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
iOS
poll()always waits forqueryNDEFStatusbefore returning, including for apps that only exchange raw commands. In an instrumented downstream build with a CanoKey Canary, this query added about 220 ms after detection; skipping it reduced the same settings read from about 1.28 s to 1.06 s. These are small-sample latency measurements, not success-rate measurements.Add a shared
checkNDEFoption (defaulttrue) to control automatic NDEF discovery on both Android and iOS:On Android, this sets the existing
FLAG_READER_SKIP_NDEF_CHECK; platform NDEF methods are unavailable for that session. On iOS, it skipsqueryNDEFStatusand leaves NDEF capability metadata at its defaults, while preserving raw commands and FeliCa PMm collection. Explicit iOS NDEF methods still contact the tag. Web ignores the option.Retain
androidCheckNDEFwith@Deprecatedfor source compatibility. When explicitly supplied, it overridescheckNDEFon Android only; legacy Android-only calls keep their previous behavior. New callers need onlycheckNDEF. Document these semantics and precedence in the README and API docs.Also fix reader lifecycle gaps exposed during repeated scans: invalidation currently skips cleanup once a successful poll has consumed its result, and failed connections leave the reader active. Clean up both cases, serialize discovery/setup state on main, and guard delayed discovery, connection, NDEF and FeliCa callbacks against replaced sessions. This retains the stale-invalidation protection introduced in #235.
Validation:
flutter test: 5 tests covering defaults, shared opt-out, legacy Android-only behavior, override precedence in both directions, and raw commands after polling. Added tests to the existing stable/beta CI workflow.dart analyze, Dart format checks andgit diff --check: passed.cd example && flutter build ios --debug --no-codesign: passed.Summary by CodeRabbit
checkNDEFoption to control automatic NDEF discovery on Android and iOS. It defaults to enabled; when disabled, polling skips the initial NDEF check while raw transceive remains available. The deprecatedandroidCheckNDEFoption remains as an Android-only override.