Gelişmiş NFC'ye genel bakış

Bu dokümanda, çeşitli etiket teknolojileriyle çalışma, NFC etiketlerine yazma ve ön planda gönderme gibi gelişmiş NFC konuları açıklanmaktadır. Bu konu, diğer uygulamalar aynı niyetleri filtrelese bile ön plandaki bir uygulamanın amaçları işlemesine olanak tanır.

Desteklenen etiket teknolojileriyle çalışma

NFC etiketleri ve Android destekli cihazlarla çalışırken etiketlerde veri okumak ve yazmak için kullandığınız ana biçim NDEF'dir. Bir cihaz, NDEF verileri içeren bir etiketi taradığında, Android mümkün olduğunda mesajı ayrıştırma ve NdefMessage içinde iletme konusunda destek sağlar. Bununla birlikte, NDEF verisi içermeyen bir etiketi taradığınız veya NDEF verilerinin bir MIME türü veya URI'si ile eşlenemediği durumlar söz konusudur. Bu gibi durumlarda, doğrudan etiketle iletişimi açmanız ve kendi protokolünüzle (ham bayt cinsinden) okuyup yazmanız gerekir. Android, Tablo 1'de açıklanan android.nfc.tech paketi ile bu kullanım alanları için genel destek sağlar. Etiket tarafından desteklenen teknolojileri belirlemek ve android.nfc.tech tarafından sağlanan sınıflardan biriyle karşılık gelen TagTechnology nesnesini oluşturmak için getTechList() yöntemini kullanabilirsiniz

Tablo 1. Desteklenen etiket teknolojileri

Sınıf Açıklama
TagTechnology Tüm etiket teknolojisi sınıflarının uygulaması gereken arayüz.
NfcA NFC-A (ISO 14443-3A) özelliklerine ve G/Ç işlemlerine erişim sağlar.
NfcB NFC-B (ISO 14443-3B) özelliklerine ve G/Ç işlemlerine erişim sağlar.
NfcF NFC-F (JIS 6319-4) özelliklerine ve G/Ç işlemlerine erişim sağlar.
NfcV NFC-V (ISO 15693) özelliklerine ve G/Ç işlemlerine erişim sağlar.
IsoDep ISO-DEP (ISO 14443-4) özelliklerine ve G/Ç işlemlerine erişim sağlar.
Ndef NDEF verilerine ve NDEF olarak biçimlendirilmiş NFC etiketlerinde işlemlerine erişim sağlar.
NdefFormatable NDEF biçimlendirilebilir etiketler için biçim işlemleri sağlar.

Aşağıdaki etiket teknolojilerinin Android destekli cihazlar tarafından desteklenmesi gerekmez.

Tablo 2. Desteklenen isteğe bağlı etiket teknolojileri

Sınıf Açıklama
MifareClassic Bu Android cihaz MIFARE'ı destekliyorsa MIFARE Classic özelliklerine ve G/Ç işlemlerine erişim sağlar.
MifareUltralight Bu Android cihaz MIFARE'ı destekliyorsa MIFARE Ultralight özelliklerine ve G/Ç işlemlerine erişim sağlar.

Etiket teknolojileri ve ACTION_TECH_DISCOVERED amacı ile çalışın

