Podstawy komunikacji NFC

W tym dokumencie opisano podstawowe czynności związane z komunikacją NFC, które możesz wykonywać na Androidzie. Wyjaśniono w nim, jak odbiera dane NFC w postaci wiadomości NDEF i opisuje interfejsy API platformy Android, które obsługują tych funkcji. W przypadku bardziej zaawansowanych tematów, w tym dyskusji na temat pracy z danymi innymi niż NDEF, Więcej informacji znajdziesz w sekcji Zaawansowane NFC.

Istnieją 2 główne przypadki użycia danych NDEF i Androida:

  • Odczyt danych NDEF z tagu NFC
  • Przesyłanie wiadomości NDEF z jednego urządzenia na drugie przy użyciu Androida BeamTM

Odczyt danych NDEF z tagu NFC jest obsługiwany przez wysyłkę tagu , który analizuje wykryte tagi NFC, odpowiednio kategoryzuje dane i uruchamia dla aplikacji, która jest zainteresowana danymi kategoryzowanymi. Aplikacja, która chce obsługiwać zeskanowany tag NFC może zadeklarować filtr intencji oraz żądania obsługi danych.

Funkcja Android BeamTM pozwala urządzeniu przesłać wiadomość NDEF na innego urządzenia, fizycznie stykając urządzenia. Taka interakcja ułatwia do wysyłania danych niż w przypadku innych technologii bezprzewodowych, takich jak Bluetooth. Dzięki komunikacji NFC nie trzeba instalować ręcznie urządzeń Wykrywanie lub parowanie jest wymagane. Połączenie nawiązywane jest automatycznie, gdy dwóch urządzeniach do celu. Android Beam jest dostępny przez zestaw interfejsów API NFC, dzięki czemu każda aplikacja może przesyłać i przekazywać informacje między urządzeniami. Na przykład aplikacje Kontakty, Przeglądarka i YouTube używają Android Beam pozwala udostępniać kontakty, strony internetowe i filmy innym urządzeniom.

System wysyłania tagów

Urządzenia z Androidem zwykle szukają tagów NFC, gdy ekran jest odblokowane, chyba że komunikacja NFC jest wyłączona w menu ustawień urządzenia. Po wykryciu tagu NFC przez urządzenie z Androidem wymagane jest jest najodpowiedniejsze działanie intencji bez pytania użytkownika o to, która aplikacja których użyć. Urządzenia skanują tagi NFC w bardzo krótkim zasięgu, więc prawdopodobnie spowoduje to odłączenie urządzenia od tagu i zerwanie połączenia. Opracowuj aktywność tak, aby obsługiwała tylko te tagi NFC, na których Ci zależy uniemożliwia wyświetlenie wyboru aktywności.

Aby Ci w tym pomóc, Android udostępnia specjalny system wysyłania tagów, który analizuje zeskanowane tagów NFC, analizuje je i próbuje znaleźć aplikacje zainteresowane zeskanowanymi danymi. it Robi to przez:

  1. Analiza tagu NFC i ustalenie typu MIME lub identyfikatora URI identyfikującego ładunek danych .
  2. Uwzględnienie typu MIME lub identyfikatora URI i ładunku w intencji. To dwa pierwsze instrukcje znajdziesz w artykule Jak tagi NFC są mapowane na typy MIME i identyfikatory URI.
  3. Rozpoczyna aktywność na podstawie intencji. Opisa to tutaj: Jak tagi NFC są wysyłane do aplikacji.

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

Zanim zaczniesz pisać aplikacje NFC, zapoznaj się z różnymi typy tagów NFC, sposób analizowania tagów NFC przez system wysyłania tagów oraz specjalne funkcje tagów system wysyłania, gdy wykryje wiadomość NDEF. Tagi NFC mają z szeroką gamą technologii, a także zapisywać dane na wiele różnych sposobów. Android w największym stopniu obsługuje standard NDEF, który został zdefiniowany na Forum NFC.

