NFC – Grundlagen

In diesem Dokument werden die grundlegenden NFC-Aufgaben beschrieben, die Sie unter Android ausführen. Es wird erläutert, wie NFC-Daten in Form von NDEF-Nachrichten gesendet und empfangen werden, und es werden die Android-Framework-APIs beschrieben, die diese Funktionen unterstützen. Weitere Informationen zu fortgeschrittenen Themen, einschließlich einer Diskussion zur Arbeit mit nicht NDEF-Daten, finden Sie unter NFC für Fortgeschrittene.

Das Lesen von NDEF-Daten von einem NFC-Tag wird vom Tag-Dispatch-System verarbeitet. Dieses analysiert erkannte NFC-Tags, kategorisiert die Daten entsprechend und startet eine Anwendung, die an den kategorisierten Daten interessiert ist. Eine Anwendung, die das gescannte NFC-Tag verarbeiten möchte, kann einen Intent-Filter deklarieren und die Verarbeitung der Daten anfordern.

Das Tag-Dispatch-System

Android-Geräte suchen normalerweise nach NFC-Tags, wenn der Bildschirm entsperrt ist, es sei denn, NFC ist in den Einstellungen des Geräts deaktiviert. Wenn ein Android-Gerät ein NFC-Tag erkennt, soll der Intent von der am besten geeigneten Aktivität verarbeitet werden, ohne dass der Nutzer gefragt wird, welche App er verwenden möchte. Da Geräte NFC-Tags nur in sehr kurzer Entfernung scannen, müssen Nutzer bei manueller Auswahl einer Aktivität wahrscheinlich das Gerät vom Tag weg bewegen und die Verbindung trennen. Sie sollten Ihre Aktivität so entwickeln, dass nur die NFC-Tags verarbeitet werden, die für Ihre Aktivität relevant sind, um zu verhindern, dass die Aktivitätsauswahl angezeigt wird.

Android bietet ein spezielles Tag-Dispatch-System, das gescannte NFC-Tags analysiert, sie parst und versucht, Apps zu finden, die an den gescannten Daten interessiert sind. Dazu gehören:

  1. Das NFC-Tag wird geparst und der MIME-Typ oder ein URI ermittelt, der die Datennutzlast im Tag identifiziert.
  2. Der MIME-Typ oder URI und die Nutzlast werden in einen Intent gekapselt. Diese ersten beiden Schritte werden unter NFC-Tags MIME-Typen und URIs zuordnen beschrieben.
  3. Startet eine Aktivität basierend auf dem Intent. Weitere Informationen finden Sie unter So werden NFC-Tags an Anwendungen gesendet.

Zuordnung von NFC-Tags zu MIME-Typen und URIs

Bevor Sie mit dem Schreiben Ihrer NFC-Anwendungen beginnen, sollten Sie sich mit den verschiedenen Arten von NFC-Tags, der Verarbeitung von NFC-Tags durch das Tag-Dispatch-System und den speziellen Aufgaben des Tag-Dispatch-Systems vertraut machen, wenn eine NDEF-Nachricht erkannt wird. NFC-Tags gibt es in vielen verschiedenen Technologien und Daten können auf viele verschiedene Arten darauf geschrieben werden. Android bietet die beste Unterstützung für den NDEF-Standard, der vom NFC Forum definiert wird.

NDEF-Daten sind in einer Nachricht (NdefMessage) gekapselt, die einen oder mehrere Einträge (NdefRecord) enthält. Jeder NDEF-Eintrag muss gemäß der Spezifikation des zu erstellenden Eintragstyps korrekt formatiert sein. Android unterstützt auch andere Arten von Tags, die keine NDEF-Daten enthalten. Sie können mit diesen Tags arbeiten, indem Sie die Klassen im Paket android.nfc.tech verwenden. Weitere Informationen zu diesen Technologien finden Sie im Hilfeartikel NFC-Funktionen. Wenn Sie mit diesen anderen Arten von Tags arbeiten, müssen Sie einen eigenen Protokollstack schreiben, um mit den Tags zu kommunizieren. Wir empfehlen daher, nach Möglichkeit NDEF zu verwenden, um die Entwicklung zu vereinfachen und die maximale Unterstützung für Android-Geräte zu erhalten.

Hinweis:Komplette NDEF-Spezifikationen können Sie auf der Website NFC Forum Specifications & Application Documents herunterladen. Unter Creating common types of NDEF records (Gängige NDEF-Eintragstypen erstellen) finden Sie Beispiele zum Erstellen von NDEF-Einträgen.

