مبانی NFC

این سند وظایف اساسی NFC را که در Android انجام می دهید، شرح می دهد. نحوه ارسال و دریافت داده‌های NFC را در قالب پیام‌های NDEF توضیح می‌دهد و APIهای چارچوب Android را که از این ویژگی‌ها پشتیبانی می‌کنند، توضیح می‌دهد. برای موضوعات پیشرفته تر، از جمله بحث در مورد کار با داده های غیر NDEF، به NFC پیشرفته مراجعه کنید.

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

سیستم ارسال برچسب

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

برای کمک به شما در این هدف، اندروید یک سیستم ارسال برچسب ویژه ارائه می کند که تگ های اسکن شده NFC را تجزیه و تحلیل می کند، آنها را تجزیه می کند و سعی می کند برنامه هایی را که به داده های اسکن شده علاقه مند هستند پیدا کند. این کار را توسط:

  1. تجزیه تگ NFC و تعیین نوع MIME یا URI که بار داده را در تگ شناسایی می کند.
  2. کپسوله کردن نوع MIME یا URI و محموله در یک intent. این دو مرحله اول در نحوه نگاشت برچسب های NFC به انواع MIME و URI توضیح داده شده است.
  3. فعالیتی را بر اساس قصد شروع می کند. این در نحوه ارسال برچسب های NFC به برنامه ها توضیح داده شده است.

نحوه نگاشت برچسب های NFC به انواع MIME و URI ها

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

داده های NDEF درون یک پیام ( NdefMessage ) که حاوی یک یا چند رکورد ( NdefRecord ) است، کپسوله می شود. هر رکورد NDEF باید با توجه به مشخصات نوع رکوردی که می خواهید ایجاد کنید، به خوبی شکل گرفته باشد. اندروید همچنین از انواع دیگری از تگ‌ها پشتیبانی می‌کند که حاوی داده‌های NDEF نیستند، که می‌توانید با استفاده از کلاس‌های موجود در بسته android.nfc.tech با آنها کار کنید. برای کسب اطلاعات بیشتر در مورد این فناوری ها، به مبحث Advanced NFC مراجعه کنید. کار با این انواع دیگر برچسب‌ها شامل نوشتن پشته پروتکل خود برای برقراری ارتباط با برچسب‌ها است، بنابراین توصیه می‌کنیم در صورت امکان برای سهولت در توسعه و حداکثر پشتیبانی از دستگاه‌های مجهز به Android از NDEF استفاده کنید.

توجه: برای دانلود مشخصات کامل NDEF، به سایت NFC Forum Specifications & Application Documents بروید و برای مثال هایی از نحوه ساخت رکوردهای NDEF ، ایجاد انواع رایج رکوردهای NDEF را ببینید.

اکنون که پیشینه ای در تگ های NFC دارید، در بخش های زیر با جزئیات بیشتری توضیح داده می شود که Android چگونه تگ های فرمت شده NDEF را مدیریت می کند. هنگامی که یک دستگاه مجهز به اندروید یک تگ 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 که اطلاعاتی در مورد فن‌آوری‌های برچسب و محموله دارد در داخل یک intent ACTION_TECH_DISCOVERED کپسوله می‌شود.

جدول 1 توضیح می دهد که چگونه سیستم ارسال برچسب TNF و فیلدهای نوع را به انواع MIME یا URI نگاشت می کند. همچنین توضیح می دهد که کدام TNF را نمی توان به یک نوع MIME یا URI نگاشت کرد. در این موارد، سیستم ارسال برچسب به ACTION_TECH_DISCOVERED برمی‌گردد.

برای مثال، اگر سیستم ارسال برچسب با رکوردی از نوع TNF_ABSOLUTE_URI مواجه شود، فیلد نوع طول متغیر آن رکورد را در یک URI نگاشت می‌کند. سیستم ارسال برچسب، آن URI را در فیلد داده یک هدف ACTION_NDEF_DISCOVERED همراه با سایر اطلاعات مربوط به برچسب، مانند بار بار، محصور می کند. از طرف دیگر، اگر با رکوردی از نوع TNF_UNKNOWN مواجه شود، یک intent ایجاد می کند که به جای آن فناوری های برچسب را محصور می کند.

جدول 1. TNF های پشتیبانی شده و نگاشت آنها

