Leser NFC-tagger med Android

Er du nysgjerrig på hva NFC er og hvordan det kan integreres i dine egne Android-applikasjoner? Denne opplæringen vil raskt presentere deg til emnet før du dykker inn og lærer deg hvordan du bygger en enkel NFC-leser-app!


Hva er NFC?

NFC er forkortelsen for Nær feltkommunikasjon. Det er den internasjonale standarden for kontaktløs datautveksling. I motsetning til et stort utvalg av andre teknologier, for eksempel trådløst LAN og Bluetooth, er maksimal avstand på to enheter 10cm. Utviklingen av standarden startet i 2002 av NXP Semiconductors og Sony. NFC Forum, et konsortium på over 170 selskaper og medlemmer, inkludert Mastercard, NXP, Nokia, Samsung, Intel og Google, har designet nye spesifikasjoner siden 2004.

Det finnes ulike muligheter for bruk av NFC med mobile enheter; for eksempel papirløse billetter, tilgangskontroller, kontantløse betalinger og bilnøkler. Ved hjelp av NFC-koder kan du styre telefonen og endre innstillinger. Data kan utveksles ved å holde to enheter ved siden av hverandre.

I denne veiledningen vil jeg forklare hvordan jeg implementerer NFC med Android SDK, hvilke fallgruver finnes, og hva du skal huske på. Vi vil opprette en app trinn for trinn, som kan lese innholdet av NFC-koder som støtter NDEF.


NFC Technologies

Det finnes en rekke NFC-koder som kan leses med en smarttelefon. Spekteret spenner fra enkle klistremerker og nøkkelringer til komplekse kort med integrert kryptografisk maskinvare. Merkene varierer også i deres chip teknologi. Det viktigste er NDEF, som støttes av de fleste tagger. I tillegg bør Mifare nevnes, da det er den mest brukte kontaktløse chipteknologien verden over. Noen koder kan leses og skrives, mens andre er skrivebeskyttet eller kryptert.

Bare NFC-datautvekslingsformatet (NDEF) er omtalt i denne opplæringen.


Legge til NFC-støtte i en app

Vi starter med et nytt prosjekt og en tom aktivitet. Det er viktig å velge en minimum SDK-versjon av nivå 10, fordi NFC bare støttes etter Android 2.3.3. Husk å velge ditt eget pakkenavn. Jeg har valgt net.vrallev.android.nfc.demo, fordi vrallev.net er domenet til nettstedet mitt og den andre delen refererer til temaet for denne applikasjonen.

 

Standardoppsettet generert av Eclipse er nesten tilstrekkelig for oss. Jeg har bare lagt til en ID i TextView og endret teksten.

 

For å få tilgang til NFC-maskinvaren må du søke om tillatelse i manifestet. Hvis appen ikke vil fungere uten NFC, kan du spesifisere tilstanden med brukerfunksjonstaggen. Hvis NFC er påkrevet, kan ikke appen installeres på enheter uten det, og Google Play viser kun appen din til brukere som eier en NFC-enhet.

  

MainActivity bør bare bestå av metoden onCreate (). Du kan kommunisere med maskinvaren via NfcAdapter-klassen. Det er viktig å finne ut om NfcAdapter er null. I dette tilfellet støtter ikke Android-enheten NFC.

 pakke net.vrallev.android.nfc.demo; importer android.app.Activity; importer android.nfc.nfcAdapter; importere android.os.Bundle; importer android.widget.TextView; importer android.widget.Toast; / ** * Aktivitet for å lese data fra en NDEF-tag. * * @author Ralf Wondratschek * * / offentlig klasse MainActivity utvider Aktivitet offentlig statisk endelig streng TAG = "NfcDemo"; privat tekstvisning mTextView; privat NfcAdapter mNfcAdapter; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); mTextView = (TextView) findViewById (R.id.textView_explanation); mNfcAdapter = NfcAdapter.getDefaultAdapter (dette); hvis (mNfcAdapter == null) // Stopp her, vi trenger absolutt NFC Toast.makeText (dette, "Denne enheten støtter ikke NFC.", Toast.LENGTH_LONG) .show (); bli ferdig(); komme tilbake;  hvis (! mNfcAdapter.isEnabled ()) mTextView.setText ("NFC er deaktivert.");  ellers mTextView.setText (R.string.explanation);  handleIntent (getIntent ());  privat tomt håndtakIntent (Intent Intent) // TODO: håndtere Intent

