W tym dokumencie opisano zaawansowane zagadnienia związane z NFC, takie jak praca z różnymi technologiami tagów, zapisywanie do tagów NFC oraz wysyłanie na pierwszym planie, które umożliwia aplikacji na pierwszym planie obsługę intencji nawet wtedy, gdy inne aplikacje odfiltrowują te same intencje.
Praca z obsługiwanymi technologiami tagów
W przypadku korzystania z tagów NFC i urządzeń z Androidem głównym formatem używanym do odczytywania i zapisywania danych w tagach jest NDEF. Gdy urządzenie skanuje tag z danymi NDEF, Android umożliwia przeanalizowanie komunikatu i dostarczenie go w elemencie NdefMessage
, gdy to możliwe. Zdarzają się jednak sytuacje, gdy skanujesz tag, który nie zawiera danych NDEF, lub gdy danych NDEF nie można zmapować na typ MIME lub identyfikator URI.
W takich przypadkach musisz nawiązać bezpośrednią komunikację z tagiem oraz odczytywać i zapisywać w nim dane za pomocą własnego protokołu (w nieprzetworzonych bajtach). Android zapewnia ogólną obsługę tych przypadków użycia w pakiecie android.nfc.tech
, który został opisany w tabeli 1. Możesz użyć metody getTechList()
, aby określić technologie obsługiwane przez tag i utworzyć odpowiedni obiekt TagTechnology
za pomocą jednej z klas dostępnych w android.nfc.tech
.
Kategoria | Opis |
---|---|
TagTechnology |
Interfejs, który muszą implementować wszystkie klasy technologii tagów. |
NfcA |
Zapewnia dostęp do właściwości NFC-A (ISO 14443-3A) i do operacji wejścia-wyjścia. |
NfcB |
Zapewnia dostęp do właściwości NFC-B (ISO 14443-3B) i operacji wejścia-wyjścia. |
NfcF |
Zapewnia dostęp do właściwości NFC-F (JIS 6319-4) i operacji wejścia-wyjścia. |
NfcV |
Zapewnia dostęp do właściwości NFC-V (ISO 15693) i operacji wejścia-wyjścia. |
IsoDep |
Zapewnia dostęp do właściwości ISO-DEP (ISO 14443-4) i operacji wejścia-wyjścia. |
Ndef |
Daje dostęp do danych i operacji NDEF na tagach NFC sformatowanych jako NDEF. |
NdefFormatable |
Udostępnia operacje formatowania tagów, które mogą być formatami NDEF. |
Urządzenia z Androidem nie muszą obsługiwać poniższych technologii tagów.
Kategoria | Opis |
---|---|
MifareClassic |
Daje dostęp do właściwości klasy MIFARE i operacji wejścia-wyjścia, jeśli to urządzenie z Androidem obsługuje MIFARE. |
MifareUltralight |
Daje dostęp do właściwości MIFARE Ultralight i operacji wejścia-wyjścia, jeśli to urządzenie z Androidem obsługuje MIFARE. |
Korzystanie z technologii tagów i intencji ACTION_TECH_DISCOVERED
Gdy urządzenie skanuje tag zawierający dane NDEF, ale nie udało się go zmapować na MIME lub identyfikator URI, system wysyłania tagów próbuje uruchomić działanie z intencją ACTION_TECH_DISCOVERED
. Parametr ACTION_TECH_DISCOVERED
jest też używany podczas skanowania tagu z danymi innymi niż NDEF. Użycie tej wartości zastępczej umożliwia pracę z danymi w tagu bezpośrednio, jeśli system wysyłania tagów nie mógł ich przeanalizować. Podstawowe kroki przy korzystaniu
z technologii tagów:
- Odfiltruj intencję
ACTION_TECH_DISCOVERED
, określając technologie tagów, które chcesz obsługiwać. Więcej informacji znajdziesz w sekcji Filtrowanie intencji NFC. Ogólnie rzecz biorąc, system wysyłania tagów próbuje uruchomić intencjęACTION_TECH_DISCOVERED
, gdy wiadomości NDEF nie można zmapować na typ MIME lub identyfikator URI albo gdy przeskanowany tag nie zawiera danych NDEF. Więcej informacji o sposobie tego określania znajdziesz w artykule System wysyłania tagów. - Gdy aplikacja otrzyma intencję, pobierz z niej obiekt
Tag
:Kotlin
var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- Uzyskaj instancję
TagTechnology
, wywołując jedną z metod fabrycznychget
klasy w pakiecieandroid.nfc.tech
. Możesz wyliczyć obsługiwane technologie tagu, wywołującgetTechList()
przed wywołaniem metody fabrycznejget
. Aby np. uzyskać wystąpienieMifareUltralight
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 w tagu NFC obejmują uzyskanie tagu z intencji i nawiązanie z nim komunikacji. Musisz zdefiniować własny stos protokołów, aby odczytywać i zapisywać dane w tagu. Pamiętaj jednak, że nadal możesz odczytywać i zapisywać dane NDEF, pracując bezpośrednio z tagiem. To zależy od Ciebie. 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; } }
Korzystanie z systemu wysyłania na pierwszym planie
System wysyłania na pierwszym planie umożliwia aktywności przechwytywanie intencji i priorytet żądania względem innych działań, które obsługują tę samą intencję. Wykorzystanie tego systemu wymaga zbudowania kilku struktur danych dla systemu Android, które będą mogły wysyłać odpowiednie intencje do Twojej aplikacji. Aby włączyć system wysyłania na pierwszym planie:
- Dodaj ten kod w metodzie
onCreate()
aktywności:- Utwórz zmienny obiekt
PendingIntent
, aby system Android mógł wypełniać go szczegółami tagu podczas 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, aby obsługiwać intencje, które chcesz przechwytywać. System wysyłania na pierwszym planie sprawdza określone filtry intencji pod kątem intencji otrzymanej, gdy urządzenie skanuje tag. Jeśli jest zgodny, aplikacja obsługuje intencję. Jeśli nie, system wysyłania na pierwszym planie wraca do systemu wysyłania intencji.
Jeśli określisz tablicę
null
w filtrach intencji i technologiach, chcesz odfiltrowywać wszystkie tagi, które odwołują się do intencjiTAG_DISCOVERED
. Poniższy fragment kodu obsługuje wszystkie typy MIME w domenieNDEF_DISCOVERED
. Używaj tylko tych, które są Ci potrzebne.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 ma obsługiwać Twoja aplikacja. Wywołaj metodę
Object.class.getName()
, aby uzyskać klasę technologii, którą chcesz obsługiwać.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 logikę, aby włączyć lub wyłączyć wysyłanie na pierwszym planie, gdy aktywność utraci (
onPause()
) i ponownie skoncentruje się (onResume()
). FunkcjęenableForegroundDispatch()
należy wywołać z wątku głównego i tylko wtedy, gdy aktywność działa na pierwszym planie (wywołanie w metodzieonResume()
jest gwarantowane). Aby przetworzyć dane ze zeskanowanego tagu NFC, musisz też zaimplementować wywołanie zwrotneonNewIntent
.
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 }