Podstawy komunikacji NFC

Ten dokument zawiera opis podstawowych zadań dotyczących NFC, które możesz wykonywać na urządzeniu z Androidem. Przewodnik ten wyjaśnia, jak wysyłać i odbierać dane NFC w postaci komunikatów NDEF, oraz opisuje interfejsy API frameworka Androida, które obsługują te funkcje. Bardziej zaawansowane tematy, w tym omówienie pracy z danymi innymi niż NDEF, znajdziesz w artykule Zaawansowane funkcje NFC.

Odczyt danych NDEF z tagu NFC jest obsługiwany przez system wysyłki tagów, który analizuje wykryte tagi NFC, odpowiednio kategoryzuje dane i uruchamia aplikację zainteresowaną danymi skategoryzowanymi. Aplikacja, która chce obsłużyć zeskanowany tag NFC, może zadeklarować filtr intencji i poprosić o obsługę danych.

System wysyłania tagów

Urządzenia z Androidem zwykle szukają tagów NFC, gdy ekran jest odblokowany, chyba że komunikacja NFC jest wyłączona w menu ustawień urządzenia. Gdy urządzenie z Androidem wykryje tag NFC, pożądane działanie polega na tym, aby najbardziej odpowiednia aktywność obsłużyła intencję bez pytania użytkownika, której aplikacji użyć. Urządzenia skanują tagi NFC w bardzo krótkim zasięgu, więc prawdopodobnie wymuszenie ręcznego wybierania przez użytkowników aktywności spowoduje, że odsuną one urządzenie od tagu i przerwą połączenie. Aby zapobiec wyświetlaniu okna wyboru aktywności, należy tak zaprogramować swoją aktywność, aby obsługiwała tylko te tagi NFC, które są dla niej istotne.

Aby Ci to ułatwić, Android udostępnia specjalny system obsługi tagów, który analizuje zeskanowane tagi NFC, interpretuje je i próbuje zlokalizować aplikacje zainteresowane zeskanowanymi danymi. Dokonuje tego,

  1. Przetwarzanie znacznika NFC i ustalanie typu MIME lub identyfikatora URI, który identyfikuje dane w znaczniku.
  2. Opakowanie typu MIME lub identyfikatora URI oraz danych w intencji. Pierwsze 2 kroki opisaliśmy w sekcji Jak tagi NFC są mapowane na typy MIME i identyfikatory URI.
  3. Rozpoczyna aktywność na podstawie intencji. Opisaliśmy to w sekcji Jak tagi NFC są wysyłane do aplikacji.

Jak tagi NFC są mapowane na typy MIME i identyfikatory URI

Zanim zaczniesz pisać aplikacje NFC, warto poznać różne typy tagów NFC, sposób analizowania tych tagów przez system wysyłania tagów oraz zadania wykonywane przez system wysyłania tagów w przypadku wykrycia komunikatu NDEF. Tagi NFC są dostępne w wielu różnych technologiach i można na nich zapisywać dane na wiele różnych sposobów. Android obsługuje standard NDEF, który jest definiowany przez Forum NFC.

Dane NDEF są zaszyfrowane w ramach komunikatu (NdefMessage), który zawiera co najmniej jeden rekord (NdefRecord). Każdy rekord NDEF musi być poprawny zgodnie ze specyfikacją typu rekordu, który chcesz utworzyć. Android obsługuje też inne typy tagów, które nie zawierają danych NDEF. Z takich tagów możesz korzystać, używając klas w pakiecie android.nfc.tech. Więcej informacji o tych technologiach znajdziesz w artykule NFC zaawansowane. Praca z tymi innymi typami tagów wymaga napisania własnego zestawu protokołów do komunikacji z tagami, dlatego zalecamy używanie NDEF, gdy tylko to możliwe, aby ułatwić proces tworzenia i maksymalnie zwiększyć obsługę urządzeń z Androidem.

Uwaga: aby pobrać pełne specyfikacje NDEF, wejdź na stronę Specyfikacje i dokumenty aplikacyjne Forum NFC i otwórz stronę Tworzenie typowych rekordów NDEF, aby zobaczyć przykłady tworzenia rekordów NDEF.