Dane NDEF są zawarte w wiadomości (NdefMessage), która zawiera jeden lub więcej rekordów (NdefRecord). Każdy rekord NDEF musi być poprawnie sformatowany zgodnie z specyfikację typu rekordu, który ma zostać utworzony. Android, obsługuje też inne typy tagów, które nie zawierają danych NDEF. Aby z nich korzystać, użyj funkcji na zajęcia w pakiecie android.nfc.tech. Aby dowiedzieć się więcej, więcej informacji o tych technologiach znajdziesz w temacie Zaawansowane funkcje NFC. Praca z tymi innymi typami tagów obejmuje własnego stosu protokołów do komunikowania się z tagami. Dlatego zalecamy użycie NDEF jest to możliwe ze względu na łatwość programowania i maksymalną obsługę urządzeń z systemem Android.

Uwaga: Aby pobrać pełną specyfikację NDEF, odwiedź specyfikacje Forum NFC dokumenty aplikacyjne oraz Tworzenie typowych typów rekordów NDEF, na których można znaleźć przykłady tworzyć rekordy NDEF.

Skoro już masz wiedzę na temat tagów NFC, w kolejnych sekcjach dowiesz się, jak Android obsługuje tagi w formacie NDEF. Gdy urządzenie z Androidem skanuje tag NFC zawierający NDEF sformatowanych danych, analizuje wiadomość i próbuje określić typ MIME lub zidentyfikować Identyfikator URI. W tym celu system odczytuje pierwszy element NdefRecord wewnątrz ciągu NdefMessage, aby określić, jak zinterpretować cały komunikat NDEF (komunikat NDEF może mają kilka rekordów NDEF). W dobrze sformułowanej wiadomości NDEF pierwszy element NdefRecord zawiera następujące pola:

3-bitowy TNF (format nazwy typu)
Wskazuje, jak interpretować pole typu zmiennej długości. Prawidłowe wartości to opisane w tabeli 1.
Typ zmiennej długości
Określa typ rekordu. Jeśli używasz TNF_WELL_KNOWN, wpisz w tym polu, aby określić definicję 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 często używane, ale (jeśli tag wymaga jednoznacznej identyfikacji, można utworzyć dla niego identyfikator.
Ładunek o zmiennej długości
Rzeczywiste ładunki danych, które chcesz odczytywać lub zapisywać. NDEF komunikat może zawierać wiele rekordów NDEF, więc nie zakładaj, że pełny ładunek znajduje się w pierwszym NDEF w rekordzie wiadomości NDEF.

System wysyłania tagów używa pól TNF i type, aby spróbować zmapować typ MIME lub identyfikator URI Komunikat NDEF. Jeśli operacja się uda, umieszcza tę informację w intencji ACTION_NDEF_DISCOVERED razem z rzeczywistym ładunkiem. Istnieje jednak występują przypadki, gdy system wysyłania tagów nie może określić typu danych na podstawie pierwszego NDEF nagrywać. Dzieje się tak, gdy danych NDEF nie można zmapować na typ MIME lub identyfikator URI albo gdy Tag NFC nie zawiera danych NDEF, od których można zacząć. W takich przypadkach obiekt Tag, który zawiera informacje o technologii tagu i ładunku, jest zawarte w intencji ACTION_TECH_DISCOVERED.

Tabela 1 opisuje, jak system wysyłania tagów mapuje TNF i typ do typów MIME lub identyfikatorów URI. Dowiesz się też, których plików TNF nie można zmapować na typ MIME lub identyfikator URI. W takich przypadkach system wysyłki tagów przełącza się na ACTION_TECH_DISCOVERED

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

Tabela 1. Obsługiwane pliki TNF i ich mapowania

Format nazwy typu (TNF) Mapowanie
TNF_ABSOLUTE_URI Identyfikator URI na podstawie pola typu.
TNF_EMPTY Powraca do ACTION_TECH_DISCOVERED.
TNF_EXTERNAL_TYPE Identyfikator URI oparty na URN w polu typu. URN jest kodowany w polu typu NDEF w skrócona forma: <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 typu.
TNF_UNCHANGED Nieprawidłowa w pierwszym rekordzie, dlatego wartość używana jest ACTION_TECH_DISCOVERED
TNF_UNKNOWN Powraca do ACTION_TECH_DISCOVERED.
TNF_WELL_KNOWN Typ MIME lub identyfikator URI w zależności od definicji typu rekordu (RTD) ustawionej w type (Typ konwersji). Więcej informacji znajdziesz w tabeli 2. dostępnych RTD i ich mapowań.

Tabela 2. RTD obsługiwane w przypadku użytkowników TNF_WELL_KNOWN i mapowania

Definicja typu rekordu (RTD) Mapowanie
RTD_ALTERNATIVE_CARRIER Powraca do ACTION_TECH_DISCOVERED.
RTD_HANDOVER_CARRIER Powraca do ACTION_TECH_DISCOVERED.
RTD_HANDOVER_REQUEST Powraca do ACTION_TECH_DISCOVERED.
RTD_HANDOVER_SELECT Powraca do ACTION_TECH_DISCOVERED.
RTD_SMART_POSTER Identyfikator URI oparty na analizie ładunku.
RTD_TEXT Typ MIME: text/plain.
RTD_URI Identyfikator URI oparty na ładunku.

Jak tagi NFC są wysyłane do aplikacji

Gdy system wysyłania tagów utworzy intencję, która obejmie tag NFC i jego tag wysyła intencje do zainteresowanych aplikacji, filtry intencji. Jeśli więcej niż jedna aplikacja może obsłużyć intencję, narzędzie wyboru aktywności jest wyświetlana, aby użytkownik mógł wybrać aktywność. System wysyłania tagów definiuje 3 intencje: 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 Działanie, gdy tag zawierający ładunek NDEF jest skanowany i ma rozpoznany typ. To jest o intencji o najwyższym priorytecie, a system wysyłania tagów próbuje uruchomić działanie z tym elementem przed intencjami z innymi intencjami, gdy tylko jest to możliwe.
  2. ACTION_TECH_DISCOVERED: jeśli żadne aktywności nie są rejestrowane na obsługuje: ACTION_NDEF_DISCOVERED system wysyłania tagów próbuje uruchomić aplikację z tą intencją. Ten intencja jest również inicjowana bezpośrednio (bez rozpoczynania dyrektywy ACTION_NDEF_DISCOVERED), jeśli skanowany tag zawiera dane NDEF, których nie można zmapować na typ MIME lub identyfikator URI albo jeśli tag nie zawiera NDEF ale pochodzą ze znanej technologii tagów.
  3. ACTION_TAG_DISCOVERED: ta intencja została uruchomiona jeśli żadne działania nie obsługują funkcji ACTION_NDEF_DISCOVERED lub ACTION_TECH_DISCOVERED intencji.

Podstawowy sposób działania systemu wysyłania tagów jest następujący:

  1. Spróbuj uruchomić aktywność z intencją utworzoną przez system wysyłania tagów podczas analizowania tagu NFC (albo ACTION_NDEF_DISCOVERED lub ACTION_TECH_DISCOVERED).
  2. Jeśli żadne działania nie są filtrowane dla tej intencji, spróbuj rozpocząć aktywność od następnej intencja o najniższym priorytecie (ACTION_TECH_DISCOVERED lub ACTION_TAG_DISCOVERED), dopóki aplikacja nie przefiltruje danych pod kątem argumentu lub do czasu, gdy system wysyłania tagów spróbuje użyć wszystkich możliwych intencji.
  3. Jeśli żadna z aplikacji nie filtruje według którejkolwiek z intencji, nie rób nic.
.
Rys. 1. System wysyłania tagów

W miarę możliwości korzystaj z wiadomości NDEF i intencji ACTION_NDEF_DISCOVERED, ponieważ jest to najbardziej szczegółowy trzy. Ta intencja umożliwia uruchomienie aplikacji w bardziej odpowiednim momencie niż dla wygody użytkownika.

Poproś o dostęp do NFC w pliku manifestu Androida

Aby uzyskać dostęp do sprzętu NFC urządzenia i prawidłowo obsługiwać intencje NFC, zadeklaruj 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. Interfejs API poziomu 9 obsługuje tylko ograniczona dostawa tagów przez ACTION_TAG_DISCOVERED i daje tylko dostęp do wiadomości NDEF przy użyciu dodatku EXTRA_NDEF_MESSAGES. Nie inne właściwości tagów lub operacje wejścia-wyjścia. Poziom API 10 obejmuje kompleksową obsługę odczytu/zapisu, a także przekazywanie NDEF na pierwszym planie i poziom interfejsu API. 14 to łatwiejszy sposób na przesyłanie wiadomości NDEF na inne urządzenia za pomocą Android Beam i dodatkowych wygodnych metod tworzenia rekordów NDEF.
    <uses-sdk android:minSdkVersion="10"/>
    
  • Element uses-feature, który umożliwia wyświetlenie aplikacji w Google Play tylko w przypadku urządzeń wyposażonych w moduł NFC:
    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    

    Jeśli aplikacja obsługuje komunikację NFC, aplikacji, możesz pominąć element uses-feature i sprawdzić dostępność NFC na stronie w środowisku wykonawczym, sprawdzając, czy getDefaultAdapter() jest null.

Filtruj pod kątem intencji NFC

Aby uruchomić aplikację po zeskanowaniu tagu NFC, który chcesz obsługiwać, może filtrować jedną, dwie lub wszystkie 3 intencje NFC w pliku manifestu Androida. Musisz jednak zwykle filtrują pod kątem intencji ACTION_NDEF_DISCOVERED dla mają największą kontrolę nad czasem uruchamiania aplikacji. Intencja ACTION_TECH_DISCOVERED jest regułą zastępczą dla reguły ACTION_NDEF_DISCOVERED, gdy żadne aplikacje nie filtrują dla tego parametru ACTION_NDEF_DISCOVERED lub gdy ładunek nie jest NDEF. Filtrowanie danych „ACTION_TAG_DISCOVERED” jest zwykle zbyt ogólne dla według kategorii, według której chcesz filtrować. Wiele aplikacji będzie odfiltrowywać ACTION_NDEF_DISCOVERED lub ACTION_TECH_DISCOVERED przed ACTION_TAG_DISCOVERED, więc w ich przypadku prawdopodobieństwo od uruchomienia. Z usługi ACTION_TAG_DISCOVERED można korzystać tylko w ostateczności dla aplikacji, które mają być filtrowane w przypadku, gdy nie są zainstalowane żadne inne aplikacje do obsługi Intencja ACTION_NDEF_DISCOVERED lub ACTION_TECH_DISCOVERED.

Implementacja tagów NFC jest różna i często nie zależy od Ciebie, dlatego nie zawsze jest to możliwe. dlatego w razie potrzeby zawsze możesz skorzystać z 2 pozostałych intencji. Jeśli masz nad typami tagów i zapisywanych danych, zalecamy użycie NDEF do formatowania . W sekcjach poniżej opisujemy, jak filtrować dane pod kątem poszczególnych typów intencji.

ACTION_NDEF_DISCOVERED

Aby filtrować intencje ACTION_NDEF_DISCOVERED, zadeklaruj klucz filtr intencji wraz z typem danych, według których chcesz filtrować. te przykładowe filtry dla zapytania ACTION_NDEF_DISCOVERED intencje 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>

Poniższy przykład filtruje identyfikator URI w formie 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 Twoja aktywność filtruje treści pod kątem intencji ACTION_TECH_DISCOVERED, musisz utworzyć plik zasobów XML określający technologie, które obsługuje Twoja aktywność w zbiorze tech-list. Twoja aktywność to uznaje się za dopasowanie, jeśli zbiór tech-list jest podzbiorem technologii, które są obsługiwane przez tag. Można je uzyskać, wywołując metodę getTechList().

Jeśli na przykład skanowany tag obsługuje MifareClassic, NdefFormatable i NfcA, tag Zbiór tech-list musi określać wszystkie 3, 2 lub 1 z technologii (i nic inne), aby Twoja aktywność była dopasowywana.

Poniższy przykład definiuje wszystkie technologie. Usuń te, które nie są obsługiwane przez Twój tag NFC. Zapisz ten plik (nadaj mu dowolną nazwę) w Folder <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. tech-list są rozpatrywane niezależnie, a Twoja aktywność zostanie uznana za dopasowanie, jeśli Zbiór tech-list to podzbiór technologii zwracanych przez funkcję getTechList(). Ta funkcja zapewnia AND i OR semantyka technologii dopasowywania. Poniższy przykład pasuje do tagów, które mogą obsługiwać technologii NfcA i Ndef lub obsługuje technologie NfcB 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 wskaż utworzony przed chwilą plik zasobów. w elemencie <meta-data> wewnątrz <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 korzystaniu z technologii tagów i intencji ACTION_TECH_DISCOVERED znajdziesz w artykule Praca z obsługiwanym tagiem Technologie w dokumencie Advanced NFC.

ACTION_TAG_DISCOVERED

Aby filtrować dane według parametru ACTION_TAG_DISCOVERED, użyj tej intencji filtr:

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

Uzyskiwanie informacji z intencji

Jeśli aktywność zostanie uruchomiona z powodu intencji NFC, możesz uzyskać informacje o zeskanowanym urządzeniu z intencji. W zależności od skanowanego tagu intencje mogą zawierać te dodatki:

Aby uzyskać te dodatki, sprawdź, czy Twoja aktywność została uruchomiona przy użyciu jednego z w celu sprawdzenia, czy tag został przeskanowany, a następnie uzyskania dodatków intencji. Ten przykład pozwala sprawdzić stan ACTION_NDEF_DISCOVERED i pobiera wiadomości NDEF z dodatkowej 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ć z intencji obiekt Tag, który zawierają ładunek i pozwalają wymienić technologie tagu:

Kotlin

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

Java

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

Tworzenie typowych typów rekordów NDEF

W tej sekcji opisano tworzenie typowych typów rekordów NDEF ułatwiających pisanie wysyłanie tagów NFC lub danych za pomocą Android Beam; Począwszy od Androida 4.0 (poziom interfejsu API 14) Metoda createUri(), która pomoże Ci utworzyć automatycznie rekordy URI. Od Androida 4.1 (poziom interfejsu API 16) createExternal() i createMime() mogą pomóc Ci w tworzeniu Rekordy NDEF typu MIME i zewnętrzne. W miarę możliwości korzystaj z tych metod pomocniczych, aby uniknąć błędów podczas ręcznego tworzenia rekordów NDEF.

W tej sekcji znajdują się również informacje na temat tworzenia odpowiednich filtr intencji dla rekordu. Wszystkie te przykładowe rekordy NDEF powinny znajdować się w pierwszym NDEF zapisu wiadomości NDEF, którą piszesz do tagu lub przesyłasz.

TNF_ABSOLUTE_URI

Uwaga: zalecamy użycie atrybutu Zamiast tego wpisz RTD_URI od TNF_ABSOLUTE_URI, ponieważ jest skuteczniejszy.

Rekord NDEF TNF_ABSOLUTE_URI można utworzyć w następujący 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żna utworzyć na następujące 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")));

Ręczne utworzenie NdefRecord:

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 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żna utworzyć w następujący 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 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 RTD_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);