Nachdem Sie nun etwas über NFC-Tags erfahren haben, wird in den folgenden Abschnitten genauer beschrieben, wie Android mit NDEF-formatierten Tags umgeht. Wenn ein Android-Gerät ein NFC-Tag mit NDEF-formatierten Daten scannt, wird die Nachricht geparst und versucht, den MIME-Typ oder die URI der Daten zu ermitteln. Dazu liest das System die erste NdefRecord in der NdefMessage, um zu bestimmen, wie die gesamte NDEF-Nachricht zu interpretieren ist. Eine NDEF-Nachricht kann mehrere NDEF-Einträge enthalten. In einer korrekt formatierten NDEF-Nachricht enthält die erste NdefRecord die folgenden Felder:

3‑Bit-TNF (Type Name Format)
Gibt an, wie das Feld vom Typ „Variable Length“ zu interpretieren ist. Gültige Werte sind in Tabelle 1 beschrieben.
Typ mit variabler Länge
Beschreibt den Typ des Eintrags. Wenn Sie TNF_WELL_KNOWN verwenden, geben Sie in diesem Feld die Datensatztypdefinition (Record Type Definition, RTD) an. Gültige RTD-Werte sind in Tabelle 2 beschrieben.
ID mit variabler Länge
Eine eindeutige Kennung für den Eintrag. Dieses Feld wird nicht oft verwendet. Wenn Sie ein Tag jedoch eindeutig identifizieren möchten, können Sie eine ID dafür erstellen.
Nutzlast mit variabler Länge
Die tatsächliche Datennutzlast, die Sie lesen oder schreiben möchten. Eine NDEF-Nachricht kann mehrere NDEF-Einträge enthalten. Angenommen Sie also nicht, dass sich die vollständige Nutzlast im ersten NDEF-Eintrag der NDEF-Nachricht befindet.

Das Tag-Dispatch-System verwendet die TNF- und Typfelder, um einen MIME-Typ oder URI der NDEF-Nachricht zuzuordnen. Ist der Vorgang erfolgreich, werden diese Informationen zusammen mit der tatsächlichen Nutzlast in einer ACTION_NDEF_DISCOVERED-Intent-Nachricht gekapselt. Es gibt jedoch Fälle, in denen das Tag-Dispatch-System den Datentyp nicht anhand des ersten NDEF-Eintrags bestimmen kann. Das passiert, wenn die NDEF-Daten keinem MIME-Typ oder URI zugeordnet werden können oder wenn das NFC-Tag gar keine NDEF-Daten enthält. In solchen Fällen wird ein Tag-Objekt mit Informationen zu den Technologien des Tags und der Nutzlast stattdessen in einer ACTION_TECH_DISCOVERED-Intention gekapselt.

In Tabelle 1 wird beschrieben, wie das Tag-Dispatch-System TNF- und Typfelder MIME-Typen oder URIs zuordnet. Außerdem wird beschrieben, welche TNFs keinem MIME-Typ oder URI zugeordnet werden können. In diesen Fällen greift das Tag-Dispatch-System auf ACTION_TECH_DISCOVERED zurück.

Wenn das Tag-Dispatch-System beispielsweise einen Datensatz vom Typ TNF_ABSOLUTE_URI findet, wird das Feld „Typ mit variabler Länge“ dieses Datensatzes in einen URI umgewandelt. Das Tag-Dispatch-System kapselt diesen URI zusammen mit anderen Informationen zum Tag, z. B. der Nutzlast, im Datenfeld einer ACTION_NDEF_DISCOVERED-Intention ein. Wenn hingegen ein Eintrag vom Typ TNF_UNKNOWN gefunden wird, wird eine Intent erstellt, die die Technologien des Tags umschließt.

Tabelle 1 Unterstützte TNFs und ihre Zuordnungen

Type Name Format (TNF) Zuordnung
TNF_ABSOLUTE_URI URI basierend auf dem Typfeld.
TNF_EMPTY Fällt auf ACTION_TECH_DISCOVERED zurück.
TNF_EXTERNAL_TYPE URI, der auf der URN im Typfeld basiert. Die URN wird in einer verkürzten Form in das NDEF-Typfeld codiert: <domain_name>:<service_name>. Android ordnet dies einem URI im folgenden Format zu: vnd.android.nfc://ext/<domain_name>:<service_name>.
TNF_MIME_MEDIA MIME-Typ basierend auf dem Typfeld.
TNF_UNCHANGED Im ersten Eintrag ungültig, daher wird ACTION_TECH_DISCOVERED zurückgegeben.
TNF_UNKNOWN Fällt auf ACTION_TECH_DISCOVERED zurück.
TNF_WELL_KNOWN MIME-Typ oder URI, je nach der Definition des Datensatztyps (Record Type Definition, RTD), die Sie im Feld „Typ“ festlegen. Weitere Informationen zu verfügbaren RTDs und ihren Zuordnungen finden Sie in Tabelle 2.