Bir cihaz, NDEF verileri olan ancak MIME veya URI ile eşlenemeyen bir etiketi taradığında, etiket gönderme sistemi ACTION_TECH_DISCOVERED amacıyla bir etkinlik başlatmaya çalışır. ACTION_TECH_DISCOVERED, NDEF olmayan verilere sahip bir etiket tarandığında da kullanılır. Bu yedeğin olması, etiket gönderme sistemi etiketi sizin için ayrıştıramıyorsa etiketteki verilerle doğrudan çalışmanıza olanak tanır. Etiket teknolojileriyle çalışırken izlenecek temel adımlar şunlardır:

  1. İşlemek istediğiniz etiket teknolojilerini belirten bir ACTION_TECH_DISCOVERED niyetini filtreleyin. Daha fazla bilgi için NFC niyetlerine göre filtreleme konusuna bakın. Genel olarak, bir NDEF mesajı bir MIME türü veya URI'siyle eşlenemediğinde ya da taranan etiket NDEF verileri içermediğinde etiket gönderme sistemi, bir ACTION_TECH_DISCOVERED niyeti başlatmaya çalışır. Bunun nasıl belirlendiği hakkında daha fazla bilgi için Etiket Sevkiyatı Sistemi'ne bakın.
  2. Uygulamanız amacı aldığında, amaçtan Tag nesnesini edinin:

    Kotlin

    var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
    

    Java

    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    
  3. android.nfc.tech paketindeki sınıfların get fabrika yöntemlerinden birini çağırarak TagTechnology örneği elde edin. get fabrika yöntemini çağırmadan önce getTechList() yöntemini çağırarak etiketin desteklenen teknolojilerini numaralandırabilirsiniz. Örneğin, Tag öğesinden MifareUltralight örneği almak için şunu yapın:

    Kotlin

    MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
    

    Java

    MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
    

Etiketleri okuma ve etiketlere yazma

Bir NFC etiketini okuma ve yazma işlemleri, etiketin amaçtan alınmasını ve etiketle iletişimin açılmasını içerir. Etikete veri okumak ve yazmak için kendi protokol yığınınızı tanımlamanız gerekir. Bununla birlikte, bir etiketle doğrudan çalışırken NDEF verilerini okuyup yazabileceğinizi unutmayın. Öğeleri nasıl yapılandırmak istediğinize siz karar verirsiniz. Aşağıdaki örnek, MIFARE Ultralight etiketiyle nasıl çalışacağınızı gösterir.

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

Ön plan gönderme sistemini kullanma

Ön plan gönderme sistemi, bir etkinliğin amaca müdahale etmesine ve aynı amacı işleyen diğer etkinliklere göre öncelikli olmasını sağlar. Bu sistemi kullanmak, Android sisteminin uygulamanıza uygun amaçları gönderebilmesi için birkaç veri yapısı oluşturmayı içerir. Ön plan gönderme sistemini etkinleştirmek için:

  1. Etkinliğinizin onCreate() yöntemine aşağıdaki kodu ekleyin:
    1. Android sisteminin, etiket tarandığında etiketin ayrıntılarıyla doldurulması için değişken bir PendingIntent nesnesi oluşturun.

      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);
      
    2. Müdahale etmek istediğiniz niyetleri işlemek için intent filtreleri bildirin. Ön plan gönderme sistemi, belirtilen intent filtrelerini cihaz bir etiketi taradığında alınan amaçla kontrol eder. Eşleşirse uygulamanız amacı ele alır. Eşleşmezse ön plandaki dağıtım sistemi, intent dağıtım sistemine geri döner. null intent filtreleri ve teknoloji filtreleri dizisi belirtmek, TAG_DISCOVERED amacına yedek olan tüm etiketler için filtrelemek istediğinizi belirtir. Aşağıdaki kod snippet'i NDEF_DISCOVERED için tüm MIME türlerini işler. Yalnızca ihtiyacınız olanlarla ilgilenmeniz gerekir.

      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, };
      
    3. Uygulamanızın kullanmak istediği bir dizi etiket teknolojisi ayarlayın. Desteklemek istediğiniz teknoloji sınıfını edinmek için Object.class.getName() yöntemini çağırın.

      Kotlin

      techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
      

      Java

      techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
      
  2. Aşağıdaki etkinlik yaşam döngüsü geri çağırmalarını geçersiz kılın ve etkinlik kaybedildiğinde (onPause()) ve yeniden odaklandığında (onResume()) yeniden ön planda göndermeyi etkinleştirmek ve devre dışı bırakmak için mantık ekleyin. enableForegroundDispatch(), ana iş parçacığından ve yalnızca etkinlik ön plandayken çağrılmalıdır (onResume() ile çağırmak bunu garanti eder). Taranan NFC etiketindeki verileri işlemek için onNewIntent geri çağırmasını da uygulamanız gerekir.
  3. 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
    }