Ręczne utworzenie NdefRecord:

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 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ć w tych usługach 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 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>

W przypadku bardziej ogólnych wdrożeń tagów NFC używaj zasady TNF_EXTERNAL_TYPE, która zapewni lepszą obsługę obu rodzajów tagów Urządzenia z systemem Android lub bez niego.

Uwaga: kanoniczne numery URN dla TNF_EXTERNAL_TYPE mają następujący format: urn:nfc:ext:example.com:externalType, jednak specyfikacja RTD Forum deklaruje, że część urn:nfc:ext: identyfikatora URN musi zostać pominięta w rekord NDEF. Wystarczy więc podać domenę (w tym przykładzie example.com). i typ (w przykładzie externalType) rozdzielone dwukropkiem. Podczas wysyłania żądania TNF_EXTERNAL_TYPE Android konwertuje URN urn:nfc:ext:example.com:externalType na identyfikator URI vnd.android.nfc://ext/example.com:externalType, który jest deklaruje filtr intencji.

Rekordy aplikacji na Androida

Wprowadzony w Androidzie 4.0 (poziom interfejsu API 14) rekord aplikacji na Androida (AAR) zapewnia aby mieć pewność, że aplikacja zostanie uruchomiona w przypadku skanowania tagu NFC. AAR ma nazwę pakietu aplikacji umieszczonej w rekordzie NDEF. Możesz dodać AAR do dowolnego rekordu NDEF swojego NDEF ponieważ Android przeszukuje całą wiadomość NDEF pod kątem zapytań AAR. Jeśli je znajdzie, uruchamia się aplikacji na podstawie nazwy pakietu w AAR. Jeśli aplikacji nie ma na urządzenia, zostaje uruchomiony Google Play, aby pobrać aplikację.