Tabelle 2 Unterstützte RTDs für TNF_WELL_KNOWN und ihre Zuordnungen

Record Type Definition (RTD) Zuordnung
RTD_ALTERNATIVE_CARRIER Fällt auf ACTION_TECH_DISCOVERED zurück.
RTD_HANDOVER_CARRIER Fällt auf ACTION_TECH_DISCOVERED zurück.
RTD_HANDOVER_REQUEST Fällt auf ACTION_TECH_DISCOVERED zurück.
RTD_HANDOVER_SELECT Fällt auf ACTION_TECH_DISCOVERED zurück.
RTD_SMART_POSTER URI, der auf dem Parsen der Nutzlast basiert.
RTD_TEXT MIME-Typ von text/plain.
RTD_URI URI basierend auf der Nutzlast.

Wie NFC-Tags an Apps gesendet werden

Sobald das Tag-Dispatch-System einen Intent erstellt hat, der das NFC-Tag und seine identifizierenden Informationen umschließt, sendet es den Intent an eine interessierte Anwendung, die nach dem Intent filtert. Wenn mehrere Anwendungen den Intent verarbeiten können, wird die Aktivitätsauswahl angezeigt, damit der Nutzer die Aktivität auswählen kann. Das Tag-Dispatch-System definiert drei Intents, die in absteigender Priorität aufgelistet sind:

  1. ACTION_NDEF_DISCOVERED: Mit dieser Intent-Aktion wird eine Aktivität gestartet, wenn ein Tag mit einer NDEF-Nutzlast gescannt wird und einen erkannten Typ hat. Dies ist der Intent mit der höchsten Priorität. Das Tag-Dispatch-System versucht, nach Möglichkeit eine Aktivität mit diesem Intent vor allen anderen Intents zu starten.

    Hinweis:Ab Android 16 wird beim Scannen von NFC-Tags, die URL-Links speichern (d. h. URI-Schema „https://“ oder „http://“), die ACTION_VIEW-Intent anstelle der ACTION_NDEF_DISCOVERED-Intent ausgelöst.

  2. ACTION_TECH_DISCOVERED: Wenn keine Aktivitäten für die Verarbeitung des ACTION_NDEF_DISCOVERED-Intents registriert sind, versucht das Tag-Dispatch-System, eine Anwendung mit diesem Intent zu starten. Dieser Intent wird auch direkt gestartet (ohne zuerst ACTION_NDEF_DISCOVERED zu starten), wenn das gescannte Tag NDEF-Daten enthält, die nicht einem MIME-Typ oder URI zugeordnet werden können, oder wenn das Tag keine NDEF-Daten enthält, aber eine bekannte Tag-Technologie verwendet.
  3. ACTION_TAG_DISCOVERED: Dieser Intent wird gestartet, wenn keine Aktivitäten die Intents ACTION_NDEF_DISCOVERED oder ACTION_TECH_DISCOVERED verarbeiten.

So funktioniert das Tag-Dispatch-System im Wesentlichen:

  1. Versuchen Sie, eine Aktivität mit der Absicht zu starten, die vom Tag-Dispatch-System beim Parsen des NFC-Tags erstellt wurde (entweder ACTION_NDEF_DISCOVERED oder ACTION_TECH_DISCOVERED).
  2. Wenn keine Aktivitäten nach diesem Intent gefiltert werden, versuchen Sie, eine Aktivität mit dem Intent mit der nächstniedrigeren Priorität (ACTION_TECH_DISCOVERED oder ACTION_TAG_DISCOVERED) zu starten, bis eine Anwendung nach dem Intent filtert oder das Tag-Dispatch-System alle möglichen Intents ausprobiert hat.
  3. Wenn keine Apps nach den Intents filtern, müssen Sie nichts unternehmen.
Abbildung 1. Tag Dispatch System

Verwenden Sie nach Möglichkeit NDEF-Nachrichten und die ACTION_NDEF_DISCOVERED-Intent, da sie die spezifischste von allen drei ist. Mit diesem Intent können Sie Ihre Anwendung zu einem geeigneteren Zeitpunkt starten als mit den anderen beiden Intents. Das ist für die Nutzer angenehmer.

NFC-Zugriff im Android-Manifest anfordern

Bevor Sie auf die NFC-Hardware eines Geräts zugreifen und NFC-Intents ordnungsgemäß verarbeiten können, müssen Sie die folgenden Elemente in Ihrer AndroidManifest.xml-Datei deklarieren:

  • Das NFC-Element <uses-permission> zum Zugriff auf die NFC-Hardware:
    <uses-permission android:name="android.permission.NFC" />
  • Die Mindest-SDK-Version, die von Ihrer Anwendung unterstützt werden kann. API-Level 9 unterstützt nur eine eingeschränkte Tag-Auslieferung über ACTION_TAG_DISCOVERED und gewährt nur über das EXTRA_NDEF_MESSAGES-Extra Zugriff auf NDEF-Nachrichten. Auf andere Tag-Properties oder E/A-Vorgänge kann nicht zugegriffen werden. API-Level 10 umfasst eine umfassende Leser-/Schreiberunterstützung sowie NDEF-Pushing im Vordergrund. API-Level 14 bietet zusätzliche praktische Methoden zum Erstellen von NDEF-Einträgen.
    <uses-sdk android:minSdkVersion="10"/>
  • Das Element uses-feature, damit Ihre App bei Google Play nur auf Geräten mit NFC-Hardware angezeigt wird:
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

    Wenn Ihre Anwendung NFC-Funktionen verwendet, diese Funktion aber nicht für Ihre Anwendung entscheidend ist, können Sie das Element uses-feature weglassen und die NFC-Verfügbarkeit zur Laufzeit prüfen, indem Sie prüfen, ob getDefaultAdapter() null ist.

Nach NFC-Intents filtern

Wenn Ihre App gestartet werden soll, wenn ein NFC-Tag gescannt wird, das Sie verarbeiten möchten, kann Ihre App nach einem, zwei oder allen drei NFC-Intents im Android-Manifest filtern. Normalerweise sollten Sie jedoch nach der ACTION_NDEF_DISCOVERED-Intent filtern, um die Kontrolle darüber zu haben, wann Ihre Anwendung gestartet wird. Der Intent ACTION_TECH_DISCOVERED ist ein Fallback für ACTION_NDEF_DISCOVERED, wenn keine Anwendungen nach ACTION_NDEF_DISCOVERED filtern oder wenn die Nutzlast nicht NDEF ist. Die Kategorie ACTION_TAG_DISCOVERED ist in der Regel zu allgemein, um nach ihr zu filtern. Viele Anwendungen filtern vor ACTION_TAG_DISCOVERED nach ACTION_NDEF_DISCOVERED oder ACTION_TECH_DISCOVERED. Die Wahrscheinlichkeit, dass Ihre Anwendung gestartet wird, ist also gering. ACTION_TAG_DISCOVERED ist nur als letztes Mittel für Apps verfügbar, um nach ihr zu filtern, wenn keine anderen Apps installiert sind, die die ACTION_NDEF_DISCOVERED- oder ACTION_TECH_DISCOVERED-Intention verarbeiten.

Da die NFC-Tag-Bereitstellung variiert und oft nicht von Ihnen gesteuert wird, ist dies nicht immer möglich. Daher können Sie bei Bedarf auf die anderen beiden Intents zurückgreifen. Wenn Sie die Typen der Tags und der geschriebenen Daten steuern können, sollten Sie Ihre Tags mit NDEF formatieren. In den folgenden Abschnitten wird beschrieben, wie Sie nach den einzelnen Arten von Intents filtern.

ACTION_NDEF_DISCOVERED

Wenn Sie nach ACTION_NDEF_DISCOVERED-Intentionen filtern möchten, deklarieren Sie den Intent-Filter zusammen mit dem Datentyp, nach dem Sie filtern möchten. Im folgenden Beispiel wird nach ACTION_NDEF_DISCOVERED-Intents mit dem MIME-Typ text/plain gefiltert:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:mimeType="text/plain" />
</intent-filter>

Im folgenden Beispiel wird nach einem URI in der Form https://developer.android.com/index.html gefiltert.

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT"/>
   <data android:scheme="https"
              android:host="developer.android.com"
              android:pathPrefix="/index.html" />
</intent-filter>

ACTION_TECH_DISCOVERED

Wenn Ihre Aktivität nach der ACTION_TECH_DISCOVERED-Intention filtert, müssen Sie eine XML-Ressourcendatei erstellen, in der die Technologien angegeben sind, die Ihre Aktivität in einem tech-list-Set unterstützt. Ihre Aktivität wird als Übereinstimmung betrachtet, wenn ein tech-list-Set eine Teilmenge der vom Tag unterstützten Technologien ist. Diese können Sie durch Aufrufen von getTechList() abrufen.

Wenn das gescannte Tag beispielsweise MifareClassic, NdefFormatable und NfcA unterstützt, müssen in Ihrem tech-list-Set alle drei, zwei oder eine der Technologien (und nichts anderes) angegeben werden, damit Ihre Aktivität abgeglichen werden kann.

Im folgenden Beispiel werden alle Technologien definiert. Sie müssen die entfernen, die von Ihrem NFC-Tag nicht unterstützt werden. Speichern Sie diese Datei (Sie können ihr einen beliebigen Namen geben) im Ordner <project-root>/res/xml.

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.NfcF</tech>
        <tech>android.nfc.tech.NfcV</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

Sie können auch mehrere tech-list-Gruppen angeben. Die einzelnen tech-list-Sätze werden unabhängig voneinander betrachtet. Ihre Aktivität wird als Übereinstimmung gewertet, wenn ein einzelner tech-list-Satz eine Teilmenge der Technologien ist, die von getTechList() zurückgegeben werden. Dies bietet AND- und OR-Semantik für Abgleichtechnologien. Im folgenden Beispiel werden Tags abgeglichen, die die NfcA- und Ndef-Technologien oder die NfcB- und Ndef-Technologien unterstützen können:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.Ndef</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.Ndef</tech>
    </tech-list>
</resources>

Geben Sie in der AndroidManifest.xml-Datei die gerade erstellte Ressourcendatei im <meta-data>-Element innerhalb des <activity>-Elements an, wie im folgenden Beispiel:

<activity>
...
<intent-filter>
    <action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>

<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
    android:resource="@xml/nfc_tech_filter" />
...
</activity>

Weitere Informationen zur Arbeit mit Tag-Technologien und der ACTION_TECH_DISCOVERED-Intent finden Sie im Dokument „NFC für Fortgeschrittene“ unter Unterstützte Tag-Technologien verwenden.

ACTION_TAG_DISCOVERED

Verwenden Sie den folgenden Intent-Filter, um nach ACTION_TAG_DISCOVERED zu filtern:

<intent-filter>
    <action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>

ACTION_VIEW

Ab Android 16 wird durch das Scannen von NFC-Tags, in denen URL-Links gespeichert sind, der ACTION_VIEW-Intent ausgelöst. Informationen zum Filtern nach ACTION_VIEW finden Sie unter this. Verwenden Sie Android app links, um die App für die URL zu öffnen.

Informationen aus Intents abrufen

Wenn eine Aktivität aufgrund eines NFC-Intents gestartet wird, können Sie über den Intent Informationen zum gescannten NFC-Tag abrufen. Je nach gescanntem Tag können Intents die folgenden Extras enthalten:

Prüfen Sie, ob Ihre Aktivität mit einem der NFC-Intents gestartet wurde, um sicherzustellen, dass ein Tag gescannt wurde, und rufen Sie dann die Extras aus dem Intent ab. Im folgenden Beispiel wird nach dem ACTION_NDEF_DISCOVERED-Intent gesucht und die NDEF-Nachrichten werden aus einem Intent-Extra abgerufen.

Kotlin

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    ...
    if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) {
        intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMessages ->
            val messages: List<NdefMessage> = rawMessages.map { it as NdefMessage }
            // Process the messages array.
            ...
        }
    }
}