Teraz, gdy już wiesz coś więcej o tagach NFC, w następnych sekcjach znajdziesz bardziej szczegółowe informacje o tym, jak Android obsługuje tagi w formacie NDEF. Gdy urządzenie z Androidem zeskanuje tag NFC zawierający dane w formacie NDEF, przeanalizuje wiadomość i spróbuje określić typ MIME danych lub identyfikujący URI. W tym celu system odczytuje pierwszy NdefRecord w ramach NdefMessage, aby określić, jak interpretować całą wiadomość NDEF (wiadomość NDEF może mieć wiele rekordów NDEF). W prawidłowo sformułowanej wiadomości NDEF pierwsze NdefRecord zawiera te pola:

3-bitowy format TNF (Type Name Format)
Wskazuje, jak interpretować pole typu o zmiennej długości. Prawidłowe wartości są opisane w tabeli 1.
Typ o zmiennej długości
Określa typ rekordu. Jeśli używasz TNF_WELL_KNOWN, użyj tego pola do określenia definicji typu rekordu (RTD). Prawidłowe wartości RTD zostały opisane w tabeli 2.
Identyfikator zmiennej długości
Unikalny identyfikator rekordu. To pole nie jest używane często, ale jeśli musisz jednoznacznie zidentyfikować tag, możesz utworzyć dla niego identyfikator.
Ładunek o zmiennej długości
Prawdziwy ładunek danych, który chcesz odczytać lub zapisać. Wiadomość NDEF może zawierać wiele rekordów NDEF, nie zakładaj więc, że pełny ładunek znajduje się w pierwszym rekordzie NDEF wiadomości NDEF.

System obsługi tagów używa pól TNF i type, aby spróbować dopasować typ MIME lub identyfikator URI do wiadomości NDEF. W przypadku powodzenia informacje te są umieszczane w intencji ACTION_NDEF_DISCOVERED wraz z rzeczywistym ładunkiem. Zdarzają się jednak sytuacje, w których system wysyłania tagów nie może określić typu danych na podstawie pierwszego rekordu NDEF. Dzieje się tak, gdy danych NDEF nie można odwzorować na typ MIME lub identyfikator URI albo gdy tag NFC nie zawiera danych NDEF. W takich przypadkach obiekt Tag zawierający informacje o technologiach tagu i o ładunku jest umieszczany w intencji ACTION_TECH_DISCOVERED.

Tabela 1 opisuje, jak system obsługi tagów mapuje pola TNF i type na typy MIME lub URI. Zawiera on też opis, które TNF nie mogą być mapowane na typ MIME ani identyfikator URI. W takich przypadkach system wysyłania tagów korzysta z ACTION_TECH_DISCOVERED.

Jeśli na przykład system obsługi tagów napotka rekord typu TNF_ABSOLUTE_URI, mapuje pole typu zmiennej długości tego rekordu na identyfikator URI. System obsługi tagów umieszcza ten identyfikator URI w polu danych w intencji ACTION_NDEF_DISCOVERED wraz z innymi informacjami o tagu, takimi jak ładunek. Z drugiej strony, jeśli napotka rekord typu TNF_UNKNOWN, tworzy intencję, która zawiera technologie tagu.

Tabela 1. Obsługiwane TNF i ich odwzorowania

Format nazwy typu (TNF) Mapowanie
TNF_ABSOLUTE_URI Identyfikator URI na podstawie pola typu.
TNF_EMPTY Przełącza się na ACTION_TECH_DISCOVERED.
TNF_EXTERNAL_TYPE Identyfikator URI oparty na URN w polu „Type” (Typ). Identyfikator URN jest kodowany w polu typu NDEF w skróconej postaci: <domain_name>:<service_name>. Android mapuje to na identyfikator URI w formie:vnd.android.nfc://ext/<domain_name>:<service_name>.
TNF_MIME_MEDIA Typ MIME na podstawie pola type.
TNF_UNCHANGED Nieprawidłowy w pierwszym rekordzie, więc przyjmuje wartość ACTION_TECH_DISCOVERED.
TNF_UNKNOWN Przełącza się na ACTION_TECH_DISCOVERED.
TNF_WELL_KNOWN Typ MIME lub identyfikator URI w zależności od definicji typu rekordu (RTD) ustawionej w polu typu. Więcej informacji o dostępnych typach danych RTD i ich mapowaniu znajdziesz w tabeli 2.

Tabela 2. Obsługiwane reguły RTD dla TNF_WELL_KNOWN i ich mapowania