Są one przydatne, jeśli chcesz zapobiec filtrowaniu przez inne aplikacje pod kątem tych samych intencji może obsługiwać konkretne tagi, które wdrożysz. Oferty AAR są obsługiwane tylko w na poziomie aplikacji ze względu na ograniczenie nazwy pakietu, a nie na poziomie aktywności, jak w przypadku przez filtrowanie intencji. Jeśli chcesz obsługiwać intencję na poziomie aktywności, użyj filtrów intencji.

Jeśli tag zawiera atrybut AAR, system wysyłania tagów wysyła go w taki sposób:

  1. Spróbuj jak zwykle rozpocząć aktywność, korzystając z filtra intencji. Jeśli aktywność pasująca do zapytania intencja jest zgodna z AAR, rozpocznij działanie.
  2. Jeśli działanie, które filtruje intencję, nie pasuje do parametru AAR, jeśli wiele działań może obsłużyć intencję lub żadne działanie nie obsługuje intencji, rozpocznij aplikacji określonej przez AAR.
  3. Jeśli żadna aplikacja nie może zaczynać się od atrybutu AAR, przejdź do Google Play, aby pobrać zgodnie z dokumentem AAR.

Uwaga: reguły AAR i system wysyłania intencji możesz zastąpić funkcją pierwszy plan system wysyłania, który umożliwia priorytetowe traktowaniu aktywności na pierwszym planie, gdy tag NFC jest odkrycie. W przypadku tej metody działanie musi być na pierwszym planie, aby można było zastąpić błędy AAR i system dyspozytorów intencji.