Java

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    ...
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
        Parcelable[] rawMessages =
            intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMessages != null) {
            NdefMessage[] messages = new NdefMessage[rawMessages.length];
            for (int i = 0; i < rawMessages.length; i++) {
                messages[i] = (NdefMessage) rawMessages[i];
            }
            // Process the messages array.
            ...
        }
    }
}

Alternativ können Sie über den Intent ein Tag-Objekt abrufen, das die Nutzlast enthält und mit dem Sie die Technologien des Tags auflisten können:

Kotlin

val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)

Java

Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

Gängige NDEF-Eintragstypen erstellen

In diesem Abschnitt wird beschrieben, wie Sie gängige Arten von NDEF-Einträgen erstellen, um das Schreiben auf NFC-Tags zu erleichtern. Ab Android 4.0 (API-Level 14) ist die Methode createUri() verfügbar, mit der Sie URI-Einträge automatisch erstellen können. Ab Android 4.1 (API-Ebene 16) sind createExternal() und createMime() verfügbar, um MIME- und externe NDEF-Einträge zu erstellen. Verwenden Sie nach Möglichkeit diese Hilfsmethoden, um Fehler beim manuellen Erstellen von NDEF-Einträgen zu vermeiden.

In diesem Abschnitt wird auch beschrieben, wie Sie den entsprechenden Intent-Filter für den Eintrag erstellen. Alle diese NDEF-Eintragsbeispiele sollten sich im ersten NDEF-Eintrag der NDEF-Nachricht befinden, die Sie in ein Tag schreiben.