Definicja typu rekordu (RTD) Mapowanie
RTD_ALTERNATIVE_CARRIER Przełącza się na ACTION_TECH_DISCOVERED.
RTD_HANDOVER_CARRIER Przełącza się na ACTION_TECH_DISCOVERED.
RTD_HANDOVER_REQUEST Przełącza się na ACTION_TECH_DISCOVERED.
RTD_HANDOVER_SELECT Przełącza się na ACTION_TECH_DISCOVERED.
RTD_SMART_POSTER Identyfikator URI na podstawie parsowania ładunku.
RTD_TEXT Typ MIME elementu text/plain.
RTD_URI Identyfikator URI na podstawie ładunku.

Jak tagi NFC są wysyłane do aplikacji

Gdy system obsługi tagów zakończy tworzenie zamiaru, który zawiera tag NFC i informacje identyfikacyjne, wysyła go do zainteresowanej aplikacji, która filtruje go pod kątem zamiaru. Jeśli do obsługi intencji kwalifikuje się więcej niż 1 aplikacja, użytkownikowi wyświetla się selektor aktywności, aby mógł wybrać odpowiednią aktywność. System obsługi tagów definiuje 3 zamiary, które są wymienione w kolejności od najwyższego do najniższego priorytetu:

  1. ACTION_NDEF_DISCOVERED: ta intencja służy do uruchamiania aktywności, gdy zeskanowany tag zawiera ładunek NDEF i jest rozpoznawany jako należący do rozpoznawanego typu. Jest to intencja o najwyższym priorytecie, a system wysyłania tagów w miarę możliwości próbuje rozpocząć działanie z tą intencją przed jakąkolwiek inną intencją.
  2. ACTION_TECH_DISCOVERED: jeśli nie zarejestrowano żadnych działań do obsługi inencji ACTION_NDEF_DISCOVERED, system obsługi tagów próbuje uruchomić aplikację z tą intencją. Ta intencja jest również uruchamiana bezpośrednio (bez uruchamiania ACTION_NDEF_DISCOVERED), jeśli skanowany tag zawiera dane NDEF, których nie można odwzorować na typ MIME lub URI, albo jeśli tag nie zawiera danych NDEF, ale jest tagiem o znanej technologii.
  3. ACTION_TAG_DISCOVERED: ta intencja jest uruchamiana, jeśli żadne aktywności nie obsługują intencji ACTION_NDEF_DISCOVERED ani ACTION_TECH_DISCOVERED.

Podstawowy sposób działania systemu rozsyłania tagów:

  1. Spróbuj uruchomić aktywność z zamiarem utworzonym przez system obsługi tagów podczas analizowania tagu NFC (ACTION_NDEF_DISCOVERED lub ACTION_TECH_DISCOVERED).
  2. Jeśli nie ma żadnych aktywności filtrujących ten zamiar, spróbuj uruchomić aktywność z zamiarem o najniższym priorytecie (ACTION_TECH_DISCOVERED lub ACTION_TAG_DISCOVERED), aż aplikacja zacznie filtrować zamiar lub dopóki system obsługi tagów nie spróbuje wszystkich możliwych zamiarów.
  3. Jeśli żadne aplikacje nie filtrują żadnego z zamierowań, nie rób nic.
Rysunek 1. System wysyłania tagów

W miarę możliwości korzystaj z wiadomości NDEF i zamiaru ACTION_NDEF_DISCOVERED, ponieważ jest on najbardziej precyzyjny spośród tych trzech. Ta intencja pozwala uruchomić aplikację w bardziej odpowiednim momencie niż w przypadku pozostałych 2 intencji, co zapewnia użytkownikowi lepsze wrażenia.

Prośba o dostęp do NFC w pliku manifestu Androida

Aby uzyskać dostęp do sprzętu NFC urządzenia i odpowiednio obsługiwać intencje NFC, musisz zadeklarować te elementy w pliku AndroidManifest.xml:

  • Element <uses-permission> NFC dający dostęp do sprzętu NFC:
    <uses-permission android:name="android.permission.NFC" />
    
  • Minimalna wersja pakietu SDK, którą obsługuje Twoja aplikacja. Poziom API 9 obsługuje tylko ograniczone wysyłanie tagów za pomocą funkcji ACTION_TAG_DISCOVERED i daje dostęp do wiadomości NDEF tylko za pomocą funkcji dodatkowej EXTRA_NDEF_MESSAGES. Niedostępne są żadne inne właściwości tagu ani operacje wejścia/wyjścia. Interfejs API w poziomie 10 zapewnia kompleksowe wsparcie dla czytnika/pisaka oraz przesyłanie NDEF na pierwszym planie. Interfejs API w poziomie 14 udostępnia dodatkowe wygodne metody tworzenia rekordów NDEF.
    <uses-sdk android:minSdkVersion="10"/>
    
  • Element uses-feature, dzięki któremu aplikacja będzie widoczna w Google Play tylko na urządzeniach z urządzeniem NFC:
    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    

    Jeśli Twoja aplikacja korzysta z NFC, ale nie jest to niezbędne, możesz pominąć element uses-feature i sprawdzić dostępność NFC w środowisku wykonawczym. W tym celu sprawdź, czy getDefaultAdapter() ma wartość null.