Jeśli mimo to chcesz filtrować wyniki pod kątem zeskanowanych tagów, które nie zawierają atrybutu AAR, możesz zadeklarować filtrów intencji. Przydaje się to, gdy Twoja aplikacja jest zainteresowana innymi tagami które nie zawierają kodu AAR. Jeśli na przykład chcesz zagwarantować, że aplikacja będzie obsługiwać własne tagi i tagi ogólne wdrażane przez Ciebie, jak również tagi ogólne wdrożone przez inne firmy. Pamiętaj że certyfikaty AAR są dostosowane do urządzeń z Androidem 4.0 lub nowszym, więc przy wdrażaniu tagów warto aby użyć kombinacji identyfikatorów AAR i typów MIME/URI w celu obsługi najszerszego zakresu urządzeń. W Jeśli wdrażasz tagi NFC, zastanów się, jak chcesz je zapisać, obsługą większości urządzeń (z systemem Android i innych). Możesz to zrobić w następujący sposób: zdefiniowanie stosunkowo unikalnego typu MIME lub identyfikatora URI, aby aplikacje mogły łatwiej je odróżnić.

Android udostępnia prosty interfejs API do tworzenia AAR, createApplicationRecord() Wszystko, czego potrzebujesz wystarczy umieścić plik AAR w dowolnym miejscu w NdefMessage. Nie chcesz aby użyć pierwszego rekordu z: NdefMessage, chyba że AAR jest jedynym wpis w NdefMessage. To dlatego, że Android system sprawdza pierwszy rekord NdefMessage, aby określić typ MIME lub Identyfikator URI tagu, który jest używany do tworzenia intencji filtrowania przez aplikacje. Następujący kod: pokazuje, jak utworzyć automatyczny klucz 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")}
        );
)

Przesyłaj wiadomości NDEF do innych urządzeń

Android Beam umożliwia prostą wymianę danych peer-to-peer między dwoma urządzeniami z Androidem. aplikacja, która chce przesyłać dane do innego urządzenia, musi działać na pierwszym planie, a urządzenie odbieranie danych nie może być zablokowane. Gdy urządzenie wysyłające znajdzie się wystarczająco blisko urządzenia odbierającego, na urządzeniu wysyłającym wyświetli się komunikat „Dotknij, by przesłać”. Interfejs. Użytkownik może wtedy wybrać czy wysłać wiadomość do urządzenia odbierającego.

Uwaga: przekazywanie NDEF na pierwszym planie było dostępne na poziomie API 10, który oferuje funkcje podobne do Android Beam. Te interfejsy API zostały już wycofane, ale są dostępne na starszych urządzeniach. Przeczytaj enableForegroundNdefPush(), by dowiedzieć się więcej.