TNF_ABSOLUTE_URI

Hinweis:Wir empfehlen, den Typ RTD_URI anstelle von TNF_ABSOLUTE_URI zu verwenden, da er effizienter ist.

So erstellen Sie einen TNF_ABSOLUTE_URI-NDEF-Eintrag:

Kotlin

val uriRecord = ByteArray(0).let { emptyByteArray ->
    NdefRecord(
            TNF_ABSOLUTE_URI,
            "https://developer.android.com/index.html".toByteArray(Charset.forName("US-ASCII")),
            emptyByteArray,
            emptyByteArray
    )
}

Java

NdefRecord uriRecord = new NdefRecord(
    NdefRecord.TNF_ABSOLUTE_URI ,
    "https://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")),
    new byte[0], new byte[0]);

Der Intent-Filter für den vorherigen NDEF-Eintrag würde so aussehen:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="https"
        android:host="developer.android.com"
        android:pathPrefix="/index.html" />
</intent-filter>

TNF_MIME_MEDIA

Sie haben folgende Möglichkeiten, einen TNF_MIME_MEDIA-NDEF-Eintrag zu erstellen:

createMime()-Methode verwenden:

Kotlin

val mimeRecord = NdefRecord.createMime(
        "application/vnd.com.example.android.beam",
        "Beam me up, Android".toByteArray(Charset.forName("US-ASCII"))
)