Filtrowanie według intencji NFC

Aby uruchomić aplikację po zeskanowaniu tagu NFC, którego chcesz użyć, aplikacja może filtrować według 1, 2 lub wszystkich 3 intencji NFC w pliku manifestu Androida. Zwykle jednak warto filtrować według zamiaru ACTION_NDEF_DISCOVERED, aby mieć jak największą kontrolę nad momentem uruchamiania aplikacji. Intencją ACTION_TECH_DISCOVERED jest intencja zastępcza dla ACTION_NDEF_DISCOVERED, gdy żadne aplikacje nie filtrują dla ACTION_NDEF_DISCOVERED lub gdy ładunek nie jest NDEF. Filtrowanie kategorii ACTION_TAG_DISCOVERED jest zwykle zbyt ogólne, by uwzględnić ją w filtrze. Wiele aplikacji filtruje ACTION_NDEF_DISCOVERED lub ACTION_TECH_DISCOVERED przed ACTION_TAG_DISCOVERED, więc Twoja aplikacja ma małe prawdopodobieństwo uruchomienia. Funkcja ACTION_TAG_DISCOVERED jest dostępna w ostateczności, gdy aplikacje są odfiltrowywane w przypadkach, gdy nie są zainstalowane żadne inne aplikacje obsługujące intencję ACTION_NDEF_DISCOVERED lub ACTION_TECH_DISCOVERED.

Ze względu na to, że wdrożenia tagów NFC są różne i często nie masz nad nimi kontroli, nie zawsze jest to możliwe. Dlatego w razie potrzeby możesz użyć jednego z 2 innych intencji. Jeśli masz kontrolę nad typami tagów i zapisywanymi danymi, zalecamy sformatowanie tagów za pomocą NDEF. W sekcjach poniżej znajdziesz informacje o tym, jak filtrować według każdego typu zamiaru.

ACTION_NDEF_DISCOVERED

Aby filtrować według intencji ACTION_NDEF_DISCOVERED, zadeklaruj filtr intencji razem z typem danych, według których chcesz filtrować. ACTION_NDEF_DISCOVERED intents z typem MIME text/plain:

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

W tym przykładzie filtrujemy według identyfikatora URI w postaci https://developer.android.com/index.html.

<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

Jeśli aktywność filtruje pod kątem intencji ACTION_TECH_DISCOVERED, musisz utworzyć plik zasobów XML określający technologie, które ta aktywność obsługuje w zbiorze tech-list. Twoja aktywność jest uznawana za dopasowanie, jeśli zbiór tech-list jest podzbiorem technologii obsługiwanych przez tag, który możesz uzyskać, wywołując funkcję getTechList().

Jeśli na przykład zeskanowany tag obsługuje MifareClassic, NdefFormatable i NfcA, zestaw tech-list musi zawierać wszystkie 3 technologie, 2 technologie lub 1 technologię (i nic więcej), aby Twoja aktywność została dopasowana.

Poniższy przykład definiuje wszystkie technologie. Musisz usunąć te, których nie obsługuje Twój tag NFC. Zapisz ten plik (możesz nadać mu dowolną nazwę) w folderze <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>

Możesz też określić kilka zbiorów tech-list. Każdy z zestawów tech-list jest rozpatrywany niezależnie, a Twoja aktywność jest uznawana za dopasowanie, jeśli dowolny zbiór tech-list jest podzbiorem technologii zwracanych przez funkcję getTechList(). Zapewnia to semantykę ANDOR dla dopasowywania technologii. W tym przykładzie pasują tagi, które mogą obsługiwać technologie NFC-A i NDEF lub NFC-B i NDEF:

<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>

