Wie deaktiviere ich automatische NFC-Scans auf Samsung-Mobilgeräten mit Flutter?Android

Forum für diejenigen, die für Android programmieren
Anonymous
 Wie deaktiviere ich automatische NFC-Scans auf Samsung-Mobilgeräten mit Flutter?

Post by Anonymous »

Ich baue eine Flutter-App, die NDEF nur dann lesen/schreiben soll, wenn der Benutzer auf eine Schaltfläche tippt. Auf Samsung (auch SM-S918B, Galaxy S23 Ultra und Galaxy Note10+) „ergreift“ die Systemverwaltung von Samsung manchmal immer noch das Tag (automatisches Lesen / automatische Benutzeroberflächen- / URL-Verwaltung), selbst wenn meine App im Vordergrund steht. Ich möchte die NFC-Kontrolle in meiner App vollständig behalten, damit das System nichts automatisch verarbeitet. Dies muss möglich sein, da z.B. Die App „NFC Tools“ übernimmt dies. Die App verliert nie den Fokus und der „automatische Tag-Reader“ erscheint nicht.
Stack:
  • Flutter
  • Pakete: nfc_manager, nfc_manager_ndef, ndef_record
  • Geräte: Samsung SM-S918B (One UI/Android 14) oder Samsung Galaxy
    Note10+
Was ich versucht habe (und es funktioniert immer noch nicht)
  • Native ReaderMode (Kotlin) mit „Sticky“-Aktivierung
Ich aktiviere den Android ReaderMode auf der Aktivitätsebene und lasse ihn aktiviert, während die App sichtbar ist:

Code: Select all

class MainActivity : FlutterActivity() {
private val CHANNEL = "de.mytagapp.app/nfc"
private var nfcAdapter: NfcAdapter? = null
private var readerModeSticky = false

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
nfcAdapter = NfcAdapter.getDefaultAdapter(this)
}

override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"enableReaderMode" -> {
readerModeSticky = true
enableReaderModeInternal()
result.success(true)
}
"disableReaderMode" -> {
readerModeSticky = false
disableReaderModeInternal()
result.success(true)
}
else -> result.notImplemented()
}
}
}

override fun onResume() {
super.onResume()
if (readerModeSticky) enableReaderModeInternal()
}

override fun onPause() {
super.onPause()
// disable when not visible
disableReaderModeInternal()
}

private fun enableReaderModeInternal() {
val flags =
NfcAdapter.FLAG_READER_NFC_A or
// NfcAdapter.FLAG_READER_NFC_V  // (tested on/off)
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS or
NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK

// No-op callback; Flutter handles reads/writes.
nfcAdapter?.enableReaderMode(this, { /* no-op */ }, flags, null)
}

private fun disableReaderModeInternal() {
nfcAdapter?.disableReaderMode(this)
}
}
Ich füge dem Manifest keine NFC-Absichtsfilter/Tech-Filter hinzu (um die Weiterleitung von Absichten an das System oder andere Apps zu vermeiden).
Aktivität hat launchMode="singleTop".
  • Globaler „Schutz“ auf der Flutter-Seite
Ich schließe die gesamte App in ein Widget ein, das den ReaderMode bei der Initialisierung aktiviert und ihn bei jeder Fortsetzung wieder aktiviert:

Code: Select all

class NfcReaderGuard extends StatefulWidget {
final Widget child;
const NfcReaderGuard({super.key, required this.child});
@override
State createState() => _NfcReaderGuardState();
}

class _NfcReaderGuardState extends State with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
NfcReaderMode.enable(); // MethodChannel -> enableReaderMode
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) NfcReaderMode.enable();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
NfcReaderMode.disable();
super.dispose();
}
@override
Widget build(BuildContext context) => widget.child;
}
  • Nur vom Benutzer ausgelöste Sitzungen
  • Ich rufe NfcManager.instance.startSession(...) nur auf, nachdem der Benutzer auf
    eine Schaltfläche (Lesen/Schreiben) tippt, und stoppe es direkt danach.
  • Ich überprüfe zuerst die Verfügbarkeit.
  • Datensätze sind RTD_TEXT; Keine URL-Einträge, die das System dazu einladen würden,
    einen Browser zu öffnen.