Hvis vi starter vår app nå, kan vi se teksten om NFC er aktivert eller deaktivert.

Slik filtrerer du for NFC-tagger

Vi har vår prøveapp, og ønsker å motta et varsel fra systemet når vi legger til en NFC-tag på enheten. Som vanlig bruker Android sitt Intent-system for å levere koder til appene. Hvis flere apper kan håndtere Intent, vises aktivitetsvelgeren og brukeren kan bestemme hvilken app som skal åpnes. Å åpne URL-adresser eller dele informasjon håndteres på samme måte.


NFC Intent Filter

Det er tre forskjellige filtre for koder:

  1. ACTION_NDEF_DISCOVERED
  2. ACTION_TECH_DISCOVERED
  3. ACTION_TAG_DISCOVERED

Listen er sortert fra høyeste til laveste prioritet.

Nå, hva skjer når en tag er festet til smarttelefonen? Hvis systemet registrerer en kode med NDEF-støtte, utløses en Intent. en ACTION_TECH_DISCOVERED Intent utløses hvis ingen aktivitet fra noen app er registrert for NDEF Intent, eller hvis taggen ikke støtter NDEF. Hvis det ikke finnes noen app for Intent, eller chip-teknologien ikke kunne oppdages, så a ACTION_TAG_DISCOVERED Intent er sparken. Følgende grafikk viser prosessen:


Sammendrag betyr dette at hver app må filtrere etter intensjonen med høyeste prioritet. I vårt tilfelle er dette NDEF Intent. Vi implementerer ACTION_TECH_DISCOVERED Intent først for å markere forskjellen mellom prioriteringer.


Tech Discovered Intent

Vi må spesifisere teknologien vi er interessert i. For dette formålet oppretter vi en undermappe som heter xml i res mappe. I denne mappen lager vi filen nfc_tech_filter.xml, der vi spesifiserer teknologiene.

    android.nfc.tech.Ndef    

Nå må vi opprette en IntentFilter i manifestet, og appen vil bli startet når vi legger til en tagg.

           

Hvis ingen annen app er registrert for denne hensikten, starter vår aktivitet umiddelbart. På enheten min er imidlertid andre apper installert, så aktivitetsvelgeren blir vist.



NDEF Discovered Intent

Som nevnt tidligere har Tech Discovered Intent nest høyeste prioritet. Siden vår app kun støtter NDEF, kan vi imidlertid bruke NDEF Discovered Intent, som har høyere prioritet. Vi kan slette teknologilisten igjen og erstatte IntentFilter med følgende.

     

Når vi fester merket nå, blir appen startet som før. Det er imidlertid en forskjell for meg. Aktivitetsvelgeren vises ikke, og appen starter umiddelbart, fordi NDEF Intent har høyere prioritet, og de andre appene er bare registrert for de lavere prioritetene. Det er akkurat det vi vil ha.


Forgrunnsforsendelse

Vær oppmerksom på at ett problem gjenstår. Når appen vår allerede er åpnet og vi legger taggen på nytt, åpnes appen en gang i stedet for å levere taggen direkte. Dette er ikke vår hensikt. Du kan omgå problemet ved å bruke en Forgrunnsforsendelse.

I stedet for at systemet har distribuert Intent, kan du registrere aktiviteten din for å motta taggen direkte. Dette er viktig for en bestemt arbeidsflyt, hvor det ikke gir mening å åpne en annen app.