W pliku AndroidManifest.xml określ utworzony właśnie plik zasobów w elemencie <meta-data> wewnątrz elementu <activity>, jak w tym przykładzie:

<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>

Więcej informacji o pracy z technologiami tagów i intencją ACTION_TECH_DISCOVERED znajdziesz w dokumentacji dotyczącej zaawansowanych funkcji NFC w sekcji Praca z obsługiwanymi technologiami tagów.

ACTION_TAG_DISCOVERED

Aby filtrować według ACTION_TAG_DISCOVERED, użyj tego filtra intencji:

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

Uzyskiwanie informacji z intencji

Jeśli aktywność rozpoczyna się z powodu intencji NFC, możesz uzyskać informacje o skanowanym tagu NFC z intencji. Zależnie od skanowanego tagu intencje mogą zawierać te dodatkowe informacje:

Aby uzyskać te dodatkowe informacje, sprawdź, czy Twoja aktywność została uruchomiona za pomocą jednego z intencji NFC, aby upewnić się, że tag został zeskanowany, a następnie uzyskać dodatkowe informacje z intencji. W tym przykładzie sprawdzamy intencję ACTION_NDEF_DISCOVERED i pobieramy wiadomości NDEF z dodatkowych danych intencji.

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.
            ...
        }
    }
}

Możesz też uzyskać obiekt Tag z intencji, który zawiera ładunek i umożliwia zliczanie technologii tagu:

Kotlin

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

Java

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

Tworzenie typowych rekordów NDEF

Z tej sekcji dowiesz się, jak tworzyć typowe typy rekordów NDEF, które ułatwią Ci zapisywanie na tagach NFC. Od Androida 4.0 (poziom interfejsu API 14) dostępna jest metoda createUri(), która ułatwia automatyczne tworzenie rekordów URI. Począwszy od Androida 4.1 (poziom interfejsu API 16) dostępne są polecenia createExternal() i createMime(), które ułatwiają tworzenie rekordów NDEF typu MIME i zewnętrznego. Aby uniknąć błędów podczas ręcznego tworzenia rekordów NDEF, używaj tych metod pomocniczych.

W tej sekcji opisaliśmy też, jak utworzyć odpowiedni filtr intencji dla rekordu. Wszystkie te przykłady rekordów NDEF powinny znajdować się w pierwszym rekordzie NDEF wiadomości NDEF zapisywanej na tagu.

TNF_ABSOLUTE_URI

Uwaga: zalecamy używanie typu RTD_URI zamiast TNF_ABSOLUTE_URI, ponieważ jest on wydajniejszy.

Rekord NDEF TNF_ABSOLUTE_URI możesz utworzyć w ten sposób:

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]);

Filtr intencji dla poprzedniego rekordu NDEF wygląda tak:

<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

Rekord NDEF TNF_MIME_MEDIA możesz utworzyć na te sposoby:

Za pomocą metody createMime():

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")));

Tworzenie NdefRecord ręcznie:

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")));

Filtr intencji dla poprzedniego rekordu NDEF wyglądałby tak:

<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 z RTD_TEXT

Rekord NDEF TNF_WELL_KNOWN możesz utworzyć w ten sposób:

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;
}

Filtr intencji dla poprzedniego rekordu NDEF wyglądałby tak:

<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 z RDT_URI

Rekord NDEF TNF_WELL_KNOWN można utworzyć na następujące sposoby:

za pomocą metody createUri(String):

Kotlin

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

Java

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

za pomocą metody createUri(Uri):

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);

Tworzenie NdefRecord ręcznie:

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);

Filtr intencji dla poprzedniego rekordu NDEF wyglądałby tak:

<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>

TYP_ZEWNĘTRZNEGO_TNF

Rekord NDEF TNF_EXTERNAL_TYPE można utworzyć na 2 sposoby:

Za pomocą metody createExternal():

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);

Ręczne utworzenie NdefRecord:

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);

Filtr intencji dla poprzedniego rekordu NDEF wyglądałby tak:

<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>

Użyj TNF_EXTERNAL_TYPE do wdrażania bardziej ogólnych tagów NFC, aby lepiej obsługiwać urządzenia z Androidem i inne.

