أساسيات تقنية NFC

يوضّح هذا المستند مهام NFC الأساسية التي تنفّذها في Android. توضّح هذه الصفحة كيفية إرسال بيانات NFC وتلقّيها في شكل رسائل NDEF، كما تصف واجهات برمجة التطبيقات لإطار عمل Android التي تتيح هذه الميزات. للاطّلاع على مواضيع أكثر تقدّمًا، بما في ذلك مناقشة حول التعامل مع البيانات غير المتوافقة مع تنسيق تبادل بيانات NFC، راجِع تقنية NFC المتقدّمة.

تتم معالجة قراءة بيانات NDEF من علامة NFC باستخدام نظام إرسال العلامات، الذي يحلّل علامات NFC التي تم رصدها ويصنّف البيانات بشكل مناسب ويبدأ تطبيقًا مهتمًا بالبيانات المصنّفة. يمكن لأي تطبيق يريد معالجة علامة NFC التي تم فحصها تحديد فلتر intent وطلب معالجة البيانات.

نظام إرسال العلامات

تبحث أجهزة Android عادةً عن علامات NFC عندما تكون الشاشة غير مقفلة، ما لم يتم إيقاف NFC في قائمة "الإعدادات" بالجهاز. عندما يعثر جهاز يعمل بنظام التشغيل Android على علامة NFC، يكون السلوك المطلوب هو أن يتعامل النشاط الأنسب مع الغرض بدون أن يُطلب من المستخدم تحديد التطبيق الذي يريد استخدامه. بما أنّ الأجهزة تفحص علامات NFC من مسافة قصيرة جدًا، من المحتمل أنّ مطالبة المستخدمين باختيار نشاط يدويًا ستجبرهم على إبعاد الجهاز عن العلامة وقطع الاتصال. عليك تطوير نشاطك للتعامل فقط مع علامات NFC التي يهتم بها نشاطك لمنع ظهور "أداة اختيار النشاط".

لمساعدتك في تحقيق هذا الهدف، يوفّر نظام Android نظامًا خاصًا لإرسال العلامات يحلّل علامات NFC التي تم فحصها ويوزّعها ويحاول تحديد التطبيقات المهتمة بالبيانات التي تم فحصها. ويتم ذلك من خلال:

  1. تحليل علامة NFC وتحديد نوع MIME أو معرّف الموارد المنتظم (URI) الذي يحدّد حمولة البيانات في العلامة
  2. تغليف نوع MIME أو معرّف الموارد المنتظم (URI) والحِمل في هدف تم توضيح هاتين الخطوتين الأوليَين في مقالة كيفية ربط علامات NFC بأنواع MIME ومعرّفات الموارد المنتظمة (URI).
  3. يبدأ نشاطًا استنادًا إلى الغرض. يتم توضيح ذلك في مقالة كيفية إرسال علامات NFC إلى التطبيقات.

كيفية ربط علامات NFC بأنواع MIME ومعرّفات الموارد الموحّدة (URI)

قبل البدء في كتابة تطبيقات NFC، من المهم فهم الأنواع المختلفة لعلامات NFC، وكيفية تحليل نظام إرسال العلامات لعلامات NFC، والعمل الخاص الذي يقوم به نظام إرسال العلامات عند رصد رسالة NDEF. تتوفّر علامات NFC في مجموعة كبيرة من التقنيات، ويمكن أيضًا كتابة البيانات إليها بطرق مختلفة. يتوافق نظام التشغيل Android مع معيار NDEF الذي يحدّده منتدى NFC.

يتم تغليف بيانات NDEF داخل رسالة (NdefMessage) تحتوي على سجل واحد أو أكثر (NdefRecord). ويجب أن يكون كل سجل NDEF منسقًا بشكل جيد وفقًا لمواصفات نوع السجل الذي تريد إنشاءه. يتيح نظام التشغيل Android أيضًا أنواعًا أخرى من العلامات التي لا تحتوي على بيانات NDEF، ويمكنك التعامل معها باستخدام الفئات في حزمة android.nfc.tech. لمزيد من المعلومات حول هذه التقنيات، اطّلِع على موضوع تقنية الاتصال القريب المدى المتقدّمة. يتطلّب استخدام هذه الأنواع الأخرى من العلامات كتابة حزمة البروتوكول الخاصة بك للتواصل مع العلامات، لذا ننصحك باستخدام تنسيق تبادل بيانات NFC (NDEF) عند الإمكان لتسهيل عملية التطوير وضمان التوافق مع أكبر عدد ممكن من الأجهزة التي تعمل بنظام التشغيل Android.

ملاحظة: لتنزيل مواصفات NDEF الكاملة، انتقِل إلى موقع مواصفات NFC Forum ومستندات التطبيقات واطّلِع على إنشاء أنواع شائعة من سجلات NDEF للحصول على أمثلة حول كيفية إنشاء سجلات NDEF.