نوع قالب نام (TNF) نقشه برداری
TNF_ABSOLUTE_URI URI بر اساس فیلد نوع.
TNF_EMPTY به ACTION_TECH_DISCOVERED برمی گردد.
TNF_EXTERNAL_TYPE URI بر اساس URN در قسمت type. 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) که در قسمت نوع تنظیم می کنید. برای اطلاعات بیشتر در مورد RTD های موجود و نگاشت آنها به جدول 2 مراجعه کنید.

جدول 2. RTD های پشتیبانی شده برای 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 به برنامه ها

هنگامی که سیستم ارسال تگ ایجاد یک intent را انجام داد که تگ NFC و اطلاعات شناسایی آن را محصور می کند، این هدف را به یک برنامه علاقه مند ارسال می کند که هدف را فیلتر می کند. اگر بیش از یک برنامه بتواند هدف را مدیریت کند، Activity Chooser ارائه می شود تا کاربر بتواند Activity را انتخاب کند. سیستم ارسال برچسب سه هدف را تعریف می کند که به ترتیب اولویت بالاتر به پایین فهرست شده اند:

  1. ACTION_NDEF_DISCOVERED : این هدف برای شروع یک فعالیت زمانی که یک برچسب حاوی بار NDEF اسکن شده و از نوع شناخته شده است استفاده می شود. این هدف بالاترین اولویت است، و سیستم ارسال برچسب سعی می کند تا قبل از هر هدف دیگری، یک Activity را با این هدف شروع کند، تا جایی که ممکن است.
  2. ACTION_TECH_DISCOVERED : اگر هیچ فعالیتی برای مدیریت هدف ACTION_NDEF_DISCOVERED ثبت نشود، سیستم ارسال برچسب سعی می‌کند برنامه‌ای را با این هدف شروع کند. اگر برچسبی که اسکن می‌شود حاوی داده‌های NDEF باشد که نمی‌توان آن‌ها را به یک نوع MIME یا URI نگاشت، یا اگر برچسب حاوی داده‌های NDEF نباشد، اما از یک فناوری برچسب شناخته شده باشد، این هدف نیز مستقیماً شروع می‌شود (بدون شروع ACTION_NDEF_DISCOVERED ابتدا).
  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 در مانیفست اندروید

قبل از اینکه بتوانید به سخت افزار NFC دستگاه دسترسی داشته باشید و به درستی مقاصد NFC را مدیریت کنید، این موارد را در فایل AndroidManifest.xml خود اعلام کنید:

  • عنصر NFC <uses-permission> برای دسترسی به سخت افزار NFC:
    <uses-permission android:name="android.permission.NFC" />
    
  • حداقل نسخه SDK که برنامه شما می تواند پشتیبانی کند. سطح 9 API فقط از ارسال برچسب محدود از طریق ACTION_TAG_DISCOVERED پشتیبانی می‌کند و فقط از طریق EXTRA_NDEF_MESSAGES اضافی به پیام‌های NDEF دسترسی می‌دهد. هیچ ویژگی تگ یا عملیات ورودی/خروجی دیگری در دسترس نیست. سطح 10 API شامل پشتیبانی جامع خواننده/نویسنده و همچنین فشار دادن پیش زمینه NDEF است و سطح API 14 روش‌های راحتی اضافی را برای ایجاد رکوردهای NDEF فراهم می‌کند.
    <uses-sdk android:minSdkVersion="10"/>
    
  • عنصر uses-feature به طوری که برنامه شما فقط برای دستگاه‌هایی که سخت‌افزار NFC دارند در Google Play نمایش داده می‌شود:
    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    

    اگر برنامه شما از عملکرد NFC استفاده می کند، اما این عملکرد برای برنامه شما حیاتی نیست، می توانید عنصر uses-feature را حذف کنید و با بررسی اینکه آیا getDefaultAdapter() null است، وجود NFC را در زمان اجرا بررسی کنید.

فیلتر برای مقاصد NFC

