In diesem Dokument werden erweiterte NFC-Themen wie das Arbeiten mit verschiedenen Tag-Technologien, das Schreiben in NFC-Tags und die Weiterleitung im Vordergrund beschrieben, die es einer Anwendung im Vordergrund ermöglicht, Intents auch dann zu verarbeiten, wenn andere Anwendungen nach denselben filtern.
Mit unterstützten Tag-Technologien arbeiten
Bei der Arbeit mit NFC-Tags und Android-Geräten ist NDEF zum Lesen und Schreiben von Daten in Tags das Hauptformat. Wenn ein Gerät ein Tag mit NDEF-Daten scannt, unterstützt Android das Parsen der Nachricht und die Übermittlung der Nachricht in einem NdefMessage
, sofern dies möglich ist. Es kann jedoch vorkommen, dass Sie ein Tag scannen, das keine NDEF-Daten enthält, oder wenn die NDEF-Daten keinem MIME-Typ oder -URI zugeordnet werden konnten.
In diesen Fällen müssen Sie die Kommunikation direkt mit dem Tag öffnen und mit Ihrem eigenen Protokoll (in Rohbyte) lesen und schreiben. Android bietet allgemeine Unterstützung für diese Anwendungsfälle mit dem Paket android.nfc.tech
, das in Tabelle 1 beschrieben wird. Sie können die Methode getTechList()
verwenden, um die vom Tag unterstützten Technologien zu ermitteln und das entsprechende TagTechnology
-Objekt mit einer der von android.nfc.tech
bereitgestellten Klassen zu erstellen.
Klasse | Beschreibung |
---|---|
TagTechnology |
Die Schnittstelle, die alle Tag-Technologieklassen implementieren müssen. |
NfcA |
Bietet Zugriff auf NFC-A-Eigenschaften (ISO 14443-3A) und auf E/A-Vorgänge. |
NfcB |
Ermöglicht Zugriff auf NFC-B-Eigenschaften (ISO 14443-3B) und auf E/A-Vorgänge. |
NfcF |
Bietet Zugriff auf NFC-F-Eigenschaften (JIS 6319-4) und E/A-Vorgänge. |
NfcV |
Bietet Zugriff auf NFC-V-Eigenschaften (ISO 15693) und E/A-Vorgänge. |
IsoDep |
Bietet Zugriff auf die Eigenschaften ISO-DEP (ISO 14443-4) und E/A-Vorgänge. |
Ndef |
Bietet Zugriff auf NDEF-Daten und Vorgänge für NFC-Tags, die als NDEF formatiert wurden. |
NdefFormatable |
Stellt Formatvorgänge für Tags bereit, die möglicherweise NDEF-formatierbar sind. |
Die folgenden Tag-Technologien müssen von Android-Mobilgeräten nicht unterstützt werden.
Klasse | Beschreibung |
---|---|
MifareClassic |
Bietet Zugriff auf MIFARE Classic-Attribute und E/A-Vorgänge, wenn dieses Android-Gerät MIFARE unterstützt. |
MifareUltralight |
Bietet Zugriff auf MIFARE Ultralight-Eigenschaften und E/A-Vorgänge, sofern dieses Android-Gerät MIFARE unterstützt. |
Mit Tag-Technologien und dem Intent ACTION_TECH_DISCOVERED arbeiten
Wenn ein Gerät ein Tag mit NDEF-Daten scannt, das aber keinem MIME oder URI zugeordnet werden konnte, versucht das System zur Tag-Weiterleitung, eine Aktivität mit dem Intent ACTION_TECH_DISCOVERED
zu starten. Der ACTION_TECH_DISCOVERED
wird auch verwendet, wenn ein Tag mit Nicht-NDEF-Daten gescannt wird. Mit diesem Fallback können Sie direkt mit den Daten im Tag arbeiten, wenn das Tag-Weiterleitungssystem diese nicht für Sie parsen konnte. Wenn Sie mit Tag-Technologien arbeiten, sind folgende grundlegende Schritte erforderlich:
- Filtern Sie nach einem
ACTION_TECH_DISCOVERED
-Intent, der die Tag-Technologien angibt, die Sie verarbeiten möchten. Weitere Informationen finden Sie unter Nach NFC-Intents filtern. Im Allgemeinen versucht das System zur Tag-Weiterleitung, einenACTION_TECH_DISCOVERED
-Intent zu starten, wenn eine NDEF-Nachricht keinem MIME-Typ oder URI zugeordnet werden kann oder das gescannte Tag keine NDEF-Daten enthält. Weitere Informationen dazu, wie dies bestimmt wird, finden Sie unter Tag Dispatch-System. - Wenn die Anwendung den Intent empfängt, rufen Sie das Objekt
Tag
vom Intent ab:Kotlin
var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- Rufen Sie eine Instanz eines
TagTechnology
ab, indem Sie eine derget
-Factory-Methoden der Klassen imandroid.nfc.tech
-Paket aufrufen. Sie können die unterstützten Technologien des Tags auflisten, indem SiegetTechList()
aufrufen, bevor Sie eineget
-Factory-Methode aufrufen. So rufen Sie beispielsweise eine Instanz vonMifareUltralight
aus einemTag
ab:Kotlin
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
Java
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
In Tags lesen und schreiben
Zum Lesen und Schreiben in ein NFC-Tag wird das Tag vom Intent abgerufen und die Kommunikation mit dem Tag gestartet. Sie müssen einen eigenen Protokollstack definieren, um Daten in das Tag zu lesen und in das Tag zu schreiben. Beachten Sie jedoch, dass Sie NDEF-Daten weiterhin lesen und schreiben können, wenn Sie direkt mit einem Tag arbeiten. Es liegt an Ihnen, wie Sie die Dinge strukturieren möchten. Das folgende Beispiel zeigt, wie Sie mit einem MIFARE-Ultralight-Tag arbeiten.
Kotlin
package com.example.android.nfc import android.nfc.Tag import android.nfc.tech.MifareUltralight import java.io.IOException import java.nio.charset.Charset class MifareUltralightTagTester { fun writeTag(tag: Tag, tagText: String) { MifareUltralight.get(tag)?.use { ultralight -> ultralight.connect() Charset.forName("US-ASCII").also { usAscii -> ultralight.writePage(4, "abcd".toByteArray(usAscii)) ultralight.writePage(5, "efgh".toByteArray(usAscii)) ultralight.writePage(6, "ijkl".toByteArray(usAscii)) ultralight.writePage(7, "mnop".toByteArray(usAscii)) } } } fun readTag(tag: Tag): String? { return MifareUltralight.get(tag)?.use { mifare -> mifare.connect() val payload = mifare.readPages(4) String(payload, Charset.forName("US-ASCII")) } } }
Java
package com.example.android.nfc; import android.nfc.Tag; import android.nfc.tech.MifareUltralight; import android.util.Log; import java.io.IOException; import java.nio.charset.Charset; public class MifareUltralightTagTester { private static final String TAG = MifareUltralightTagTester.class.getSimpleName(); public void writeTag(Tag tag, String tagText) { MifareUltralight ultralight = MifareUltralight.get(tag); try { ultralight.connect(); ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII"))); } catch (IOException e) { Log.e(TAG, "IOException while writing MifareUltralight...", e); } finally { try { ultralight.close(); } catch (IOException e) { Log.e(TAG, "IOException while closing MifareUltralight...", e); } } } public String readTag(Tag tag) { MifareUltralight mifare = MifareUltralight.get(tag); try { mifare.connect(); byte[] payload = mifare.readPages(4); return new String(payload, Charset.forName("US-ASCII")); } catch (IOException e) { Log.e(TAG, "IOException while reading MifareUltralight message...", e); } finally { if (mifare != null) { try { mifare.close(); } catch (IOException e) { Log.e(TAG, "Error closing tag...", e); } } } return null; } }
Weiterleitungssystem im Vordergrund verwenden
Das Weiterleitungssystem im Vordergrund ermöglicht es einer Aktivität, einen Intent abzufangen und Priorität gegenüber anderen Aktivitäten zu beanspruchen, die denselben Intent verarbeiten. Für die Verwendung dieses Systems müssen einige Datenstrukturen konstruiert werden, damit das Android-System die entsprechenden Intents an Ihre Anwendung senden kann. So aktivieren Sie das Weiterleitungssystem im Vordergrund:
- Fügen Sie der Methode
onCreate()
Ihrer Aktivität den folgenden Code hinzu:- Erstellen Sie ein änderbares
PendingIntent
-Objekt, damit das Android-System die Details des Tags beim Scannen in dieses Objekt übernehmen kann.Kotlin
val intent = Intent(this, javaClass).apply { addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) } var pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)
Java
PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE);
- Deklarieren Sie Intent-Filter für die Verarbeitung der Intents, die Sie abfangen möchten. Das Weiterleitungssystem im Vordergrund prüft die angegebenen Intent-Filter mit dem Intent, der empfangen wird, wenn das Gerät ein Tag scannt. Bei Übereinstimmung verarbeitet die Anwendung den Intent. Wenn sie nicht übereinstimmt, greift das Weiterleitungssystem im Vordergrund auf das Intent-Weiterleitungssystem zurück.
Wenn Sie ein
null
-Array von Intent- und Technologiefiltern angeben, wird damit festgelegt, dass nach allen Tags gefiltert werden soll, die auf denTAG_DISCOVERED
-Intent zurückgreifen. Mit dem folgenden Code-Snippet werden alle MIME-Typen fürNDEF_DISCOVERED
verarbeitet. Sie sollten nur solche verarbeiten, die Sie benötigen.Kotlin
val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply { try { addDataType("*/*") /* Handles all MIME based dispatches. You should specify only the ones that you need. */ } catch (e: IntentFilter.MalformedMimeTypeException) { throw RuntimeException("fail", e) } } intentFiltersArray = arrayOf(ndef)
Java
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndef.addDataType("*/*"); /* Handles all MIME based dispatches. You should specify only the ones that you need. */ } catch (MalformedMimeTypeException e) { throw new RuntimeException("fail", e); } intentFiltersArray = new IntentFilter[] {ndef, };
- Richten Sie eine Reihe von Tag-Technologien ein, die von Ihrer Anwendung verarbeitet werden sollen. Rufen Sie die Methode
Object.class.getName()
auf, um die Klasse der Technologie zu ermitteln, die unterstützt werden soll.Kotlin
techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
Java
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
- Erstellen Sie ein änderbares
- Überschreiben Sie die folgenden Callbacks für den Aktivitätslebenszyklus und fügen Sie Logik hinzu, um die Weiterleitung im Vordergrund zu aktivieren und zu deaktivieren, wenn die Aktivität den Fokus verliert (
onPause()
) und wiedererlangt (onResume()
).enableForegroundDispatch()
muss aus dem Hauptthread aufgerufen werden, und nur, wenn die Aktivität im Vordergrund ausgeführt wird (der Aufruf inonResume()
garantiert dies). Außerdem musst du denonNewIntent
-Callback implementieren, um die Daten aus dem gescannten NFC-Tag zu verarbeiten.
Kotlin
public override fun onPause() { super.onPause() adapter.disableForegroundDispatch(this) } public override fun onResume() { super.onResume() adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray) } public override fun onNewIntent(intent: Intent) { val tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG) // do something with tagFromIntent }
Java
public void onPause() { super.onPause(); adapter.disableForegroundDispatch(this); } public void onResume() { super.onResume(); adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray); } public void onNewIntent(Intent intent) { Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // do something with tagFromIntent }