بعد أن أصبحت لديك بعض المعلومات الأساسية عن علامات NFC، توضّح الأقسام التالية بمزيد من التفصيل كيفية تعامل نظام التشغيل Android مع العلامات المنسَّقة وفقًا لمعيار NDEF. عندما يقرأ جهاز يعمل بنظام التشغيل Android علامة NFC تحتوي على بيانات منسَّقة وفقًا لمعيار NDEF، يحلّل الجهاز الرسالة ويحاول تحديد نوع MIME للبيانات أو معرّف URI. ولإجراء ذلك، يقرأ النظام أول NdefRecord داخل NdefMessage لتحديد كيفية تفسير رسالة NDEF بأكملها (يمكن أن تتضمّن رسالة NDEF سجلات NDEF متعدّدة). في رسالة NDEF ذات التنسيق السليم، يحتوي أول NdefRecord على الحقول التالية:

تنسيق اسم النوع (TNF) المكوّن من 3 بتات
يشير إلى كيفية تفسير حقل نوع طول المتغير. يتم وصف القيم الصالحة في الجدول 1.
نوع الطول المتغيّر
تصف هذه السمة نوع السجلّ. في حال استخدام TNF_WELL_KNOWN، استخدِم هذا الحقل لتحديد تعريف نوع السجلّ (RTD). يتم توضيح قيم RTD الصالحة في الجدول 2.
المعرّف ذو الطول المتغيّر
معرّف فريد للسجلّ. لا يُستخدَم هذا الحقل كثيرًا، ولكن إذا كنت بحاجة إلى تحديد علامة بشكل فريد، يمكنك إنشاء رقم تعريف لها.
الحمولة ذات الطول المتغيّر
حمولة البيانات الفعلية التي تريد قراءتها أو كتابتها يمكن أن تحتوي رسالة NDEF على سجلات NDEF متعددة، لذا لا تفترض أنّ الحمولة الكاملة موجودة في سجل NDEF الأول من رسالة NDEF.

يستخدم نظام إرسال العلامات حقلَي TNF والنوع لمحاولة ربط نوع MIME أو معرّف موارد منتظم (URI) برسالة NDEF. في حال النجاح، يتم تغليف هذه المعلومات داخل هدف ACTION_NDEF_DISCOVERED مع حمولة البيانات الفعلية. ومع ذلك، هناك حالات لا يستطيع فيها نظام إرسال العلامات تحديد نوع البيانات استنادًا إلى سجلّ NDEF الأول. يحدث ذلك عندما يتعذّر ربط بيانات NDEF بنوع MIME أو معرّف URI، أو عندما لا تحتوي علامة NFC على بيانات NDEF في الأساس. في هذه الحالات، يتم تضمين عنصر Tag يحتوي على معلومات حول تقنيات العلامة والحِمل النافع داخل الغرض ACTION_TECH_DISCOVERED بدلاً من ذلك.

يوضّح الجدول 1 كيفية ربط نظام إرسال العلامات بحقلَي TNF والنوع بأنواع MIME أو معرّفات الموارد المنتظمة (URI). ويوضّح أيضًا أنواع NFC التي لا يمكن ربطها بنوع MIME أو معرّف URI. في هذه الحالات، يعود نظام إرسال العلامات إلى ACTION_TECH_DISCOVERED.

على سبيل المثال، إذا صادف نظام إرسال العلامات سجلاً من النوع TNF_ABSOLUTE_URI، سيتم ربط حقل نوع الطول المتغير الخاص بهذا السجل بمعرّف موارد منتظم (URI). يغلّف نظام إرسال العلامات معرّف الموارد المنتظم (URI) هذا في حقل البيانات الخاص بغرض ACTION_NDEF_DISCOVERED مع معلومات أخرى عن العلامة، مثل الحمولة. من ناحية أخرى، إذا صادف سجلّاً من النوع TNF_UNKNOWN، سينشئ غرضًا يغلف تكنولوجيات العلامة بدلاً من ذلك.

الجدول 1. التنسيقات المتوافقة من TNFs وعمليات الربط بينها

تنسيق اسم النوع (TNF) الربط
TNF_ABSOLUTE_URI عنوان URI استنادًا إلى حقل النوع
TNF_EMPTY الرجوع إلى ACTION_TECH_DISCOVERED
TNF_EXTERNAL_TYPE عنوان URI يستند إلى URN في حقل النوع يتم ترميز URN في حقل نوع NDEF في شكل مختصر: <domain_name>:<service_name>. يُجري نظام التشغيل Android عملية الربط هذه بمعرّف موارد منتظم (URI) بالتنسيق التالي: vnd.android.nfc://ext/<domain_name>:<service_name>.
TNF_MIME_MEDIA نوع MIME استنادًا إلى حقل النوع
TNF_UNCHANGED غير صالح في السجلّ الأول، لذا يتم الرجوع إلى ACTION_TECH_DISCOVERED.
TNF_UNKNOWN الرجوع إلى ACTION_TECH_DISCOVERED
TNF_WELL_KNOWN نوع MIME أو معرّف الموارد المنتظم (URI) استنادًا إلى تعريف نوع السجلّ (RTD)، والذي تحدّده في حقل النوع اطّلِع على الجدول 2 للحصول على مزيد من المعلومات حول أنواع البيانات في الوقت الفعلي المتاحة وعمليات الربط الخاصة بها.