Jeg har lagt inn forklaringene på de riktige stedene i koden.

 pakke net.vrallev.android.nfc.demo; importer android.app.Activity; importer android.app.PendingIntent; importer android.content.Intent; importer android.content.IntentFilter; importer android.content.IntentFilter.MalformedMimeTypeException; importer android.nfc.nfcAdapter; importere android.os.Bundle; importer android.widget.TextView; importer android.widget.Toast; / ** * Aktivitet for å lese data fra en NDEF-tag. * * @author Ralf Wondratschek * * / offentlig klasse MainActivity utvider Aktivitet offentlig statisk endelig streng MIME_TEXT_PLAIN = "text / plain"; offentlig statisk endelig streng TAG = "NfcDemo"; privat tekstvisning mTextView; privat NfcAdapter mNfcAdapter; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); mTextView = (TextView) findViewById (R.id.textView_explanation); mNfcAdapter = NfcAdapter.getDefaultAdapter (dette); hvis (mNfcAdapter == null) // Stopp her, vi trenger absolutt NFC Toast.makeText (dette, "Denne enheten støtter ikke NFC.", Toast.LENGTH_LONG) .show (); bli ferdig(); komme tilbake;  hvis (! mNfcAdapter.isEnabled ()) mTextView.setText ("NFC er deaktivert.");  ellers mTextView.setText (R.string.explanation);  handleIntent (getIntent ());  @Override protected void onResume () super.onResume (); / ** * Det er viktig at aktiviteten er i forgrunnen (gjenopptatt). Ellers kastes en ulovlig statuseksempel. * / setupForegroundDispatch (dette, mNfcAdapter);  @Override protected void onPause () / ** * Ring dette før påPause, ellers blir en UlovligArgumentException kastet også. * / stopForegroundDispatch (dette, mNfcAdapter); super.onPause ();  @Override protected void onNewIntent (Intent Intent) / ** * Denne metoden blir kalt, når en ny hensikt blir knyttet til gjeldende aktivitetseksempel. * I stedet for å opprette en ny aktivitet vil onNewIntent bli kalt. For mer informasjon se på dokumentasjonen. * * I vårt tilfelle blir denne metoden kalt når brukeren legger et tag til enheten. * / handleIntent (hensikt);  privat ugyldig håndtering (Intent intention) // TODO: handle Intent / ** * @param aktivitet Den tilsvarende @linkaktiviteten ber om forgrunnsforsendelsen. * @param-adapteren @link NfcAdapter brukt til forgrunnsforsendelsen. * / offentlig statisk tomgang setupForegroundDispatch (endelig aktivitetsaktivitet, NfcAdapter adapter) endelig Intent Intent = ny Intent (activity.getApplicationContext (), activity.getClass ()); intent.setFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP); endelig PendingIntent pendingIntent = PendingIntent.getActivity (activity.getApplicationContext (), 0, intent, 0); IntentFilter [] filters = new IntentFilter [1]; String [] [] techList = ny String [] [] ; // Merk at dette er det samme filteret som i vårt manifest. filtre [0] = ny IntentFilter (); filtre [0] .addAction (NfcAdapter.ACTION_NDEF_DISCOVERED); filtre [0] .addCategory (Intent.CATEGORY_DEFAULT); prøv filters [0] .addDataType (MIME_TEXT_PLAIN);  fangst (MalformedMimeTypeException e) Kast ny RuntimeException ("Sjekk din mime type.");  adapter.enableForegroundDispatch (aktivitet, ventendeIntent, filtre, techList);  / ** * @param aktivitet Den tilsvarende @link BaseActivity ber om å stoppe forgrunnsforsendelsen. * @param-adapteren @link NfcAdapter brukt til forgrunnsforsendelsen. * / offentlig statisk tomgangstoppForegroundDispatch (endelig aktivitetsaktivitet, NfcAdapter-adapter) adapter.disableForegroundDispatch (aktivitet); 

Nå, når du legger til en tagg og vår app allerede er åpnet, kalles onNewIntent og ingen ny aktivitet er opprettet.


Lese data fra en NDEF-tag

