نمای کلی NFC پیشرفته

این سند مباحث پیشرفته NFC را توصیف می کند ، مانند کار با فن آوری های مختلف برچسب ، نوشتن به برچسب های NFC و اعزام پیش زمینه ، که به یک برنامه در پیش زمینه اجازه می دهد تا حتی در مواردی که سایر برنامه ها برای همان موارد فیلتر می شوند ، اهداف را کنترل کنند.

با فناوری های برچسب پشتیبانی شده کار کنید

هنگام کار با برچسب های NFC و دستگاه های اندرویدی ، قالب اصلی که برای خواندن و نوشتن داده ها در برچسب ها استفاده می کنید NDEF است. هنگامی که یک دستگاه برچسب را با داده های NDEF اسکن می کند ، Android در تجزیه و تحلیل پیام پشتیبانی می کند و در صورت امکان آن را در NdefMessage تحویل می دهد. مواردی وجود دارد ، با این حال ، هنگامی که برچسب را اسکن می کنید که حاوی داده های NDEF نیست یا وقتی داده های NDEF نمی توانند به یک نوع MIME یا URI نقشه برداری شوند. در این موارد ، شما باید ارتباطات را مستقیماً با برچسب باز کنید و با پروتکل خود (در بایت های خام) برای آن بخوانید و بنویسید. Android با بسته android.nfc.tech ، که در جدول 1 شرح داده شده است ، پشتیبانی عمومی را برای این موارد استفاده ارائه می دهد. برای تعیین فن آوری های پشتیبانی شده توسط TAG می توانید از روش getTechList() استفاده کنید و با یکی از کلاسهای ارائه شده توسط android.nfc.tech شیء مربوط به TagTechnology را ایجاد کنید

جدول 1. فناوری های برچسب پشتیبانی شده

کلاس توضیحات
TagTechnology رابط کاربری که تمام کلاسهای فناوری برچسب باید پیاده سازی کنند.
NfcA دسترسی به خصوصیات NFC-A (ISO 14443-3A) و عملیات I/O را فراهم می کند.
NfcB دسترسی به خصوصیات NFC-B (ISO 14443-3B) و عملیات I/O را فراهم می کند.
NfcF دسترسی به خصوصیات NFC-F (JIS 6319-4) و عملیات I/O را فراهم می کند.
NfcV Provides access to NFC-V (ISO 15693) properties and I/O operations.
IsoDep Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations.
Ndef Provides access to NDEF data and operations on NFC tags that have been formatted as NDEF.
NdefFormatable Provides a format operations for tags that may be NDEF formattable.

The following tag technologies are not required to be supported by Android-powered devices.

جدول 2. فن آوری های تگ پشتیبانی شده اختیاری

کلاس توضیحات
MifareClassic Provides access to MIFARE Classic properties and I/O operations, if this Android device supports MIFARE.
MifareUltralight Provides access to MIFARE Ultralight properties and I/O operations, if this Android device supports MIFARE.

Work with tag technologies and the ACTION_TECH_DISCOVERED intent

هنگامی که یک دستگاه برچسب ای را که داده های NDEF را در آن قرار داده است ، اسکن می کند ، اما نمی توان آن را به یک MIME یا URI نقشه برداری کرد ، سیستم Dispatch Tag سعی می کند با هدف ACTION_TECH_DISCOVERED فعالیتی را آغاز کند. The ACTION_TECH_DISCOVERED is also used when a tag with non-NDEF data is scanned. Having this fallback allows you to work with the data on the tag directly if the tag dispatch system could not parse it for you. The basic steps when working with tag technologies are as follows:

  1. Filter for an ACTION_TECH_DISCOVERED intent specifying the tag technologies that you want to handle. See Filtering for NFC intents for more information. به طور کلی ، سیستم Dispatch TAG سعی می کند یک هدف ACTION_TECH_DISCOVERED را شروع کند که یک پیام NDEF نتواند به یک نوع MIME یا URI نقشه برداری شود ، یا اگر برچسب اسکن شده حاوی داده NDEF نبود. For more information on how this is determined, see The Tag Dispatch System .
  2. When your application receives the intent, obtain the Tag object from the intent:

    کاتلین

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

    جاوا

    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    
  3. Obtain an instance of a TagTechnology , by calling one of the get factory methods of the classes in the android.nfc.tech package. You can enumerate the supported technologies of the tag by calling getTechList() before calling a get factory method. For example, to obtain an instance of MifareUltralight from a Tag , do the following:

    کاتلین

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

    جاوا

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

خواندن و نوشتن در برچسب ها

Reading and writing to an NFC tag involves obtaining the tag from the intent and opening communication with the tag. You must define your own protocol stack to read and write data to the tag. Keep in mind, however, that you can still read and write NDEF data when working directly with a tag. It is up to you how you want to structure things. The following example shows how to work with a MIFARE Ultralight tag.

کاتلین

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"))
        }
    }
}

جاوا

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

از سیستم اعزام پیش زمینه استفاده کنید

The foreground dispatch system allows an activity to intercept an intent and claim priority over other activities that handle the same intent. استفاده از این سیستم شامل ساخت چند ساختار داده برای سیستم Android است تا بتواند اهداف مناسب را برای برنامه شما ارسال کند. برای فعال کردن سیستم اعزام پیش زمینه:

  1. Add the following code in the onCreate() method of your activity:
    1. Create a mutable PendingIntent object so the Android system can populate it with the details of the tag when it is scanned.

      کاتلین

      val intent = Intent(this, javaClass).apply {
          addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
      }
      var pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent,
              PendingIntent.FLAG_MUTABLE)
      

      جاوا

      PendingIntent pendingIntent = PendingIntent.getActivity(
          this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
          PendingIntent.FLAG_MUTABLE);
      
    2. Declare intent filters to handle the intents that you want to intercept. The foreground dispatch system checks the specified intent filters with the intent that is received when the device scans a tag. If it matches, then your application handles the intent. If it does not match, the foreground dispatch system falls back to the intent dispatch system. با مشخص کردن یک آرایه null از فیلترهای قصد و فیلترهای فناوری ، مشخص می کند که می خواهید برای همه برچسب هایی که به هدف TAG_DISCOVERED بازگردند ، فیلتر کنید. The code snippet below handles all MIME types for NDEF_DISCOVERED . شما فقط باید آنهایی را که نیاز دارید مدیریت کنید.

      کاتلین

      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)
      

      جاوا

      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. مجموعه ای از فن آوری های برچسب را که برنامه شما می خواهد انجام دهد تنظیم کنید. برای به دست آوردن کلاس فناوری که می خواهید از آن پشتیبانی کنید ، با روش Object.class.getName() تماس بگیرید.

      کاتلین

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

      جاوا

      techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
      
  2. در هنگام از دست دادن فعالیت ( onPause() ) و تمرکز مجدد ( onResume() ) ، به تماس های چرخه چرخه فعالیت زیر و منطقی اضافه کنید تا بتوانید اعزام پیش زمینه را فعال و غیرفعال کنید. enableForegroundDispatch() باید از موضوع اصلی فراخوانی کرد و فقط وقتی فعالیت در پیش زمینه باشد (فراخوانی در onResume() این را تضمین می کند). You also need to implement the onNewIntent callback to process the data from the scanned NFC tag.
  3. کاتلین

    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
    }
    

    جاوا

    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
    }