الجدول 2. أنواع السجلات المتوافقة مع TNF_WELL_KNOWN وعمليات الربط الخاصة بها

تعريف نوع السجلّ (RTD) الربط
RTD_ALTERNATIVE_CARRIER الرجوع إلى ACTION_TECH_DISCOVERED
RTD_HANDOVER_CARRIER الرجوع إلى ACTION_TECH_DISCOVERED
RTD_HANDOVER_REQUEST الرجوع إلى ACTION_TECH_DISCOVERED
RTD_HANDOVER_SELECT الرجوع إلى ACTION_TECH_DISCOVERED
RTD_SMART_POSTER عنوان URI استنادًا إلى تحليل الحمولة
RTD_TEXT نوع MIME الخاص بـ text/plain.
RTD_URI عنوان URI يستند إلى الحمولة.

كيفية إرسال علامات NFC إلى التطبيقات

عندما ينتهي نظام إرسال العلامات من إنشاء هدف يغلّف علامة NFC ومعلوماتها التعريفية، يرسل الهدف إلى تطبيق مهتم يفلتر الهدف. إذا كان بإمكان أكثر من تطبيق معالجة الغرض، سيتم عرض "أداة اختيار التطبيقات" ليتمكّن المستخدم من اختيار النشاط. يحدّد نظام إرسال العلامات ثلاث نوايا، وهي مُدرَجة بالترتيب من الأعلى إلى الأدنى أولوية:

  1. ACTION_NDEF_DISCOVERED: يتم استخدام هذا الغرض لبدء نشاط عند فحص علامة تحتوي على حمولة NDEF ومن نوع معروف. هذه هي نية الأولوية القصوى، ويحاول نظام إرسال العلامات بدء نشاط بهذه النية قبل أي نية أخرى، كلما أمكن ذلك.

    ملاحظة: بدءًا من Android 16، سيؤدي فحص علامات NFC التي تخزّن روابط عناوين URL (أي أنّ مخطط URI هو "https://" أو "http://") إلى تشغيل الغرض ACTION_VIEW بدلاً من الغرض ACTION_NDEF_DISCOVERED.

  2. ACTION_TECH_DISCOVERED: إذا لم يتم تسجيل أي أنشطة للتعامل مع الغرض ACTION_NDEF_DISCOVERED، يحاول نظام إرسال العلامات بدء تطبيق بهذا الغرض. يتم أيضًا بدء هذا الغرض مباشرةً (بدون بدء ACTION_NDEF_DISCOVERED أولاً) إذا كانت العلامة التي يتم فحصها تحتوي على بيانات NDEF لا يمكن ربطها بنوع MIME أو معرّف URI، أو إذا كانت العلامة لا تحتوي على بيانات NDEF ولكنها تستخدم تكنولوجيا علامات معروفة.
  3. ACTION_TAG_DISCOVERED: يتم بدء هذا الغرض إذا لم تعالج أي أنشطة الأغراض ACTION_NDEF_DISCOVERED أو ACTION_TECH_DISCOVERED.

في ما يلي الطريقة الأساسية التي يعمل بها نظام إرسال العلامات:

  1. حاوِل بدء نشاط باستخدام الغرض الذي أنشأه نظام إرسال العلامات عند تحليل علامة NFC (إما ACTION_NDEF_DISCOVERED أو ACTION_TECH_DISCOVERED).
  2. إذا لم يتم فلترة أي أنشطة حسب هذه النية، حاوِل بدء نشاط باستخدام النية ذات الأولوية الأقل التالية (إما ACTION_TECH_DISCOVERED أو ACTION_TAG_DISCOVERED) إلى أن يتم فلترة تطبيق حسب النية أو إلى أن يحاول نظام إرسال العلامات استخدام جميع النوايا الممكنة.
  3. إذا لم يتم فلترة أي تطبيقات لأي من الأهداف، لا تفعل شيئًا.
الشكل 1. نظام إرسال العلامات

استخدِم رسائل NDEF وintent ACTION_NDEF_DISCOVERED كلما أمكن ذلك، لأنّها الأكثر تحديدًا من بين الثلاثة. يتيح لك هذا الغرض بدء تطبيقك في وقت أكثر ملاءمة من الغرضَين الآخرَين، ما يمنح المستخدم تجربة أفضل.

طلب إذن الوصول إلى NFC في ملف بيان Android

