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

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

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

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

جدول 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 دسترسی به ویژگی های NFC-V (ISO 15693) و عملیات I/O را فراهم می کند.
IsoDep دسترسی به ویژگی های ISO-DEP (ISO 14443-4) و عملیات I/O را فراهم می کند.
Ndef دسترسی به داده های NDEF و عملیات روی برچسب های NFC که به صورت NDEF فرمت شده اند را فراهم می کند.
NdefFormatable عملیات قالب بندی را برای برچسب هایی که ممکن است قابل قالب بندی NDEF باشند ارائه می دهد.

فناوری‌های برچسب زیر نیازی به پشتیبانی دستگاه‌های مجهز به Android ندارند.

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

کلاس توضیحات
MifareClassic در صورتی که این دستگاه Android از MIFARE پشتیبانی کند، امکان دسترسی به ویژگی‌های MIFARE Classic و عملیات ورودی/خروجی را فراهم می‌کند.
MifareUltralight در صورتی که این دستگاه اندرویدی از MIFARE پشتیبانی کند، امکان دسترسی به ویژگی های MIFARE Ultralight و عملیات I/O را فراهم می کند.

با فناوری‌های برچسب و هدف ACTION_TECH_DISCOVERED کار کنید

وقتی دستگاهی برچسبی را اسکن می‌کند که داده‌های NDEF روی آن است، اما نمی‌توان آن را به یک MIME یا URI نگاشت، سیستم ارسال برچسب تلاش می‌کند تا فعالیتی را با هدف ACTION_TECH_DISCOVERED شروع کند. ACTION_TECH_DISCOVERED همچنین هنگامی که یک برچسب با داده های غیر NDEF اسکن می شود استفاده می شود. اگر سیستم ارسال برچسب نتواند آن را برای شما تجزیه کند، داشتن این بازگشت به شما امکان می دهد مستقیماً با داده های روی برچسب کار کنید. مراحل اساسی هنگام کار با فناوری های برچسب به شرح زیر است:

  1. فیلتر برای یک هدف ACTION_TECH_DISCOVERED که فناوری‌های برچسبی را که می‌خواهید مدیریت کنید مشخص می‌کند. برای اطلاعات بیشتر به فیلتر کردن اهداف NFC مراجعه کنید. به طور کلی، زمانی که یک پیام NDEF نمی تواند به یک نوع MIME یا URI نگاشت شود، یا اگر برچسب اسکن شده حاوی داده های NDEF نباشد، سیستم ارسال برچسب سعی می کند یک هدف ACTION_TECH_DISCOVERED را شروع کند. برای اطلاعات بیشتر در مورد چگونگی تعیین این، به سیستم ارسال برچسب مراجعه کنید.
  2. هنگامی که برنامه شما intent را دریافت کرد، شی Tag را از intent دریافت کنید:

    کاتلین

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

    جاوا

    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    
  3. با فراخوانی یکی از متدهای get کارخانه کلاس ها در بسته android.nfc.tech ، نمونه ای از TagTechnology را دریافت کنید. قبل از فراخوانی متد get factory می توانید فناوری های پشتیبانی شده تگ را با فراخوانی getTechList() برشمارید. به عنوان مثال، برای به دست آوردن یک نمونه از MifareUltralight از یک Tag ، موارد زیر را انجام دهید:

    کاتلین

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

    جاوا

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

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

خواندن و نوشتن در یک تگ NFC شامل به دست آوردن تگ از قصد و باز کردن ارتباط با تگ است. برای خواندن و نوشتن داده ها در تگ باید پشته پروتکل خود را تعریف کنید. با این حال، به خاطر داشته باشید که هنگام کار مستقیم با یک برچسب، همچنان می توانید داده های NDEF را بخوانید و بنویسید. این به شما بستگی دارد که چگونه می خواهید چیزها را ساختار دهید. مثال زیر نحوه کار با تگ MIFARE Ultralight را نشان می دهد.

کاتلین

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

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

سیستم ارسال پیش‌زمینه به یک فعالیت اجازه می‌دهد تا یک هدف را رهگیری کند و نسبت به سایر فعالیت‌هایی که همان هدف را مدیریت می‌کنند، اولویت داشته باشد. استفاده از این سیستم شامل ساخت چند ساختار داده برای سیستم اندروید است تا بتواند مقاصد مناسب را به برنامه شما ارسال کند. برای فعال کردن سیستم ارسال پیش زمینه:

  1. کد زیر را در متد onCreate() فعالیت خود اضافه کنید:
    1. یک شی PendingIntent قابل تغییر ایجاد کنید تا سیستم اندروید بتواند آن را با جزئیات برچسب در هنگام اسکن پر کند.

      کاتلین

      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. فیلترهای قصد را برای مدیریت مقاصدی که می خواهید رهگیری کنید، اعلام کنید. سیستم ارسال پیش زمینه فیلترهای هدف مشخص شده را با هدفی که هنگام اسکن یک برچسب دریافت می شود، بررسی می کند. اگر مطابقت داشته باشد، برنامه شما هدف را مدیریت می کند. اگر مطابقت نداشته باشد، سیستم اعزام پیش زمینه به سیستم اعزام قصد برمی گردد. با تعیین یک آرایه null از فیلترهای هدف و فیلترهای فناوری، مشخص می‌کند که می‌خواهید برای همه برچسب‌هایی که به قصد TAG_DISCOVERED بازگشتی دارند، فیلتر کنید. قطعه کد زیر همه انواع MIME را برای 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() این را تضمین می کند). همچنین برای پردازش داده‌ها از تگ NFC اسکن شده، نیاز به اجرای callback onNewIntent دارید.
  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
    }