Możesz włączyć Android Beam dla swojej aplikacji, wywołując jedną z dwóch metod:

  • setNdefPushMessage(): akceptuje NdefMessage, aby ustawić ją jako wiadomość do przesłania. Automatycznie przesyła wiadomość zbliżeniowo gdy 2 urządzenia znajdują się w odpowiedniej odległości od siebie.
  • setNdefPushMessageCallback(): Akceptuje wywołanie zwrotne zawierające createNdefMessage() która jest wywoływana, gdy urządzenie znajduje się w zasięgu, do którego można przesłać dane. Wywołanie zwrotne umożliwia utworzenie komunikatu NDEF tylko wtedy, gdy jest to konieczne.

Aktywność może przekazać tylko 1 wiadomość NDEF naraz, więc zasada setNdefPushMessageCallback() ma pierwszeństwo więcej niż setNdefPushMessage(), jeśli oba są ustawione. Aby użyć funkcji Android Beam, musisz przestrzegać tych ogólnych wytycznych:

  • Działanie przesyłające dane musi znajdować się na pierwszym planie. Oba urządzenia muszą mieć odblokowane ekrany.
  • Dane, które przesyłasz, musisz umieścić w NdefMessage obiektu.
  • Urządzenie NFC odbierające przesyłane dane musi obsługiwać com.android.npp Protokół push NDEF lub SNEP forum NFC (Simple NDEF Exchange) Protokół). Protokół com.android.npp jest wymagany w przypadku urządzeń z interfejsem API poziomu 9 (Android 2.3) do poziomu API 13 (Android 3.2). Zarówno com.android.npp, jak i SNEP są wymagane na Interfejs API poziomu 14 (Android 4.0) i nowsze.

Uwaga: jeśli w aktywności włączona jest funkcja Android Beam, na pierwszym planie system standardowego wysyłania intencji jest wyłączony. Jeśli jednak Twoja aktywność włącza wysyłanych na pierwszym planie, nadal może skanować tagi pasujące do filtrów intencji ustawionych w parametrze wysyłanie danych na pierwszym planie.

Aby włączyć Android Beam:

  1. Utwórz obiekt NdefMessage zawierający NdefRecord który chcesz rozesłać na drugie urządzenie.
  2. Wywołaj funkcję setNdefPushMessage() za pomocą funkcji NdefMessage lub wywołaj setNdefPushMessageCallback przekazywane w obiekcie NfcAdapter.CreateNdefMessageCallback w metodzie onCreate() Twojej aktywności. Te metody wymagają co najmniej 1 działania, które chcesz włączyć na Androidzie Beam oraz opcjonalną listę innych aktywności, które możesz aktywować.

    Zazwyczaj używasz setNdefPushMessage() wtedy, gdy aktywność wysyłania tego samego komunikatu NDEF przez cały czas, gdy 2 urządzenia znajdują się w zasięgu komunikacji. Używasz setNdefPushMessageCallback, gdy aplikacja dba o bieżący kontekst aplikacji i chce wysłać komunikat NDEF w zależności od tego, co użytkownik robi w aplikacji.

Poniższy przykład pokazuje, jak prosta aktywność wywołuje NfcAdapter.CreateNdefMessageCallback w metodzie onCreate() funkcji (zobacz AndroidBeamDemo) , gdzie znajduje się cała próbka). Ten przykład przedstawia też metody tworzenia rekordu MIME:

Kotlin

package com.example.android.beam

import android.app.Activity
import android.content.Intent
import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.NfcAdapter
import android.nfc.NfcAdapter.CreateNdefMessageCallback
import android.nfc.NfcEvent
import android.os.Bundle
import android.os.Parcelable
import android.widget.TextView
import android.widget.Toast
import java.nio.charset.Charset

class Beam : Activity(), NfcAdapter.CreateNdefMessageCallback {
    