قبل أن تتمكّن من الوصول إلى أجهزة NFC والتعامل بشكل صحيح مع أغراض NFC، عليك تعريف العناصر التالية في ملف AndroidManifest.xml:

  • عنصر NFC <uses-permission> للوصول إلى أجهزة NFC:
    <uses-permission android:name="android.permission.NFC" />
  • الحد الأدنى لإصدار حزمة تطوير البرامج (SDK) الذي يمكن أن يدعمه تطبيقك يتيح المستوى 9 من واجهة برمجة التطبيقات إرسال العلامات بشكل محدود من خلال ACTION_TAG_DISCOVERED، كما يتيح الوصول إلى رسائل NDEF من خلال الإضافة EXTRA_NDEF_MESSAGES فقط. ولا يمكن الوصول إلى أي خصائص أخرى للعلامة أو عمليات إدخال/إخراج. يتضمّن المستوى 10 لواجهة برمجة التطبيقات توافقًا شاملاً مع القراءة والكتابة، بالإضافة إلى إمكانية إرسال بيانات NDEF في المقدّمة، ويتيح المستوى 14 لواجهة برمجة التطبيقات طُرقًا إضافية سهلة الاستخدام لإنشاء سجلات NDEF.
    <uses-sdk android:minSdkVersion="10"/>
  • عنصر uses-feature لكي يظهر تطبيقك على Google Play فقط للأجهزة التي تتضمّن أجهزة NFC:
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

    إذا كان تطبيقك يستخدم وظيفة NFC، ولكنّ هذه الوظيفة ليست ضرورية لتطبيقك، يمكنك حذف العنصر uses-feature والتحقّق من توفّر NFC في وقت التشغيل من خلال التحقّق مما إذا كان getDefaultAdapter() هو null.

فلترة أغراض NFC

لبدء تطبيقك عند مسح علامة NFC ضوئيًا تريد معالجتها، يمكن لتطبيقك فلترة هدف واحد أو هدفَين أو جميع أهداف NFC الثلاثة في بيان Android. ومع ذلك، من المفيد عادةً فلترة ACTION_NDEF_DISCOVERED لكي تتمكّن من التحكّم بشكل أكبر في وقت بدء تطبيقك. الهدف ACTION_TECH_DISCOVERED هو خيار احتياطي للهدف ACTION_NDEF_DISCOVERED عندما لا يتوفّر فلتر للتطبيقات في ACTION_NDEF_DISCOVERED أو عندما لا تكون الحمولة بتنسيق NDEF. عادةً ما تكون الفلترة حسب ACTION_TAG_DISCOVERED فئة عامة جدًا لا يمكن الفلترة حسبها. ستعمل العديد من التطبيقات على فلترة ACTION_NDEF_DISCOVERED أو ACTION_TECH_DISCOVERED قبل ACTION_TAG_DISCOVERED، لذا فإنّ تطبيقك لديه احتمال ضئيل للبدء. لا يتوفّر ACTION_TAG_DISCOVERED إلا كحلّ أخير للتطبيقات التي تريد فلترة الحالات التي لم يتم فيها تثبيت أي تطبيقات أخرى للتعامل مع الغرض ACTION_NDEF_DISCOVERED أو ACTION_TECH_DISCOVERED.

وبما أنّ عمليات نشر علامات NFC تختلف ولا يمكنك التحكّم فيها في كثير من الأحيان، لا يكون ذلك ممكنًا دائمًا، ولهذا السبب يمكنك الرجوع إلى الغرضَين الآخرَين عند الضرورة. عندما يكون لديك إذن بالتحكّم في أنواع العلامات والبيانات المكتوبة، ننصحك باستخدام NDEF لتنسيق علاماتك. توضّح الأقسام التالية كيفية الفلترة حسب كل نوع من أنواع النية.

ACTION_NDEF_DISCOVERED

للفلترة حسب أغراض ACTION_NDEF_DISCOVERED، عليك تعريف فلتر الأغراض مع نوع البيانات التي تريد الفلترة حسبها. يتم في المثال التالي فلترة طلبات ACTION_NDEF_DISCOVERED التي لها نوع MIME هو text/plain:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:mimeType="text/plain" />
</intent-filter>

يقدّم المثال التالي فلترة لمعرّف URI بالتنسيق https://developer.android.com/index.html.

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT"/>
   <data android:scheme="https"
              android:host="developer.android.com"
              android:pathPrefix="/index.html" />
</intent-filter>

ACTION_TECH_DISCOVERED

إذا كانت فلاتر الأنشطة الخاصة بك مخصّصة للغرض ACTION_TECH_DISCOVERED، عليك إنشاء ملف موارد XML يحدّد التقنيات التي يدعمها نشاطك ضمن مجموعة tech-list. يُعدّ نشاطك مطابقًا إذا كانت مجموعة tech-list مجموعة فرعية من التقنيات التي تتوافق مع العلامة، ويمكنك الحصول عليها من خلال طلب getTechList().