Java

NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam",
    "Beam me up, Android".getBytes(Charset.forName("US-ASCII")));

NdefRecord manuell erstellen:

Kotlin

val mimeRecord = Charset.forName("US-ASCII").let { usAscii ->
    NdefRecord(
            NdefRecord.TNF_MIME_MEDIA,
            "application/vnd.com.example.android.beam".toByteArray(usAscii),
            ByteArray(0),
            "Beam me up, Android!".toByteArray(usAscii)
    )
}

Java

NdefRecord mimeRecord = new NdefRecord(
    NdefRecord.TNF_MIME_MEDIA ,
    "application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")),
    new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));

Der Intent-Filter für den vorherigen NDEF-Eintrag würde so aussehen:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="application/vnd.com.example.android.beam" />
</intent-filter>

TNF_WELL_KNOWN mit RTD_TEXT

So erstellen Sie einen TNF_WELL_KNOWN-NDEF-Eintrag:

Kotlin

fun createTextRecord(payload: String, locale: Locale, encodeInUtf8: Boolean): NdefRecord {
    val langBytes = locale.language.toByteArray(Charset.forName("US-ASCII"))
    val utfEncoding = if (encodeInUtf8) Charset.forName("UTF-8") else Charset.forName("UTF-16")
    val textBytes = payload.toByteArray(utfEncoding)
    val utfBit: Int = if (encodeInUtf8) 0 else 1 shl 7
    val status = (utfBit + langBytes.size).toChar()
    val data = ByteArray(1 + langBytes.size + textBytes.size)
    data[0] = status.toByte()
    System.arraycopy(langBytes, 0, data, 1, langBytes.size)
    System.arraycopy(textBytes, 0, data, 1 + langBytes.size, textBytes.size)
    return NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, ByteArray(0), data)
}

Java

public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) {
    byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
    Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
    byte[] textBytes = payload.getBytes(utfEncoding);
    int utfBit = encodeInUtf8 ? 0 : (1 << 7);
    char status = (char) (utfBit + langBytes.length);
    byte[] data = new byte[1 + langBytes.length + textBytes.length];
    data[0] = (byte) status;
    System.arraycopy(langBytes, 0, data, 1, langBytes.length);
    System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
    NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
    NdefRecord.RTD_TEXT, new byte[0], data);
    return record;
}

Der Intent-Filter für den vorherigen NDEF-Eintrag würde so aussehen:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="text/plain" />
</intent-filter>

TNF_WELL_KNOWN mit RTD_URI

Sie haben folgende Möglichkeiten, einen TNF_WELL_KNOWN-NDEF-Eintrag zu erstellen:

