উন্নত NFC ওভারভিউ

এই ডকুমেন্টে NFC সংক্রান্ত উন্নত বিষয় বর্ণনা করা হয়েছে, যেমন বিভিন্ন ট্যাগ প্রযুক্তির সাথে কাজ করা, NFC ট্যাগে লেখা এবং ফোরগ্রাউন্ড ডিসপ্যাচিং, যা ফোরগ্রাউন্ডে থাকা কোনও অ্যাপ্লিকেশনকে ইনটেন্ট ম্যানেজ করার অনুমতি দেয়, এমনকি অন্যান্য অ্যাপ্লিকেশন একই ইনটেন্ট ফিল্টার করলেও।

মানানসই ট্যাগ প্রযুক্তির সাথে কাজ করা

NFC ট্যাগ এবং Android-চালিত ডিভাইসের সাথে কাজ করার সময়, ট্যাগে ডেটা পড়তে এবং লিখতে আপনি যে প্রধান ফর্ম্যাটটি ব্যবহার করেন তা হল NDEF। কোনও ডিভাইস NDEF ডেটা সহ ট্যাগ স্ক্যান করলে, Android মেসেজ পার্স করতে এবং সম্ভব হলে NdefMessage-এ ডেলিভার করতে সহায়তা প্রদান করে। তবে, এমন কিছু ঘটনা ঘটে যখন আপনি এমন কোনও ট্যাগ স্ক্যান করেন যাতে NDEF ডেটা থাকে না অথবা যখন NDEF ডেটা কোনও MIME-এর ধরন বা URI-তে ম্যাপ করা যায় না। এইসব ক্ষেত্রে, আপনাকে সরাসরি ট্যাগের সাথে যোগাযোগ করতে হবে এবং আপনার নিজস্ব প্রোটোকল (র বাইটে) ব্যবহার করে এতে পড়তে ও লিখতে হবে। Android এইসব ব্যবহারের ক্ষেত্রে android.nfc.tech প্যাকেজের মাধ্যমে সাধারণ সহায়তা প্রদান করে, যা সারণী ১-এ বর্ণনা করা হয়েছে। ট্যাগ দ্বারা সমর্থিত প্রযুক্তি নির্ধারণ করতে এবং android.nfc.tech দ্বারা প্রদত্ত ক্লাসগুলির একটির সাথে সংশ্লিষ্ট TagTechnology অবজেক্ট তৈরি করতে আপনি getTechList() পদ্ধতি ব্যবহার করতে পারেন

টেবিল ১. কাজ করে এমন ট্যাগ প্রযুক্তি

শ্রেণী বর্ণনা
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-চালিত ডিভাইসে নিম্নলিখিত ট্যাগ প্রযুক্তি কাজ করার প্রয়োজন নেই।

টেবিল ২. ঐচ্ছিক কাজ করে এমন ট্যাগ প্রযুক্তি

শ্রেণী বর্ণনা
MifareClassic এই Android ডিভাইসে MIFARE কাজ করলে, MIFARE Classic প্রপার্টি এবং I/O অপারেশনে অ্যাক্সেস প্রদান করে।
MifareUltralight এই Android ডিভাইসে MIFARE কাজ করলে, MIFARE Ultralight প্রপার্টি এবং I/O অপারেশনে অ্যাক্সেস প্রদান করে।

ট্যাগ টেকনোলজি ও ACTION_TECH_DISCOVERED ইনটেন্ট নিয়ে কাজ করা

কোনও ডিভাইস যখন এমন কোনও ট্যাগ স্ক্যান করে যাতে NDEF ডেটা আছে, কিন্তু MIME বা URI-তে ম্যাপ করা যায়নি, তখন ট্যাগ ডিসপ্যাচ সিস্টেম ACTION_TECH_DISCOVERED ইনটেন্ট সহ কোনও অ্যাক্টিভিটি শুরু করার চেষ্টা করে। এছাড়াও, NDEF-নয় এমন ডেটা সহ ট্যাগ স্ক্যান করা হলে ACTION_TECH_DISCOVERED ব্যবহার করা হয়। এই ফলব্যাক থাকলে, ট্যাগ ডিসপ্যাচ সিস্টেম আপনার জন্য এটি পার্স করতে না পারলে, আপনি সরাসরি ট্যাগের ডেটা নিয়ে কাজ করতে পারবেন। ট্যাগ প্রযুক্তির সাথে কাজ করার সময় প্রাথমিক ধাপগুলি নিচে দেওয়া হল:

  1. আপনি যে ট্যাগ প্রযুক্তি ম্যানেজ করতে চান তা উল্লেখ করে ACTION_TECH_DISCOVERED ইনটেন্টের জন্য ফিল্টার করুন। আরও তথ্যের জন্য NFC ইনটেন্টের জন্য ফিল্টার করা দেখুন। সাধারণত, ট্যাগ ডিসপ্যাচ সিস্টেম ACTION_TECH_DISCOVERED ইনটেন্ট শুরু করার চেষ্টা করে যখন NDEF মেসেজ MIME টাইপ বা URI-তে ম্যাপ করা যায় না অথবা স্ক্যান করা ট্যাগে NDEF ডেটা থাকে না। এটি কীভাবে নির্ধারণ করা হয় সেই সম্পর্কে আরও জানতে, ট্যাগ ডিসপ্যাচ সিস্টেম দেখুন।
  2. আপনার অ্যাপ্লিকেশন ইনটেন্ট পেলে, ইনটেন্ট থেকে Tag অবজেক্ট পান:

    Kotlin

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

    জাভা

    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
  3. android.nfc.tech প্যাকেজে ক্লাসের get ফ্যাক্টরি পদ্ধতির মধ্যে কোনও একটিকে কল করে TagTechnology-এর একটি ইনস্ট্যান্স পান। আপনি get ফ্যাক্টরি পদ্ধতি কল করার আগে getTechList() কল করে ট্যাগের কাজ করে এমন প্রযুক্তিগুলি গণনা করতে পারেন। যেমন, Tag থেকে MifareUltralight-এর ইনস্ট্যান্স পেতে, নিম্নলিখিত ধাপগুলি অনুসরণ করুন:

    Kotlin

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

    জাভা

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