Das Problem:
Trotz alledem verarbeitet das System auf dem Samsung-Gerät das Tag manchmal immer noch automatisch (als ob mein ReaderMode es nicht „besitzen“ würde). Selbst das Fokussieren der App (Tippen auf die Benutzeroberfläche) verhindert nicht immer, dass der automatische Lese-/Handler angezeigt wird. Ich sehe das am häufigsten, wenn die App den Fokus wiedererlangt oder nach einem kurzen Aus-/Ein-Zyklus des Bildschirms.
Fragen an die Samsung-/NFC-/Android-/Flutter-Experten:
  • Überschreibt Samsung das ReaderMode-Verhalten? Auf AOSP-Geräten würde ich
    enableReaderMode(...) mit SKIP_NDEF_CHECK erwarten, um
    die NDEF-Prüfung/automatische Benutzeroberfläche der Plattform zu stoppen. Gibt es Samsung-spezifische Macken
    wo das System immer noch an seinen eigenen Handler sendet?
  • Schieße ich mir selbst ins Bein, indem ich enableReaderMode(...)
    und nfc_manager.startSession(...) kombiniere? Könnte nfc_manager intern
    seinen eigenen Reader/Vordergrund-Versand umschalten und versehentlich
    Systemstandards auf Samsung wieder aktivieren?
  • Würden Sie empfehlen, nfc_manager.startSession überhaupt nicht zu verwenden und
    stattdessen alle Tag-Erkennung im nativen onTagDiscovered durchzuführen und dann
    Bytes über MethodChannel an Flutter weiterzuleiten?
  • Wäre „enableForegroundDispatch(...)“ auf Samsung zuverlässiger als
    ReaderMode hier? Wenn ja, gibt es eine minimale Einrichtung, die Absichten in meiner
    Aktivität aufrechterhält und zuverlässig verhindert, dass Samsung Wallet/Tag-Apps
    übernehmen – ohne dass Benutzer die Geräteeinstellungen ändern müssen?
  • Irgendwelche Samsung-spezifischen Flags oder Best Practices, die mir fehlen?
    - Zusätzliche Reader-Flags?

    - Timing-Bedenken (z. B. Wiederaktivierung zu einem späteren Zeitpunkt). Lifecycle-Callback)?
    - Bekannte One UI-Verhaltensweisen, die einen anderen Ansatz erfordern?
  • Andere Problemumgehungen, die Sie in der Produktion verwendet haben? Meine Einschränkungen:
    - Ich muss System-Popups/automatisches Öffnen vermeiden.
    - Lese-/Schreibvorgänge sollten nur bei expliziter Benutzeraktion erfolgen.
    - Ich würde Benutzer lieber nicht bitten, Samsung Wallet/„Tag“-Dienste
    in den Einstellungen zu deaktivieren, da dies das Tag-Lesen generell deaktivieren würde (wie
    meine Tests zeigen)
Mögliche nächste Schritte, die ich in Betracht ziehe (Feedback willkommen)
  • Für die Entdeckung vollständig nativ gehen: onTagDiscovered in Kotlin verarbeiten, NDEF dort analysieren (oder einfach rohe Technologie/Bytes übergeben) an Flutter; Rufen Sie
    nfc_manager.startSession überhaupt nicht auf.
  • Versuchen Sie Foreground Dispatch anstelle von ReaderMode und stellen Sie sicher, dass keine Filter
    URL-Verarbeitung zulassen.
  • Drosseln Sie das Timing für onResume() erneut (z. B. eine kleine Verzögerung veröffentlichen), falls Samsung während des Lebenslaufs etwas unternimmt.
  • Überprüfen Sie die zum Testen verwendeten Tags noch einmal (stellen Sie sicher, dass sie keine
    URLs/Datensätze enthalten, mit denen Samsung aggressiv umgeht; meine sind nur RTD_TEXT
    , aber ich teste noch einmal mit empty/FORMAT).
Wenn jemand ein bekanntermaßen gutes Rezept für Samsung (One UI) hat, um NFC strikt in der App zu belassen – entweder mit ReaderMode oder Foreground Dispatch – ich würde mich wirklich über konkrete Hinweise oder Codeausschnitte freuen. Danke!

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post