    private var nfcAdapter: NfcAdapter? = null
    private lateinit var textView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
        textView = findViewById(R.id.textView)
        // Check for available NFC Adapter
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show()
            finish()
            return
        }
        // Register callback
        nfcAdapter?.setNdefPushMessageCallback(this, this)
    }

    override fun createNdefMessage(event: NfcEvent): NdefMessage {
        val text = "Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis()
        return NdefMessage(
                arrayOf(
                        createMime("application/vnd.com.example.android.beam", text.toByteArray())
                )
                /**
                 * The Android Application Record (AAR) is commented out. When a device
                 * receives a push with an AAR in it, the application specified in the AAR
                 * is guaranteed to run. The AAR overrides the tag dispatch system.
                 * You can add it back in to guarantee that this
                 * activity starts when receiving a beamed message. For now, this code
                 * uses the tag dispatch system.
                 *///,NdefRecord.createApplicationRecord("com.example.android.beam")
        )
    }

    override fun onResume() {
        super.onResume()
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) {
            processIntent(intent)
        }
    }

    override fun onNewIntent(intent: Intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent)
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    private fun processIntent(intent: Intent) {
        textView = findViewById(R.id.textView)
        // only one message sent during the beam
        intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMsgs ->
            (rawMsgs[0] as NdefMessage).apply {
                // record 0 contains the MIME type, record 1 is the AAR, if present
                textView.text = String(records[0].payload)
            }
        }
    }
}

Java

package com.example.android.beam;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.widget.TextView;
import android.widget.Toast;
import java.nio.charset.Charset;


public class Beam extends Activity implements CreateNdefMessageCallback {
    NfcAdapter nfcAdapter;
    TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView textView = (TextView) findViewById(R.id.textView);
        // Check for available NFC Adapter
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        // Register callback
        nfcAdapter.setNdefPushMessageCallback(this, this);
    }

    @Override
    public NdefMessage createNdefMessage(NfcEvent event) {
        String text = ("Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis());
        NdefMessage msg = new NdefMessage(
                new NdefRecord[] { createMime(
                        "application/vnd.com.example.android.beam", text.getBytes())
         /**
          * The Android Application Record (AAR) is commented out. When a device
          * receives a push with an AAR in it, the application specified in the AAR
          * is guaranteed to run. The AAR overrides the tag dispatch system.
          * You can add it back in to guarantee that this
          * activity starts when receiving a beamed message. For now, this code
          * uses the tag dispatch system.
          */
          //,NdefRecord.createApplicationRecord("com.example.android.beam")
        });
        return msg;
    }

    @Override
    public void onResume() {
        super.onResume();
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
            processIntent(getIntent());
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent);
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    void processIntent(Intent intent) {
        textView = (TextView) findViewById(R.id.textView);
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // only one message sent during the beam
        NdefMessage msg = (NdefMessage) rawMsgs[0];
        // record 0 contains the MIME type, record 1 is the AAR, if present
        textView.setText(new String(msg.getRecords()[0].getPayload()));
    }
}

Pamiętaj, że ten kod komentuje plik AAR, który możesz usunąć. Jeśli włączysz automatyczne stosowanie rekomendacji, aplikacja określona w AAR zawsze otrzymuje wiadomość Android Beam. Jeśli aplikacja nie jest rozpocznie się pobieranie aplikacji przez Google Play. W związku z tym następujący zamiar W przypadku urządzeń z Androidem 4.0 i nowszym stosowanie filtru AAR nie jest technicznie konieczne:

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

Dzięki temu filtrowi intencji można teraz uruchomić aplikację com.example.android.beam gdy skanuje tag NFC lub odbiera sygnał Android Beam z kodem AAR ustawionym na poziomie wpisz com.example.android.beam lub jeśli wiadomość w formacie NDEF zawiera rekord MIME typu application/vnd.com.example.android.beam.

Chociaż AAR gwarantują uruchomienie lub pobranie aplikacji, filtry intencji są zalecane, bo pozwalają rozpocząć aktywność na aplikacji zamiast zawsze uruchamiać główne działanie w pakiecie określonym przez AAR. Rekomendacje AAR nie mają szczegółowości na poziomie aktywności. Ponadto, ponieważ niektóre urządzenia z systemem Android obsługuje aplikacje AAR, należy również umieścić informacje identyfikacyjne w pierwszym rekordzie NDEF dokumentu NDEF wiadomości i filtrować je, tak na wszelki wypadek. Zobacz Tworzenie wspólnych Typy rekordów NDEF.