على سبيل المثال، إذا كانت العلامة التي يتم فحصها تتوافق مع MifareClassic وNdefFormatable وNfcA، يجب أن تحدّد مجموعة tech-list جميع التقنيات الثلاث أو اثنتين أو واحدة منها (ولا شيء آخر) حتى يتم مطابقة نشاطك.

يحدّد النموذج التالي جميع التقنيات. يجب إزالة تلك التي لا تتوافق مع علامة NFC. احفظ هذا الملف (يمكنك اختيار أي اسم له) في المجلد <project-root>/res/xml.

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.NfcF</tech>
        <tech>android.nfc.tech.NfcV</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

يمكنك أيضًا تحديد مجموعات tech-list متعددة. يتم التعامل مع كل مجموعة من المجموعات tech-list بشكل مستقل، ويتم اعتبار نشاطك مطابقًا إذا كانت أي مجموعة tech-list واحدة هي مجموعة فرعية من التقنيات التي تعرضها getTechList(). ويوفّر ذلك دلالات AND وOR لتقنيات المطابقة. يتطابق المثال التالي مع العلامات التي يمكنها توفير دعم لتقنيتَي NfcA وNdef أو تقنيتَي NfcB وNdef:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.Ndef</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.Ndef</tech>
    </tech-list>
</resources>

في ملف AndroidManifest.xml، حدِّد ملف الموارد الذي أنشأته للتو في العنصر <meta-data> داخل العنصر <activity> كما في المثال التالي:

<activity>
...
<intent-filter>
    <action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>

<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
    android:resource="@xml/nfc_tech_filter" />
...
</activity>

لمزيد من المعلومات حول استخدام تقنيات العلامات والغرض ACTION_TECH_DISCOVERED، راجِع استخدام تقنيات العلامات المتوافقة في مستند "تقنية NFC المتقدّمة".

ACTION_TAG_DISCOVERED

للفلترة حسب ACTION_TAG_DISCOVERED، استخدِم فلتر الأهداف التالي:

<intent-filter>
    <action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>

ACTION_VIEW

اعتبارًا من Android 16، سيؤدي مسح علامات NFC التي تخزّن روابط عناوين URL إلى تشغيل الغرض ACTION_VIEW. للفلترة حسب ACTION_VIEW، يُرجى الرجوع إلى this. استخدِم Android app links لفتح تطبيقك لعنوان URL.

الحصول على معلومات من الأهداف

إذا بدأ نشاط بسبب عنصر intent خاص بتكنولوجيا NFC، يمكنك الحصول على معلومات حول علامة NFC التي تم مسحها ضوئيًا من عنصر intent. يمكن أن تحتوي الأهداف على الإضافات التالية استنادًا إلى العلامة التي تم فحصها ضوئيًا:

  • EXTRA_TAG (مطلوب): عنصر Tag يمثّل العلامة الممسوحة ضوئيًا.
  • EXTRA_NDEF_MESSAGES (اختياري): مصفوفة من رسائل NDEF تم تحليلها من العلامة. هذه البيانات الإضافية إلزامية في طلبات ACTION_NDEF_DISCOVERED.
  • EXTRA_ID (اختياري): المعرّف المنخفض المستوى للعلامة.

للحصول على هذه البيانات الإضافية، تحقَّق مما إذا كان نشاطك قد تم إطلاقه باستخدام إحدى نوايا NFC للتأكّد من أنّه تم فحص علامة، ثم احصل على البيانات الإضافية من النية. يتحقّق المثال التالي من intent ACTION_NDEF_DISCOVERED ويحصل على رسائل NDEF من intent إضافي.

Kotlin

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    ...
    if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) {
        intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMessages ->
            val messages: List<NdefMessage> = rawMessages.map { it as NdefMessage }
            // Process the messages array.
            ...
        }
    }
}

Java

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    ...
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
        Parcelable[] rawMessages =
            intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMessages != null) {
            NdefMessage[] messages = new NdefMessage[rawMessages.length];
            for (int i = 0; i < rawMessages.length; i++) {
                messages[i] = (NdefMessage) rawMessages[i];
            }
            // Process the messages array.
            ...
        }
    }
}

بدلاً من ذلك، يمكنك الحصول على عنصر Tag من الغرض، والذي سيحتوي على الحمولة ويسمح لك بتعداد تقنيات العلامة:

Kotlin

val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)

Java

Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

إنشاء أنواع شائعة من سجلات NDEF

يوضّح هذا القسم كيفية إنشاء أنواع شائعة من سجلات NDEF لمساعدتك عند الكتابة إلى علامات NFC. بدءًا من الإصدار 4.0 من نظام التشغيل Android (المستوى 14 من واجهة برمجة التطبيقات)، تتوفّر الطريقة createUri() لمساعدتك في إنشاء سجلّات URI تلقائيًا. بدءًا من الإصدار 4.1 من نظام التشغيل Android (المستوى 16 من واجهة برمجة التطبيقات)، تتوفّر السمتان createExternal() وcreateMime() لمساعدتك في إنشاء سجلات NDEF من نوع MIME وخارجية. استخدِم طرق المساعدة هذه كلما أمكن لتجنُّب الأخطاء عند إنشاء سجلات NDEF يدويًا.

