W tym dokumencie opisujemy zaawansowane zagadnienia dotyczące NFC, takie jak praca z różnymi technologiami tagów, zapisywanie danych do tagów NFC oraz wysyłanie działającej na pierwszym planie, które umożliwia aplikacji na pierwszym planie obsługuje intencje nawet wtedy, gdy inne aplikacje filtrują te same intencje.
Korzystanie z obsługiwanych technologii tagów
W przypadku pracy z tagami NFC i urządzeniami z systemem Android jest to główny format używany do odczytu
a dane zapisu w tagach to NDEF. Gdy urządzenie skanuje tag z danymi NDEF, Android zapewnia pomoc
podczas analizowania wiadomości i dostarczania jej w metodzie NdefMessage
, gdy
jak to tylko możliwe. Istnieją jednak przypadki, gdy skanuje się tag, który nie zawiera
dane NDEF lub gdy danych NDEF nie można zmapować na typ MIME albo identyfikator URI.
W takich przypadkach należy nawiązać bezpośrednią komunikację z tagiem i odczytać go oraz zapisać za pomocą
(w nieprzetworzonych bajtach). Android zapewnia ogólną pomoc w tych przypadkach użycia dzięki
android.nfc.tech
, który został opisany w tabeli 1. Dostępne opcje
użyj metody getTechList()
do określania technologii
obsługiwane przez tag i utwórz odpowiednią wartość TagTechnology
obiekt z jedną z klas udostępnionych przez android.nfc.tech
Kategoria | Opis |
---|---|
TagTechnology |
Interfejs, z którego muszą korzystać wszystkie klasy technologii tagów. |
NfcA |
Zapewnia dostęp do właściwości NFC-A (ISO 14443-3A) oraz operacji wejścia-wyjścia. |
NfcB |
Zapewnia dostęp do właściwości NFC-B (ISO 14443-3B) oraz operacji wejścia-wyjścia. |
NfcF |
Zapewnia dostęp do właściwości NFC-F (JIS 6319-4) oraz operacji wejścia-wyjścia. |
NfcV |
Zapewnia dostęp do właściwości NFC-V (ISO 15693) oraz operacji wejścia-wyjścia. |
IsoDep |
Zapewnia dostęp do właściwości ISO-DEP (ISO 14443-4) oraz operacji wejścia-wyjścia. |
Ndef |
Zapewnia dostęp do danych NDEF i operacji na tagach NFC, które zostały sformatowane jako NDEF. |
NdefFormatable |
Udostępnia operacje formatowania tagów, które mogą być formatowane przez NDEF. |
Następujące technologie tagów nie muszą być obsługiwane przez urządzenia z systemem Android.
Kategoria | Opis |
---|---|
MifareClassic |
Zapewnia dostęp do właściwości MIFARE Classic oraz operacji wejścia-wyjścia, jeśli to urządzenie z Androidem obsługuje MIFARE. |
MifareUltralight |
Zapewnia dostęp do właściwości Ultralight MIFARE oraz operacji wejścia-wyjścia, jeśli to urządzenie z Androidem urządzenie obsługuje MIFARE. |
Praca z technologiami tagów i intencją ACTION_TECH_DISCOVERED
Jeśli urządzenie skanuje tag, który zawiera dane NDEF, ale nie udało się zamapować go na MIME lub identyfikator URI
system wysyłania tagów próbuje rozpocząć aktywność z użyciem tagu ACTION_TECH_DISCOVERED
intencji. ACTION_TECH_DISCOVERED
jest też używany, gdy tag
z danymi w formacie innym niż NDEF. Dzięki temu możesz pracować z danymi w tagu.
bezpośrednio, jeśli system wysyłania tagów nie mógł ich przeanalizować. Podstawowe kroki podczas pracy z
technologie tagów są następujące:
- Filtruj intencję
ACTION_TECH_DISCOVERED
określającą technologie tagów, które chcesz obsługiwać. Patrz Filtrowanie pod kątem komunikacji NFC . Ogólnie rzecz biorąc, system wysyłania tagów próbuje uruchomić intencjęACTION_TECH_DISCOVERED
, gdy komunikat NDEF. nie można zmapować na typ MIME lub identyfikator URI albo jeśli zeskanowany tag nie zawiera danych NDEF. Dla: (więcej informacji o sposobie jego wyliczania znajdziesz w artykule System wysyłki tagów). - Gdy aplikacja otrzyma intencję, pobierz obiekt
Tag
z: intencja:Kotlin
var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- Uzyskaj instancję
TagTechnology
, wywołując jeden zget
metody fabryczne klas w pakiecieandroid.nfc.tech
. Dostępne opcje wylicza obsługiwane technologie tagu, wywołując metodęgetTechList()
przed wywołaniem metody fabrycznejget
. Aby na przykład uzyskać instancjęMifareUltralight
zTag
, wykonaj te czynności:Kotlin
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
Java
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
Odczyt i zapis w tagach
Odczyt i zapis do tagu NFC polega na uzyskaniu go z intencji rozpoczęcie komunikacji z tagiem. Aby odczytywać i zapisywać dane, musisz zdefiniować własny stos protokołów do tagu. Pamiętaj jednak, że nadal możesz odczytywać i zapisywać dane NDEF podczas pracy bezpośrednio za pomocą tagu. To od Ciebie zależy, jak nadasz im strukturę. Poniższy przykład pokazuje, jak korzystać z tagu MIFARE Ultralight.
Kotlin
package com.example.android.nfc import android.nfc.Tag import android.nfc.tech.MifareUltralight import java.io.IOException import java.nio.charset.Charset class MifareUltralightTagTester { fun writeTag(tag: Tag, tagText: String) { MifareUltralight.get(tag)?.use { ultralight -> ultralight.connect() Charset.forName("US-ASCII").also { usAscii -> ultralight.writePage(4, "abcd".toByteArray(usAscii)) ultralight.writePage(5, "efgh".toByteArray(usAscii)) ultralight.writePage(6, "ijkl".toByteArray(usAscii)) ultralight.writePage(7, "mnop".toByteArray(usAscii)) } } } fun readTag(tag: Tag): String? { return MifareUltralight.get(tag)?.use { mifare -> mifare.connect() val payload = mifare.readPages(4) String(payload, Charset.forName("US-ASCII")) } } }
Java
package com.example.android.nfc; import android.nfc.Tag; import android.nfc.tech.MifareUltralight; import android.util.Log; import java.io.IOException; import java.nio.charset.Charset; public class MifareUltralightTagTester { private static final String TAG = MifareUltralightTagTester.class.getSimpleName(); public void writeTag(Tag tag, String tagText) { MifareUltralight ultralight = MifareUltralight.get(tag); try { ultralight.connect(); ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII"))); } catch (IOException e) { Log.e(TAG, "IOException while writing MifareUltralight...", e); } finally { try { ultralight.close(); } catch (IOException e) { Log.e(TAG, "IOException while closing MifareUltralight...", e); } } } public String readTag(Tag tag) { MifareUltralight mifare = MifareUltralight.get(tag); try { mifare.connect(); byte[] payload = mifare.readPages(4); return new String(payload, Charset.forName("US-ASCII")); } catch (IOException e) { Log.e(TAG, "IOException while reading MifareUltralight message...", e); } finally { if (mifare != null) { try { mifare.close(); } catch (IOException e) { Log.e(TAG, "Error closing tag...", e); } } } return null; } }
Użyj systemu dyspozytorskiego na pierwszym planie
System dyspozytorów na pierwszym planie umożliwia aktywności przechwytywanie intencji i roszczenia mają wyższy priorytet niż inne działania, które obsługują tę samą intencję. Korzystanie z tego systemu wiąże się i tworzą struktury danych, dzięki którym system Android będzie wysyłać odpowiednie do aplikacji. Aby włączyć system wysyłania na pierwszym planie:
- Dodaj ten kod w metodzie
onCreate()
w Twojej aktywności:- Utwórz zmienny obiekt
PendingIntent
, aby system Android mógł go wypełnić ze szczegółami tagu w momencie jego skanowania.Kotlin
val intent = Intent(this, javaClass).apply { addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) } var pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)
Java
PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE);
- Zadeklaruj filtry intencji do obsługi intencji, które chcesz przechwytywać. Na pierwszym planie
system wysyłania sprawdza określone filtry intencji z intencją, która jest odbierana,
urządzenie skanuje tag. Jeśli będzie pasować, aplikacja obsługuje intencję. Jeśli tak,
nie pasuje, system dyspozytorów na pierwszym planie powraca do systemu wysyłania intencji.
Określenie tablicy
null
filtrów intencji i filtrów technicznych, określa który chcesz odfiltrować pod kątem wszystkich tagów kreacji zastępczychTAG_DISCOVERED
intencji. Poniższy fragment kodu obsługuje wszystkie typy MIME w domenieNDEF_DISCOVERED
. Ty powinien obsługiwać tylko te, których potrzebujesz.Kotlin
val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply { try { addDataType("*/*") /* Handles all MIME based dispatches. You should specify only the ones that you need. */ } catch (e: IntentFilter.MalformedMimeTypeException) { throw RuntimeException("fail", e) } } intentFiltersArray = arrayOf(ndef)
Java
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndef.addDataType("*/*"); /* Handles all MIME based dispatches. You should specify only the ones that you need. */ } catch (MalformedMimeTypeException e) { throw new RuntimeException("fail", e); } intentFiltersArray = new IntentFilter[] {ndef, };
- Skonfiguruj tablicę technologii tagów, które aplikacja ma obsługiwać. Wywołaj funkcję
Object.class.getName()
, by uzyskać klasę technologii które chcesz wspierać.Kotlin
techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
Java
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
- Utwórz zmienny obiekt
- Zastąp poniższe wywołania zwrotne cyklu życia aktywności i dodaj funkcje logiczne, aby włączyć lub wyłączyć
wysyłanie pierwszego planu po utracie aktywności (
onPause()
) i odzyskuje (onResume()
) skupienie. Należy wywołać funkcjęenableForegroundDispatch()
z w wątku głównym i tylko wtedy, gdy aktywność jest na pierwszym planie (gwarantuje to wywołania w narzędziuonResume()
). Musisz też zaimplementować wywołanie zwrotneonNewIntent
, aby przetwarzać dane ze zeskanowanej komunikacji NFC. .
Kotlin
public override fun onPause() { super.onPause() adapter.disableForegroundDispatch(this) } public override fun onResume() { super.onResume() adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray) } public override fun onNewIntent(intent: Intent) { val tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG) // do something with tagFromIntent }
Java
public void onPause() { super.onPause(); adapter.disableForegroundDispatch(this); } public void onResume() { super.onResume(); adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray); } public void onNewIntent(Intent intent) { Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // do something with tagFromIntent }