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

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

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

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

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

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

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

كيفية ربط علامات NFC بأنواع MIME وعناوين URL

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

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

ملاحظة: لتنزيل مواصفات NDEF الكاملة، انتقِل إلى الموقع الإلكتروني NFC Forum Specifications & Application Documents (مواصفات منتدى NFC ومستندات التطبيقات) واطّلِع على Creating common types of NDEF records (إنشاء أنواع شائعة من سجلّات NDEF) للحصول على أمثلة حول كيفية إنشاء سجلّات NDEF.

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

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

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

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

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

الجدول 1. معرّفات TNF المتوافقة وعمليات الربط الخاصة بها

تنسيق اسم النوع (TNF) التعيين
TNF_ABSOLUTE_URI عنوان URL استنادًا إلى حقل النوع
TNF_EMPTY يعود إلى ACTION_TECH_DISCOVERED.
TNF_EXTERNAL_TYPE معرّف الموارد المنتظم (URI) استنادًا إلى معرّف الموارد الموحّد (URN) في حقل النوع يتم ترميز معرّف URN في حقل نوع NDEF بأحد يليه: شكل مختصر: <domain_name>:<service_name>. يربط Android هذا العنوان بمعرّف موارد منتظم على النحو التالي: 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) الذي تحدّده في حقل type اطّلِع على الجدول 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 عنوان URL استنادًا إلى تحليل الحمولة
RTD_TEXT نوع MIME لـ text/plain.
RTD_URI عنوان URL يستند إلى الحمولة

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

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

  1. ACTION_NDEF_DISCOVERED: يُستخدَم هذا الغرض لبدء نشاط عندما يتم فحص علامة تحتوي على حمولة NDEF وتكون من نوع معروف. هذا هو الهدف الأعلى أولوية، ويحاول نظام إرسال العلامات بدء نشاط باستخدام هذا الهدف قبل أي هدف آخر، كلما أمكن ذلك.
  2. ACTION_TECH_DISCOVERED: إذا لم يتم تسجيل أي أنشطة لمعالجة ACTION_NDEF_DISCOVERED intent، يحاول نظام إرسال العلامات بدء تطبيق باستخدام هذا الintent. يبدأ هذا القصد أيضًا مباشرةً (بدون بدء ACTION_NDEF_DISCOVERED أولاً) إذا كانت العلامة التي يتم مسحها ضوئيًا تحتوي على بيانات NDEF لا يمكن ربطها بنوع MIME أو عنوان URL، أو إذا كانت العلامة لا تحتوي على بيانات 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 وهدف 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>

تصفّح المثال التالي عن عنوان URL بالتنسيق التالي: 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>

لمزيد من المعلومات عن التعامل مع تكنولوجيات العلامات وintent‏ ACTION_TECH_DISCOVERED، اطّلِع على العمل باستخدام تكنولوجيات العلامات المتوافقة في مستند NFC المتقدّم.

ACTION_TAG_DISCOVERED

لفلترة النتائج حسب ACTION_TAG_DISCOVERED، استخدِم فلتر القصْد التالي:

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

الحصول على معلومات من النوايا

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

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

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

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. اعتبارًا من Android 4.0 (المستوى 14 من واجهة برمجة التطبيقات)، تتوفّر الطريقة createUri() لمساعدتك في إنشاء سجلّات عناوين URL تلقائيًا. بدءًا من الإصدار 4.1 من نظام التشغيل Android (المستوى 16 من واجهة برمجة التطبيقات)، يتوفّر الإصداران createExternal() وcreateMime() لمساعدتك في إنشاء سجلات MIME وسجلات NDEF من النوع الخارجي. استخدِم طرق المساعدة هذه كلما أمكن ذلك لتجنُّب الأخطاء عند إنشاء سجلّات NDEF يدويًا.

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

TNF_ABSOLUTE_URI

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

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

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

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

باستخدام طريقة 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

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

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

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

باستخدام طريقة 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

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

باستخدام طريقة 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 والأجهزة التي لا تعمل بنظام التشغيل Android.

ملاحظة: تتّبع عناوين URN الخاصة بـ TNF_EXTERNAL_TYPE التنسيق الأساسي التالي: urn:nfc:ext:example.com:externalType، ومع ذلك، تُشير مواصفات NFC Forum RTD إلى أنّه يجب حذف الجزء urn:nfc:ext: من عنوان URN من ملف تسجيل NDEF. لذلك، ما عليك سوى توفير النطاق (example.com في المثال) والنوع (externalType في المثال) مفصولَين بنقطتين. عند إرسال TNF_EXTERNAL_TYPE، يحوّل Android رقم URN urn:nfc:ext:example.com:externalType إلى معرّف الموارد المنتظم (URI) 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 مخصّصة لأجهزة Android 4.0 أو الإصدارات الأحدث، لذا عند نشر العلامات، من المرجّح أن تحتاج إلى استخدام مجموعة من ملفات AAR وأنواع MIME/عناوين URL لتتوافق مع أكبر نطاق من الأجهزة. بالإضافة إلى ذلك، عند نشر علامات NFC، يجب التفكير في كيفية كتابة علامات NFC لتفعيل التوافق مع معظم الأجهزة (الأجهزة التي تعمل بنظام التشغيل Android والأجهزة الأخرى). ويمكنك إجراء ذلك من خلال تحديد نوع MIME أو عنوان URI فريدَين نسبيًا لتسهيل تمييز التطبيقات بينهما.

يوفّر Android واجهة برمجة تطبيقات بسيطة لإنشاء حِزم APK القابلة للاستبدال، createApplicationRecord(). ما عليك سوى تضمين ملف AAR في أي مكان في NdefMessage. لا تريد استخدام السجلّ الأول من NdefMessage، ما لم يكن سجلّ AAR هو السجلّ الوحيد في NdefMessage. ويعود السبب في ذلك إلى أنّ نظام Android يتحقّق من السجلّ الأول من NdefMessage لتحديد نوع MIME أو عنوان URL للعلامة، والذي يتم استخدامه لإنشاء نية للتطبيقات لفلترة المحتوى. توضّح لك التعليمة البرمجية التالية كيفية إنشاء تقرير 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")}
        );
)