ট্যাগ পড়া ও লেখা

NFC ট্যাগ রিড ও রাইট করার মধ্যে ইনটেন্ট থেকে ট্যাগ পাওয়া এবং ট্যাগের সাথে কমিউনিকেশন শুরু করা অন্তর্ভুক্ত। ট্যাগে ডেটা রিড ও রাইট করার জন্য আপনাকে নিজের প্রোটোকল স্ট্যাক নির্ধারণ করতে হবে। তবে মনে রাখবেন, সরাসরি কোনও ট্যাগের সাথে কাজ করার সময় আপনি এখনও NDEF ডেটা পড়তে ও লিখতে পারবেন। আপনি কীভাবে জিনিসগুলি সাজাতে চান তা আপনার উপর নির্ভর করে। 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"))
        }
    }
}

জাভা

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

ফোরগ্রাউন্ড ডিসপ্যাচ সিস্টেম ব্যবহার করুন

ফোরগ্রাউন্ড ডিসপ্যাচ সিস্টেম কোনও অ্যাক্টিভিটিকে একটি ইনটেন্ট ইন্টারসেপ্ট করতে এবং একই ইনটেন্ট ম্যানেজ করে এমন অন্যান্য অ্যাক্টিভিটির উপর অগ্রাধিকার দাবি করার অনুমতি দেয়। এই সিস্টেম ব্যবহার করার অর্থ হল Android সিস্টেমের জন্য কিছু ডেটা স্ট্রাকচার তৈরি করা যাতে আপনার অ্যাপ্লিকেশনে উপযুক্ত ইনটেন্ট পাঠানো যায়। ফোরগ্রাউন্ড ডিসপ্যাচ সিস্টেম চালু করতে:

  1. আপনার অ্যাক্টিভিটির onCreate() পদ্ধতিতে নিম্নলিখিত কোড যোগ করুন:
    1. একটি পরিবর্তনযোগ্য PendingIntent অবজেক্ট তৈরি করুন যাতে Android সিস্টেম স্ক্যান করার সময় ট্যাগের বিবরণ দিয়ে এটি পূরণ করতে পারে।

      Kotlin

      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 ইনটেন্টে ফলব্যাক করা সব ট্যাগ ফিল্টার করতে চান। নিচের কোড স্নিপেট NDEF_DISCOVERED-এর জন্য সব MIME টাইপ ম্যানেজ করে। আপনার প্রয়োজনীয় ইভেন্টগুলিই শুধু ম্যানেজ করা উচিত।

      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)

      জাভা

      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() মেথডকে কল করুন।

      Kotlin

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

      জাভা

      techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
  2. নিম্নলিখিত অ্যাক্টিভিটি লাইফসাইকেল কলব্যাক ওভাররাইড করুন এবং অ্যাক্টিভিটি ফোকাস হারালে (onPause()) এবং আবার ফোকাস ফিরে পেলে (onResume()) ফোরগ্রাউন্ড ডিসপ্যাচ চালু ও বন্ধ করার জন্য লজিক যোগ করুন। enableForegroundDispatch() অবশ্যই মূল থ্রেড থেকে কল করতে হবে এবং শুধুমাত্র তখনই যখন অ্যাক্টিভিটি ফোরগ্রাউন্ডে থাকে (onResume()-এ কল করা এটির গ্যারান্টি দেয়)। এছাড়াও, স্ক্যান করা NFC ট্যাগ থেকে ডেটা প্রসেস করার জন্য আপনাকে onNewIntent কলব্যাক প্রয়োগ করতে হবে।
  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
    }

    জাভা

    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
    }