Uwaga: identyfikatory URN dla TNF_EXTERNAL_TYPE mają kanoniczny format urn:nfc:ext:example.com:externalType. Jednak specyfikacja RTD NFC Forum deklaruje, że w rekordzie NDEF należy pominąć część urn:nfc:ext: identyfikatora URN. Wystarczy, że podasz domenę (w tym przykładzie example.com) i typ (w tym przykładzie externalType), rozdzielone dwukropkiem. Podczas wysyłania TNF_EXTERNAL_TYPE Android konwertuje identyfikator URN urn:nfc:ext:example.com:externalType na identyfikator URI vnd.android.nfc://ext/example.com:externalType, który deklaruje filtr intencji w tym przykładzie.

Rekordy aplikacji na Androida

Wprowadzony w Androidzie 4.0 (poziom interfejsu API 14) rekord aplikacji na Androida (AAR) zapewnia większą pewność, że aplikacja zostanie uruchomiona po zeskanowaniu tagu NFC. Plik AAR zawiera nazwę pakietu aplikacji umieszczoną w rekordzie NDEF. Możesz dodać AAR do dowolnego rekordu NDEF w wiadomości NDEF, ponieważ Android przeszukuje całą wiadomość NDEF w celu znalezienia AAR. Jeśli znajdzie plik AAR, uruchomi aplikację na podstawie nazwy pakietu w tym pliku. Jeśli aplikacja nie jest obecna na urządzeniu, uruchamia się Google Play, aby ją pobrać.

AAR-y są przydatne, jeśli chcesz uniemożliwić innym aplikacjom filtrowanie według tego samego zamiaru i potencjalnie obsługi określonych tagów, które zostały przez Ciebie wdrożone. Ze względu na ograniczenie nazwy pakietu obsługiwane są one tylko na poziomie aplikacji, a nie na poziomie aktywności, jak w przypadku filtrowania intencji. Jeśli chcesz obsłużyć intencję na poziomie aktywności, użyj filtrów intencji.

Jeśli tag zawiera AAR, system obsługi tagów działa w ten sposób:

  1. Spróbuj rozpocząć aktywność, używając filtra intencji tak jak zwykle. Jeśli aktywność pasująca do intencji pasuje również do AAR, uruchom tę aktywność.
  2. Jeśli aktywność, która filtruje intencję, nie pasuje do AAR, jeśli kilka aktywności może obsłużyć intencję lub jeśli żadna aktywność nie obsługuje intencji, uruchom aplikację określoną przez AAR.
  3. Jeśli żadna aplikacja nie może uruchomić pliku AAR, otwórz Google Play i pobierz aplikację na podstawie pliku AAR.

Uwaga: możesz zastąpić AAR i system obsługi intencji systemem obsługi intencji na pierwszym planie, który umożliwia priorytetowe traktowanie aktywności na pierwszym planie po wykryciu tagu NFC. W przypadku tej metody aktywność musi być na pierwszym planie, aby można było zastąpić polecenia AAR i system wysyłania intencji.

Jeśli nadal chcesz filtrować tagi skanowania, które nie zawierają AAR, możesz zadeklarować filtry intencji w zwykły sposób. Jest to przydatne, jeśli aplikacja jest zainteresowana innymi tagami, które nie zawierają AAR. Możesz na przykład chcieć zagwarantować, aby Twoja aplikacja obsługiwała tagi własne, które wdrażasz, a także tagi ogólne wdrażane przez osoby trzecie. Pamiętaj, że tagi AAR są przeznaczone do urządzeń z Androidem 4.0 lub nowszym, więc podczas wdrażania tagów prawdopodobnie zechcesz użyć kombinacji tagów AAR i typów/identyfikatorów URI MIME, aby zapewnić obsługę jak największej liczby urządzeń. Poza tym podczas wdrażania tagów NFC zastanów się, jak chcesz je zapisać, aby umożliwić obsługę na większości urządzeń (z Androidem i innych). Aby to zrobić, zdefiniuj stosunkowo unikalny typ MIME lub identyfikator URI, aby ułatwić aplikacjom ich rozróżnianie.

Android udostępnia prosty interfejs API do tworzenia pakietów AAR.createApplicationRecord() Wystarczy, że umieścisz plik AAR w dowolnym miejscu w swojej NdefMessage. Nie chcesz używać pierwszego rekordu NdefMessage, chyba że AAR jest jedynym rekordem w NdefMessage. Dzieje się tak, ponieważ system Android sprawdza pierwszy rekord ciągu NdefMessage, aby określić typ MIME lub identyfikator URI tagu, który służy do tworzenia intencji filtrowania aplikacji. Poniższy kod pokazuje, jak utworzyć AAR:

Kotlin

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

Java

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