createUri(String)-Methode verwenden:

Kotlin

val rtdUriRecord1 = NdefRecord.createUri("https://example.com")

Java

NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");

createUri(Uri)-Methode verwenden:

Kotlin

val rtdUriRecord2 = Uri.parse("https://example.com").let { uri ->
    NdefRecord.createUri(uri)
}

Java

Uri uri = Uri.parse("https://example.com");
NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);

NdefRecord manuell erstellen:

Kotlin

val uriField = "example.com".toByteArray(Charset.forName("US-ASCII"))
val payload = ByteArray(uriField.size + 1)                   //add 1 for the URI Prefix
payload [0] = 0x01                                           //prefixes https://www. to the URI
System.arraycopy(uriField, 0, payload, 1, uriField.size)     //appends URI to payload
val rtdUriRecord = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, ByteArray(0), payload)

Java

byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII"));
byte[] payload = new byte[uriField.length + 1];              //add 1 for the URI Prefix
payload[0] = 0x01;                                           //prefixes https://www. to the URI
System.arraycopy(uriField, 0, payload, 1, uriField.length);  //appends URI to payload
NdefRecord rtdUriRecord = new NdefRecord(
    NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);

Der Intent-Filter für den vorherigen NDEF-Eintrag würde so aussehen:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="https"
        android:host="example.com"
        android:pathPrefix="" />
</intent-filter>

TNF_EXTERNAL_TYPE

Sie haben folgende Möglichkeiten, einen TNF_EXTERNAL_TYPE-NDEF-Eintrag zu erstellen:

createExternal()-Methode verwenden:

Kotlin

var payload: ByteArray //assign to your data
val domain = "com.example" //usually your app's package name
val type = "externalType"
val extRecord = NdefRecord.createExternal(domain, type, payload)

Java

byte[] payload; //assign to your data
String domain = "com.example"; //usually your app's package name
String type = "externalType";
NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);

NdefRecord manuell erstellen:

Kotlin

var payload: ByteArray
...
val extRecord = NdefRecord(
        NdefRecord.TNF_EXTERNAL_TYPE,
        "com.example:externalType".toByteArray(Charset.forName("US-ASCII")),
        ByteArray(0),
        payload
)

Java

byte[] payload;
...
NdefRecord extRecord = new NdefRecord(
    NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".getBytes(Charset.forName("US-ASCII")),
    new byte[0], payload);

Der Intent-Filter für den vorherigen NDEF-Eintrag würde so aussehen:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="vnd.android.nfc"
        android:host="ext"
        android:pathPrefix="/com.example:externalType"/>
</intent-filter>

Verwenden Sie TNF_EXTERNAL_TYPE für allgemeinere NFC-Tag-Implementierungen, um sowohl Android- als auch Nicht-Android-Geräte besser zu unterstützen.

Hinweis: URNs für TNF_EXTERNAL_TYPE haben das kanonische Format urn:nfc:ext:example.com:externalType. Gemäß der NFC Forum RTD-Spezifikation muss der Teil urn:nfc:ext: der URN jedoch aus dem NDEF-Eintrag entfernt werden. Sie müssen also nur die Domain (example.com im Beispiel) und den Typ (externalType im Beispiel) durch einen Doppelpunkt getrennt angeben. Beim Senden von TNF_EXTERNAL_TYPE wandelt Android die urn:nfc:ext:example.com:externalType -URN in einen vnd.android.nfc://ext/example.com:externalType-URI um, was im Intent-Filter im Beispiel angegeben ist.

Einträge zu Android-Apps

Ein Android Application Record (AAR), der in Android 4.0 (API-Level 14) eingeführt wurde, bietet eine größere Sicherheit, dass Ihre App gestartet wird, wenn ein NFC-Tag gescannt wird. Ein AAR enthält den Paketnamen einer Anwendung, der in einen NDEF-Eintrag eingebettet ist. Sie können jedem NDEF-Eintrag Ihrer NDEF-Nachricht einen AAR hinzufügen, da Android die gesamte NDEF-Nachricht nach AARs sucht. Wenn ein AAR gefunden wird, wird die Anwendung basierend auf dem Paketnamen im AAR gestartet. Wenn die App nicht auf dem Gerät vorhanden ist, wird Google Play gestartet, um die App herunterzuladen.