Det siste trinnet er å lese dataene fra taggen. Forklaringene er satt inn på de riktige stedene i koden igjen. NdefReaderTask er en privat indre klasse.

 pakke net.vrallev.android.nfc.demo; importer java.io.UnsupportedEncodingException; importer java.util.Arrays; importer android.app.Activity; importer android.app.PendingIntent; importer android.content.Intent; importer android.content.IntentFilter; importer android.content.IntentFilter.MalformedMimeTypeException; importer android.nfc.NdefMessage; importer android.nfc.NdefRecord; importer android.nfc.nfcAdapter; importer android.nfc.Tag; importer android.nfc.tech.Ndef; importer android.os.AsyncTask; importere android.os.Bundle; importer android.util.Log; importer android.widget.TextView; importer android.widget.Toast; / * * ... andre kodedeler * / private void handleIntent (Intent Intent) String action = intent.getAction (); hvis (NfcAdapter.ACTION_NDEF_DISCOVERED.equals (action)) String type = intent.getType (); hvis (MIME_TEXT_PLAIN.equals (type)) Tag tag = intent.getParcelableExtra (NfcAdapter.EXTRA_TAG); ny NdefReaderTask (). utfør (tag);  ellers Log.d (TAG, "Feil mime type:" + type);  annet hvis (NfcAdapter.ACTION_TECH_DISCOVERED.equals (action)) // Hvis vi fortsatt vil bruke Tech Discovered Intent Tag tag = intent.getParcelableExtra (NfcAdapter.EXTRA_TAG); String [] techList = tag.getTechList (); String søkteTech = Ndef.class.getName (); for (String tech: techList) if (searchedTech.equals (tech)) ny NdefReaderTask (). utføre (tag); gå i stykker; 
 / ** * Bakgrunnsoppgave for å lese dataene. Ikke blokkér UI-tråden mens du leser. * * @author Ralf Wondratschek * * / privat klasse NdefReaderTask utvider AsyncTask @Override protected String doInBackground (Tag ... params) Tag tag = params [0]; Ndef ndef = Ndef.get (tag); hvis (ndef == null) // NDEF støttes ikke av dette tagget. return null;  NdefMessage ndefMessage = ndef.getCachedNdefMessage (); NdefRecord [] records = ndefMessage.getRecords (); for (NdefRecord ndefRecord: records) hvis (ndefRecord.getTnf () == NdefRecord.TNF_WELL_KNOWN && Arrays.equals (ndefRecord.getType (), NdefRecord.RTD_TEXT)) prøv return readText (ndefRecord);  catch (UnsupportedEncodingException e) Log.e (TAG, "Unsupported Encoding", e);  returnere null;  Private String readText (NdefRecord record) kaster UnsupportedEncodingException / * * Se NFC forum spesifikasjon for "Text Record Type Definition" på 3.2.1 * * http://www.nfc-forum.org/specs/ * * bit_7 definerer koding * bit_6 reservert for fremtidig bruk, må være 0 * bit_5 ... 0 lengde av IANA språkkode * / byte [] nyttelast = record.getPayload (); // Få tekstkodingsstrengen textEncoding = ((nyttelast [0] & 128) == 0)? "UTF-8": "UTF-16"; // Få språkkoden int languageCodeLength = nyttelast [0] & 0063; // String languageCode = Ny String (nyttelast, 1, LanguageCodeLength, "US-ASCII"); // f.eks. "no" // Få teksten tilbake til ny streng (nyttelast, språkKodeLengde + 1, nyttelast.lengde - språkKodeLengde - 1, tekstEnkoding);  @Override protected void onPostExecute (Stringresultat) if (result! = Null) mTextView.setText ("Les innhold:" + resultat); 

Appen leser nå innholdet.



Nyttige Apps

For å sjekke om data leses og skrives riktig, bruker jeg personlig følgende apper:

  • NFC TagInfo av NFC Research Lab for lesing av data
  • TagInfo av NXP SEMICONDUCTORS for å lese data
  • TagWriter av NXP SEMICONDUCTORS for å skrive data

Konklusjon

I denne veiledningen har jeg vist deg hvordan dataene fra en NDEF-tag kan utvinnes. Du kan utvide eksemplet til andre mime typer og chip teknologier; en funksjon for å skrive data vil også være nyttig. Det første trinnet for å jobbe med NFC ble laget. Android SDK tilbyr imidlertid mye flere muligheter, for eksempel en enkel datautveksling (kalt Android Beam).

Hvis du vil ta Android-utviklingen ytterligere, sjekk ut det store spekteret av nyttige Android-appmaler på Envato Market. Eller ansett en Android-utvikler på Envato Studio.


om forfatteren

Ralf Wondratschek er en datavitenskapsstudent fra Tyskland. I tillegg til hans studier, jobber Ralf som freelancer innen mobil databehandling. I de siste årene har han jobbet med Java, XML, HTML, JSP, JSF, Eclipse, Google App Engine, og selvfølgelig Android. Han har utgitt to Android-apper til dags, som finnes her.

Du kan finne ut mer om forfatterens arbeid på sin hjemmeside vrallev.net.


kilder

http://www.nfc-forum.org/home/n-mark.jpg

http://commons.wikimedia.org/wiki/File%3A%C3%9Cberlagert.jpg

http://developer.android.com/images/nfc_tag_dispatch.png