يوضّح هذا القسم أيضًا كيفية إنشاء فلتر الأهداف ذي الصلة بالسجلّ. يجب أن تكون جميع أمثلة سجلّات NDEF هذه في سجلّ NDEF الأول ضمن رسالة NDEF التي تكتبها على علامة.

TNF_ABSOLUTE_URI

ملاحظة: ننصحك باستخدام النوع RTD_URI بدلاً من TNF_ABSOLUTE_URI لأنّه أكثر فعالية.

يمكنك إنشاء سجلّ TNF_ABSOLUTE_URI NDEF بالطريقة التالية :

Kotlin

val uriRecord = ByteArray(0).let { emptyByteArray ->
    NdefRecord(
            TNF_ABSOLUTE_URI,
            "https://developer.android.com/index.html".toByteArray(Charset.forName("US-ASCII")),
            emptyByteArray,
            emptyByteArray
    )
}

Java

NdefRecord uriRecord = new NdefRecord(
    NdefRecord.TNF_ABSOLUTE_URI ,
    "https://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")),
    new byte[0], new byte[0]);

سيبدو فلتر الأهداف لسجلّ NDEF السابق على النحو التالي:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="https"
        android:host="developer.android.com"
        android:pathPrefix="/index.html" />
</intent-filter>

TNF_MIME_MEDIA

يمكنك إنشاء TNF_MIME_MEDIA سجلّ NDEF بالطرق التالية:

باستخدام طريقة createMime():

Kotlin

val mimeRecord = NdefRecord.createMime(
        "application/vnd.com.example.android.beam",
        "Beam me up, Android".toByteArray(Charset.forName("US-ASCII"))
)

Java

NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam",
    "Beam me up, Android".getBytes(Charset.forName("US-ASCII")));

إنشاء NdefRecord يدويًا:

Kotlin

val mimeRecord = Charset.forName("US-ASCII").let { usAscii ->
    NdefRecord(
            NdefRecord.TNF_MIME_MEDIA,
            "application/vnd.com.example.android.beam".toByteArray(usAscii),
            ByteArray(0),
            "Beam me up, Android!".toByteArray(usAscii)
    )
}

Java

NdefRecord mimeRecord = new NdefRecord(
    NdefRecord.TNF_MIME_MEDIA ,
    "application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")),
    new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));

سيبدو فلتر الأهداف لسجلّ NDEF السابق على النحو التالي:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="application/vnd.com.example.android.beam" />
</intent-filter>

TNF_WELL_KNOWN مع RTD_TEXT

يمكنك إنشاء سجلّ TNF_WELL_KNOWN NDEF بالطريقة التالية:

Kotlin

fun createTextRecord(payload: String, locale: Locale, encodeInUtf8: Boolean): NdefRecord {
    val langBytes = locale.language.toByteArray(Charset.forName("US-ASCII"))
    val utfEncoding = if (encodeInUtf8) Charset.forName("UTF-8") else Charset.forName("UTF-16")
    val textBytes = payload.toByteArray(utfEncoding)
    val utfBit: Int = if (encodeInUtf8) 0 else 1 shl 7
    val status = (utfBit + langBytes.size).toChar()
    val data = ByteArray(1 + langBytes.size + textBytes.size)
    data[0] = status.toByte()
    System.arraycopy(langBytes, 0, data, 1, langBytes.size)
    System.arraycopy(textBytes, 0, data, 1 + langBytes.size, textBytes.size)
    return NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, ByteArray(0), data)
}

Java

public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) {
    byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
    Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
    byte[] textBytes = payload.getBytes(utfEncoding);
    int utfBit = encodeInUtf8 ? 0 : (1 << 7);
    char status = (char) (utfBit + langBytes.length);
    byte[] data = new byte[1 + langBytes.length + textBytes.length];
    data[0] = (byte) status;
    System.arraycopy(langBytes, 0, data, 1, langBytes.length);
    System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
    NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
    NdefRecord.RTD_TEXT, new byte[0], data);
    return record;
}

سيبدو فلتر الأهداف لسجلّ NDEF السابق على النحو التالي:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="text/plain" />
</intent-filter>

TNF_WELL_KNOWN مع RTD_URI

يمكنك إنشاء TNF_WELL_KNOWN سجلّ NDEF بالطرق التالية:

باستخدام طريقة createUri(String):

Kotlin

val rtdUriRecord1 = NdefRecord.createUri("https://example.com")

Java

NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");

باستخدام طريقة createUri(Uri):

Kotlin

val rtdUriRecord2 = Uri.parse("https://example.com").let { uri ->
    NdefRecord.createUri(uri)
}

Java

Uri uri = Uri.parse("https://example.com");
NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);

إنشاء NdefRecord يدويًا:

Kotlin

val uriField = "example.com".toByteArray(Charset.forName("US-ASCII"))
val payload = ByteArray(uriField.size + 1)                   //add 1 for the URI Prefix
payload [0] = 0x01                                           //prefixes https://www. to the URI
System.arraycopy(uriField, 0, payload, 1, uriField.size)     //appends URI to payload
val rtdUriRecord = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, ByteArray(0), payload)

Java

byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII"));
byte[] payload = new byte[uriField.length + 1];              //add 1 for the URI Prefix
payload[0] = 0x01;                                           //prefixes https://www. to the URI
System.arraycopy(uriField, 0, payload, 1, uriField.length);  //appends URI to payload
NdefRecord rtdUriRecord = new NdefRecord(
    NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);

سيبدو فلتر الأهداف لسجلّ NDEF السابق على النحو التالي:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="https"
        android:host="example.com"
        android:pathPrefix="" />
</intent-filter>

TNF_EXTERNAL_TYPE

يمكنك إنشاء سجلّ TNF_EXTERNAL_TYPE NDEF بالطرق التالية:

باستخدام طريقة createExternal():

Kotlin

var payload: ByteArray //assign to your data
val domain = "com.example" //usually your app's package name
val type = "externalType"
val extRecord = NdefRecord.createExternal(domain, type, payload)

Java

byte[] payload; //assign to your data
String domain = "com.example"; //usually your app's package name
String type = "externalType";
NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);

إنشاء NdefRecord يدويًا:

Kotlin

var payload: ByteArray
...
val extRecord = NdefRecord(
        NdefRecord.TNF_EXTERNAL_TYPE,
        "com.example:externalType".toByteArray(Charset.forName("US-ASCII")),
        ByteArray(0),
        payload
)

Java

byte[] payload;
...
NdefRecord extRecord = new NdefRecord(
    NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".getBytes(Charset.forName("US-ASCII")),
    new byte[0], payload);

سيبدو فلتر الأهداف لسجلّ NDEF السابق على النحو التالي:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="vnd.android.nfc"
        android:host="ext"
        android:pathPrefix="/com.example:externalType"/>
</intent-filter>

استخدِم TNF_EXTERNAL_TYPE لعمليات نشر أكثر عمومية لعلامات NFC من أجل توفير دعم أفضل لكل من الأجهزة التي تعمل بنظام التشغيل Android والأجهزة التي لا تعمل به.

ملاحظة: تتضمّن معرّفات الموارد الموحّدة (URN) الخاصة بـ TNF_EXTERNAL_TYPE تنسيقًا أساسيًا هو: urn:nfc:ext:example.com:externalType، إلا أنّ مواصفات RTD الخاصة بمنتدى NFC توضّح أنّه يجب حذف جزء urn:nfc:ext: من معرّف الموارد الموحّد من سجلّ NDEF. كل ما عليك تقديمه هو النطاق (example.com في المثال) والنوع (externalType في المثال) مفصولَين بنقطتَين رأسيتَين. عند إرسال TNF_EXTERNAL_TYPE، يحوّل نظام التشغيل Android معرّف الموارد الموحّد urn:nfc:ext:example.com:externalType إلى معرّف الموارد المنتظم vnd.android.nfc://ext/example.com:externalType، وهو ما يعرّفه فلتر الأهداف في المثال.

سجلات تطبيقات Android

تم طرح سجلّ تطبيقات Android (AAR) في الإصدار 4.0 من نظام التشغيل Android (المستوى 14 لواجهة برمجة التطبيقات)، وهو يوفّر تأكيدًا أقوى على أنّه سيتم تشغيل تطبيقك عند مسح علامة NFC ضوئيًا. تحتوي سجلّات AAR على اسم حزمة تطبيق مضمّن في سجلّ NDEF. يمكنك إضافة سجلّ AAR إلى أي سجلّ NDEF في رسالة NDEF، لأنّ نظام التشغيل Android يبحث في رسالة NDEF بأكملها عن سجلّات AAR. إذا عثر على ملف AAR، سيبدأ تشغيل التطبيق استنادًا إلى اسم الحزمة داخل ملف AAR. إذا لم يكن التطبيق متوفّرًا على الجهاز، سيتم تشغيل Google Play لتنزيل التطبيق.

تكون طلبات AAR مفيدة إذا كنت تريد منع التطبيقات الأخرى من فلترة الغرض نفسه وربما معالجة علامات معيّنة نشرتها. لا تتوفّر طلبات AAR إلا على مستوى التطبيق بسبب قيود اسم الحزمة، وليس على مستوى النشاط كما هو الحال مع فلترة الأهداف. إذا كنت تريد التعامل مع هدف على مستوى النشاط، استخدِم فلاتر الأهداف.