AARs sind nützlich, wenn Sie verhindern möchten, dass andere Anwendungen nach derselben Absicht filtern und möglicherweise bestimmte von Ihnen bereitgestellte Tags verarbeiten. AARs werden aufgrund der Einschränkung des Paketnamens nur auf Anwendungsebene unterstützt und nicht auf Aktivitätsebene wie beim Intent-Filter. Wenn Sie einen Intent auf Aktivitätsebene verarbeiten möchten, verwenden Sie Intent-Filter.

Wenn ein Tag einen AAR enthält, erfolgt die Zustellung durch das Tag-Dispatch-System auf folgende Weise:

  1. Versuchen Sie, wie gewohnt eine Aktivität mit einem Intent-Filter zu starten. Wenn die Aktivität, die mit dem Intent übereinstimmt, auch mit der AAR übereinstimmt, starten Sie die Aktivität.
  2. Wenn die Aktivität, die nach dem Intent filtert, nicht mit der AAR übereinstimmt, wenn mehrere Aktivitäten den Intent verarbeiten können oder wenn keine Aktivität den Intent verarbeitet, starten Sie die in der AAR angegebene Anwendung.
  3. Wenn keine Anwendung mit dem AAR gestartet werden kann, laden Sie die App, die auf dem AAR basiert, bei Google Play herunter.

Hinweis:Sie können AARs und das Intent-Dispatch-System mit dem Dispatch-System für den Vordergrund überschreiben. Dadurch kann eine Aktivität im Vordergrund Vorrang haben, wenn ein NFC-Tag erkannt wird. Bei dieser Methode muss sich die Aktivität im Vordergrund befinden, um AARs und das Intent-Dispatch-System zu überschreiben.

Wenn Sie weiterhin nach gescannten Tags filtern möchten, die keine AAR enthalten, können Sie Intent-Filter wie gewohnt deklarieren. Das ist nützlich, wenn Ihre Anwendung an anderen Tags interessiert ist, die keine AAR enthalten. Vielleicht möchten Sie beispielsweise dafür sorgen, dass Ihre Anwendung sowohl von Ihnen bereitgestellte eigene Tags als auch allgemeine Tags von Drittanbietern verarbeitet. Beachten Sie, dass AARs nur für Geräte mit Android 4.0 oder höher geeignet sind. Wenn Sie Tags bereitstellen, sollten Sie daher am besten eine Kombination aus AARs und MIME-Typen/URIs verwenden, um möglichst viele Geräte zu unterstützen. Berücksichtigen Sie beim Bereitstellen von NFC-Tags außerdem, wie Sie sie beschreiben möchten, damit die meisten Geräte (Android- und andere Geräte) unterstützt werden. Sie können dazu einen relativ eindeutigen MIME-Typ oder URI definieren, um die Unterscheidung für Anwendungen zu erleichtern.

Android bietet eine einfache API zum Erstellen einer AAR,createApplicationRecord(). Sie müssen den AAR nur an einer beliebigen Stelle in Ihre NdefMessage einbetten. Verwenden Sie den ersten Datensatz Ihrer NdefMessage nur, wenn der AAR der einzige Datensatz in der NdefMessage ist. Das liegt daran, dass das Android-System den ersten Eintrag einer NdefMessage prüft, um den MIME-Typ oder die URI des Tags zu ermitteln. Diese Informationen werden verwendet, um einen Intent für Anwendungen zu erstellen, der gefiltert werden soll. Im folgenden Code wird gezeigt, wie eine AAR erstellt wird:

Kotlin

val msg = NdefMessage(
        arrayOf(
                ...,
                NdefRecord.createApplicationRecord("com.example.android.beam")
        )
)

Java

NdefMessage msg = new NdefMessage(
        new NdefRecord[] {
            ...,
            NdefRecord.createApplicationRecord("com.example.android.beam")}
        );
)

Zulassungsliste für Apps zum Scannen von NFC-Tags

Ab Android 16 werden Nutzer benachrichtigt, wenn eine App die erste NFC-Intent zum Scannen von NFC-Tags empfängt. Der Nutzer hat in der Benachrichtigung die Möglichkeit, der App zu untersagen, nach NFC-Tags zu suchen.

Hinweis:Die Zulassungsliste für Apps zum Scannen von NFC-Tags finden Sie unter Settings > Apps > Special app access > Launch via NFC.

Dieser Mechanismus wurde hinzugefügt, um Bedenken von Nutzern zu berücksichtigen, bei denen einige Apps, die Intent-Filter für NFC-Tag-Intents registriert hatten, wiederholt in den Vordergrund gebracht wurden, wenn sie das Smartphone neben ein NFC-Tag (z. B. eine Kreditkarte, ein anderes Smartphone oder eine Smartwatch) hielten.