برای شروع برنامه زمانی که یک برچسب NFC که می‌خواهید با آن کار کنید اسکن می‌شود، برنامه شما می‌تواند یک، دو یا هر سه هدف NFC را در مانیفست Android فیلتر کند. با این حال، شما معمولاً می‌خواهید برای هدف ACTION_NDEF_DISCOVERED فیلتر کنید تا زمان شروع برنامه‌تان بیشترین کنترل را داشته باشید. هدف ACTION_TECH_DISCOVERED زمانی برای ACTION_NDEF_DISCOVERED زمانی که هیچ برنامه‌ای برای ACTION_NDEF_DISCOVERED فیلتر نمی‌کند یا زمانی که محموله NDEF نیست، بازگشتی است. فیلتر کردن برای ACTION_TAG_DISCOVERED معمولاً برای فیلتر کردن آن خیلی عمومی است. بسیاری از برنامه‌ها قبل از ACTION_TAG_DISCOVERED برای ACTION_NDEF_DISCOVERED یا ACTION_TECH_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>

اطلاعات را از نیت ها بدست آورید

اگر فعالیتی به دلیل هدف NFC شروع شود، می توانید اطلاعات مربوط به برچسب NFC اسکن شده را از قصد دریافت کنید. بسته به برچسبی که اسکن شده است، Intent ها می توانند شامل موارد اضافی زیر باشند:

  • EXTRA_TAG (الزامی): یک شی Tag که نشان دهنده برچسب اسکن شده است.
  • EXTRA_NDEF_MESSAGES (اختیاری): آرایه ای از پیام های NDEF تجزیه شده از برچسب. این اضافی برای اهداف ACTION_NDEF_DISCOVERED اجباری است.
  • EXTRA_ID (اختیاری): شناسه سطح پایین تگ.

برای به دست آوردن این موارد اضافی، بررسی کنید که آیا فعالیت شما با یکی از اهداف NFC راه اندازی شده است تا مطمئن شوید که یک برچسب اسکن شده است یا خیر، و سپس موارد اضافی را خارج از هدف دریافت کنید. مثال زیر هدف ACTION_NDEF_DISCOVERED را بررسی می‌کند و پیام‌های NDEF را از یک intent اضافی دریافت می‌کند.

کاتلین

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

جاوا

@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 از intent بدست آورید که حاوی بار بار است و به شما امکان می‌دهد فناوری‌های برچسب را برشمارید:

کاتلین

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

جاوا

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

انواع رایج رکوردهای NDEF را ایجاد کنید

این بخش نحوه ایجاد انواع رایج رکوردهای NDEF را توضیح می دهد تا به شما در هنگام نوشتن روی برچسب های NFC کمک کند. با شروع Android 4.0 (سطح API 14)، متد createUri() برای کمک به ایجاد خودکار رکوردهای URI در دسترس است. با شروع Android 4.1 (سطح API 16)، createExternal() و createMime() در دسترس هستند تا به شما کمک کنند تا رکوردهای MIME و نوع خارجی NDEF ایجاد کنید. در صورت امکان از این روش های کمکی استفاده کنید تا هنگام ایجاد دستی رکوردهای NDEF از اشتباه جلوگیری کنید.

این بخش همچنین نحوه ایجاد فیلتر قصد مربوطه برای رکورد را توضیح می دهد. همه این نمونه‌های رکورد NDEF باید در اولین رکورد NDEF پیام NDEF باشد که در حال نوشتن روی یک برچسب هستید.

TNF_ABSOLUTE_URI

توجه: توصیه می کنیم به جای TNF_ABSOLUTE_URI از نوع RTD_URI استفاده کنید، زیرا کارآمدتر است.

می توانید یک رکورد TNF_ABSOLUTE_URI NDEF به روش زیر ایجاد کنید:

کاتلین

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

جاوا

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() :

کاتلین

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

جاوا

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

ایجاد NdefRecord به صورت دستی:

کاتلین

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

جاوا

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 به روش زیر ایجاد کنید:

کاتلین

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

جاوا

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) :

کاتلین

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

جاوا

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

با استفاده از متد createUri(Uri) :

کاتلین

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

جاوا

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

ایجاد NdefRecord به صورت دستی:

کاتلین

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)

جاوا

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() :

کاتلین

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)

جاوا

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 به صورت دستی:

کاتلین

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

جاوا

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 ، اما مشخصات NFC Forum RTD اعلام می کند که بخش urn:nfc:ext: URN باید از رکورد NDEF حذف شود. بنابراین تنها چیزی که باید ارائه دهید دامنه (در مثال example.com ) و نوع ( externalType در مثال) است که با یک دونقطه از هم جدا شده اند. هنگام ارسال TNF_EXTERNAL_TYPE ، Android urn:nfc:ext:example.com:externalType URN را به vnd.android.nfc://ext/example.com:externalType URI تبدیل می کند، که فیلتر قصد در مثال اعلام می کند.