إذا كانت العلامة تحتوي على طلب AAR، يرسل نظام إرسال العلامات الطلب بالطريقة التالية:

  1. حاوِل بدء نشاط باستخدام فلتر أهداف كالمعتاد. إذا كان النشاط الذي يتطابق مع الغرض يتطابق أيضًا مع AAR، ابدأ النشاط.
  2. إذا كان النشاط الذي يفلتر الغرض لا يتطابق مع AAR، أو إذا كان بإمكان أنشطة متعددة التعامل مع الغرض، أو إذا لم يتعامل أي نشاط مع الغرض، ابدأ التطبيق المحدّد بواسطة AAR.
  3. إذا لم يتمكّن أي تطبيق من البدء باستخدام AAR، انتقِل إلى Google Play لتنزيل التطبيق استنادًا إلى AAR.

ملاحظة: يمكنك إلغاء معالجة AAR ونظام إرسال الأهداف باستخدام نظام الإرسال في المقدّمة، ما يتيح لنشاط في المقدّمة الحصول على الأولوية عند اكتشاف علامة NFC. باستخدام هذه الطريقة، يجب أن يكون النشاط في المقدّمة لتجاوز طلبات AAR ونظام إرسال الأهداف.

إذا كنت لا تزال تريد فلترة العلامات التي تم فحصها والتي لا تحتوي على سجلّ AAR، يمكنك تعريف فلاتر الأهداف كالمعتاد. ويكون ذلك مفيدًا إذا كان تطبيقك مهتمًا بعلامات أخرى لا تحتوي على سجلّ AAR. على سبيل المثال، قد تريد ضمان أنّ تطبيقك يتعامل مع العلامات الخاصة التي تنشرها بالإضافة إلى العلامات العامة التي تنشرها الجهات الخارجية. يُرجى العِلم أنّ سجلّات AAR مخصّصة لأجهزة Android 4.0 أو الإصدارات الأحدث، لذا عند نشر العلامات، من الأفضل استخدام مجموعة من سجلّات AAR وأنواع MIME/معرّفات URI لتوفير التوافق مع أكبر مجموعة من الأجهزة. بالإضافة إلى ذلك، عند نشر علامات NFC، فكِّر في الطريقة التي تريد بها كتابة علامات NFC لتوفير الدعم لأكبر عدد من الأجهزة (الأجهزة التي تعمل بنظام التشغيل Android والأجهزة الأخرى). يمكنك إجراء ذلك من خلال تحديد نوع MIME أو عنوان URI فريد نسبيًا لتسهيل التمييز على التطبيقات.

يوفّر نظام التشغيل Android واجهة برمجة تطبيقات بسيطة لإنشاء ملف AAR, createApplicationRecord(). كل ما عليك فعله هو تضمين ملف AAR في أي مكان في NdefMessage. لا ننصحك باستخدام السجلّ الأول من NdefMessage، إلا إذا كان سجلّ AAR هو السجلّ الوحيد في NdefMessage. ويرجع ذلك إلى أنّ نظام Android يتحقّق من السجلّ الأول في NdefMessage لتحديد نوع MIME أو معرّف الموارد المنتظم (URI) الخاص بالعلامة، والذي يُستخدَم لإنشاء هدف لتتمكّن التطبيقات من فلترته. يوضّح الرمز التالي كيفية إنشاء ملف AAR:

Kotlin

val msg = NdefMessage(
        arrayOf(
                ...,
                NdefRecord.createApplicationRecord("com.example.android.beam")
        )
)

Java

NdefMessage msg = new NdefMessage(
        new NdefRecord[] {
            ...,
            NdefRecord.createApplicationRecord("com.example.android.beam")}
        );
)

قائمة التطبيقات المسموح لها بمسح علامات NFC ضوئيًا

اعتبارًا من Android 16، يتم إرسال إشعار إلى المستخدمين عندما يتلقّى التطبيق أول غرض NFC لفحص علامات NFC. يُتاح للمستخدم خيار منع التطبيق من البحث عن علامات NFC مرة أخرى في الإشعار.

  • يمكن للتطبيقات التحقّق مما إذا كان المستخدم قد سمح لها بفحص علامات NFC باستخدام NfcAdapter.isTagIntentAllowed().
  • يمكن للتطبيقات أن تطلب من المستخدم السماح بمسح علامات NFC ضوئيًا مرة أخرى عن طريق إرسال الغرض ACTION_CHANGE_TAG_INTENT_PREFERENCE.

ملاحظة: يمكن الوصول إلى قائمة التطبيقات المسموح لها بمسح علامات NFC ضوئيًا ضمن Settings > Apps > Special app access > Launch via NFC.

تمت إضافة هذه الآلية لمعالجة المخاوف التي أثارها المستخدمون بشأن بعض التطبيقات التي سجّلت فلاتر أهداف لطلبات علامات NFC، والتي كانت تظهر بشكل متكرر في المقدّمة عندما يضع المستخدم الهاتف بجانب علامة NFC (مثل بطاقة الائتمان أو هاتف أو ساعة أخرى وما إلى ذلك).