رکوردهای برنامه اندروید

یک رکورد برنامه Android (AAR) که در Android 4.0 (سطح API 14) معرفی شده است، اطمینان قوی تری را ارائه می دهد که برنامه شما با اسکن شدن یک برچسب NFC شروع به کار می کند. یک AAR نام بسته یک برنامه کاربردی را در یک رکورد NDEF تعبیه کرده است. می‌توانید یک AAR به هر رکورد NDEF پیام NDEF خود اضافه کنید، زیرا Android کل پیام NDEF را برای AAR جستجو می‌کند. اگر یک AAR پیدا کند، برنامه را بر اساس نام بسته داخل AAR شروع می کند. اگر برنامه در دستگاه وجود نداشته باشد، Google Play برای دانلود برنامه راه اندازی می شود.

اگر می‌خواهید از فیلتر کردن سایر برنامه‌ها برای همان هدف و مدیریت بالقوه برچسب‌های خاصی که شما مستقر کرده‌اید جلوگیری کنید، AARها مفید هستند. AARها فقط در سطح برنامه به دلیل محدودیت نام بسته پشتیبانی می شوند و نه در سطح Activity مانند فیلتر قصد. اگر می‌خواهید یک intent را در سطح Activity مدیریت کنید، از فیلترهای intent استفاده کنید .

اگر یک برچسب حاوی یک AAR باشد، سیستم ارسال برچسب به روش زیر ارسال می شود:

  1. سعی کنید یک Activity را با استفاده از فیلتر هدف به طور معمول شروع کنید. اگر فعالیتی که با هدف مطابقت دارد نیز با AAR مطابقت دارد، Activity را شروع کنید.
  2. اگر فعالیتی که برای intent فیلتر می‌کند با AAR مطابقت ندارد، اگر چندین فعالیت می‌تواند هدف را مدیریت کند، یا اگر هیچ فعالیتی قصد مدیریت را ندارد، برنامه مشخص شده توسط AAR را شروع کنید.
  3. اگر هیچ برنامه ای نمی تواند با AAR شروع شود، برای دانلود برنامه بر اساس AAR به Google Play بروید.

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

اگر همچنان می‌خواهید برچسب‌های اسکن‌شده را که حاوی AAR نیستند فیلتر کنید، می‌توانید فیلترهای هدف را عادی اعلام کنید. اگر برنامه شما به تگ های دیگری که حاوی AAR نیستند علاقه مند باشد، مفید است. به عنوان مثال، شاید بخواهید تضمین کنید که برنامه شما برچسب های اختصاصی را که شما مستقر می کنید و همچنین برچسب های عمومی استقرار شده توسط اشخاص ثالث را کنترل می کند. به خاطر داشته باشید که AARها مختص دستگاه‌های Android نسخه 4.0 یا بالاتر هستند، بنابراین هنگام استقرار برچسب‌ها، به احتمال زیاد می‌خواهید از ترکیبی از انواع AAR و MIME/URI برای پشتیبانی از وسیع‌ترین طیف دستگاه‌ها استفاده کنید. علاوه بر این، هنگامی که تگ های NFC را نصب می کنید، به این فکر کنید که چگونه می خواهید برچسب های NFC خود را بنویسید تا پشتیبانی از اکثر دستگاه ها (با اندروید و سایر دستگاه ها) فعال شود. شما می توانید این کار را با تعریف یک نوع MIME یا URI نسبتاً منحصر به فرد انجام دهید تا تشخیص آسان تر برای برنامه ها انجام شود.

Android یک API ساده برای ایجاد AAR، createApplicationRecord() ارائه می دهد. تنها کاری که باید انجام دهید این است که AAR را در هر جایی از NdefMessage خود جاسازی کنید. شما نمی خواهید از اولین رکورد NdefMessage خود استفاده کنید، مگر اینکه AAR تنها رکورد در NdefMessage باشد. این به این دلیل است که سیستم اندروید اولین رکورد یک NdefMessage را برای تعیین نوع MIME یا URI تگ بررسی می‌کند، که برای ایجاد هدفی برای فیلتر کردن برنامه‌ها استفاده می‌شود. کد زیر نحوه ایجاد AAR را به شما نشان می دهد:

کاتلین

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

جاوا

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