במסמך הזה מתוארות המשימות הבסיסיות של NFC שאפשר לבצע ב-Android. במאמר מוסבר איך לשלוח ולקבל נתוני NFC בצורת הודעות NDEF, ומתוארים ממשקי ה-API של Android framework שתומכים בתכונות האלה. לנושאים מתקדמים יותר, כולל דיון על עבודה עם נתונים שאינם NDEF, תוכלו לעיין במאמר NFC מתקדם.
קריאת נתוני NDEF מתג NFC מתבצעת באמצעות מערכת שליחת התגים, שמנתחת את תגי ה-NFC שזוהו, מסווגת את הנתונים בצורה מתאימה ומפעילה אפליקציה שמתעניינת בנתונים המסווגים. אפליקציה שרוצה לטפל בתג ה-NFC שנסרק יכולה להצהיר על מסנן Intent ולבקש לטפל בנתונים.
מערכת השליחה של התגים
מכשירי Android מחפשים בדרך כלל תגי NFC כשהמסך לא נעול, אלא אם ה-NFC מושבת בתפריט ההגדרות של המכשיר. כשמכשיר עם Android מזהה תג NFC, ההתנהגות הרצויה היא שהפעילות המתאימה ביותר לטפל בכוונה ללא שצריך לשאול את המשתמש באיזו אפליקציה להשתמש. מאחר שמכשירים סורקים תגי NFC בטווח קצר מאוד, סביר להניח שהמשתמשים יצטרכו להזיז את המכשיר מהתג כדי לבחור פעילות באופן ידני, וכך לקרוע את החיבור. כדי למנוע את ההצגה של בורר הפעילויות, כדאי לפתח את הפעילות כך שתטפל רק בתגי ה-NFC שקשורים לפעילות.
כדי לעזור לכם להשיג את המטרה הזו, מערכת Android מספקת מערכת מיוחדת לטיפול בתגים, שמנתחת תגי NFC שנסרקו, מנתחת אותם ומנסה לאתר אפליקציות שמתעניינות בנתונים שנסרקו. כדי לעשות זאת, הוא:
- ניתוח תג ה-NFC וזיהוי סוג ה-MIME או ה-URI שמזהה את עומס הנתונים בתג.
- אנקפסולציה של סוג ה-MIME או ה-URI ושל עומס העבודה (payload) בתוך כוונה (intent). שני השלבים הראשונים מתוארים בקטע איך תגי NFC ממופה לסוגים של MIME ולמזהי URI.
- הפעלת פעילות על סמך הכוונה. המידע הזה מפורט בקטע איך תגי 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 Specifications & Application Documents ולעיין במאמר יצירת סוגים נפוצים של רשומות 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 ו-type כדי לנסות למפות סוג MIME או URI להודעת ה-NDEF. אם הפעולה מצליחה, היא עוטפת את המידע הזה בתוך כוונה (intent) מסוג ACTION_NDEF_DISCOVERED
יחד עם עומס העבודה בפועל. עם זאת, יש מקרים שבהם מערכת השליחה של התגים לא יכולה לקבוע את סוג הנתונים על סמך רשומת ה-NDEF הראשונה. המצב הזה קורה כשאי אפשר למפות את נתוני ה-NDEF לסוג MIME או למזהה URI, או כשתג ה-NFC לא מכיל נתוני NDEF מלכתחילה. במקרים כאלה, אובייקט Tag
שמכיל מידע על הטכנולוגיות של התג ועל עומס העבודה (payload) מוקף במקום זאת בכוונה ACTION_TECH_DISCOVERED
.
טבלה 1 מתארת איך מערכת שליחת התגים ממפה שדות TNF וסוגי שדות לסוגי MIME או למזהי URI. בנוסף, מוסבר אילו TNFs לא ניתן למפות לסוג MIME או ל-URI.
במקרים כאלה, מערכת השליחה של התגים חוזרת ל-ACTION_TECH_DISCOVERED
.
לדוגמה, אם מערכת שליחת התגים נתקלת ברשומה מסוג TNF_ABSOLUTE_URI
, היא ממפה את שדה הסוג באורך משתנה של אותה רשומה למזהה URI. מערכת השליחה של התגים עוטפת את ה-URI הזה בשדה הנתונים של כוונה ACTION_NDEF_DISCOVERED
, יחד עם מידע נוסף על התג, כמו עומס העבודה. לעומת זאת, אם המערכת נתקלת ברשומה מסוג TNF_UNKNOWN
, היא יוצרת כוונה שמכילה את הטכנולוגיות של התג במקום זאת.
טבלה 1. TNF נתמכים והמיפויים שלהם
פורמט שם הסוג (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) בשדה type. מידע נוסף על מדדי 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 ואת פרטי הזיהוי שלו, היא שולחת את הכוונה לאפליקציה שמתעניינת בכך ומסננת את הכוונה. אם יש יותר מאפליקציה אחת שיכולה לטפל ב-Intent, מוצג בורר הפעילויות כדי שהמשתמש יוכל לבחור את הפעילות. מערכת השליחה של התגים מגדירה שלושה כוונות, שמפורטות לפי סדר העדיפות הגבוה ביותר לנמוך ביותר:
-
ACTION_NDEF_DISCOVERED
: ה-intent הזה משמש להפעלת פעילות כשנסרק תג שמכיל עומס נתונים של NDEF והוא מסוג מוכר. זוהי כוונת השימוש בעדיפות הגבוהה ביותר, ומערכת שליחת התגים מנסה להתחיל פעילות עם כוונת השימוש הזו לפני כל כוונת שימוש אחרת, כשהדבר אפשרי.הערה: החל מגרסה 16 של Android, סריקת תגי NFC שמאחסנים קישורי URL (כלומר סכימה של URI היא "htttps://" או "http://") תפעיל את ה-intent
ACTION_VIEW
במקום את ה-intentACTION_NDEF_DISCOVERED
. ACTION_TECH_DISCOVERED
: אם לא נרשמו פעילויות לטיפול בכוונהACTION_NDEF_DISCOVERED
, מערכת שליחת התגים תנסה להפעיל אפליקציה עם הכוונה הזו. הכוונה הזו מופעלת ישירות (בלי להפעיל קודם אתACTION_NDEF_DISCOVERED
) גם אם התג שנסרק מכיל נתוני NDEF שאי אפשר למפות לסוג MIME או ל-URI, או אם התג לא מכיל נתוני NDEF אבל הוא מתבסס על טכנולוגיית תגים ידועה.ACTION_TAG_DISCOVERED
: הכוונה הזו מופעלת אם אין פעילויות שמטפלות בכוונותACTION_NDEF_DISCOVERED
אוACTION_TECH_DISCOVERED
.
כך פועלת מערכת השליחה של התגים:
- מנסים להפעיל פעילות עם הכוונה שנוצרה על ידי מערכת שליחת התגים במהלך ניתוח תג ה-NFC (
ACTION_NDEF_DISCOVERED
אוACTION_TECH_DISCOVERED
). - אם אין פעילות שמסננת את הכוונה הזו, מנסים להפעיל פעילות עם הכוונה הבאה ברמת העדיפות הנמוכה ביותר (
ACTION_TECH_DISCOVERED
אוACTION_TAG_DISCOVERED
) עד שאפליקציה מסננת את הכוונה הזו או עד שמערכת שליחת התגים מנסה את כל הכוונות האפשריות. - אם אף אפליקציה לא מסננת אף אחד מהכוונות, לא עושים כלום.

כשהדבר אפשרי, מומלץ לעבוד עם הודעות NDEF ועם הכוונה ACTION_NDEF_DISCOVERED
, כי היא הספציפית ביותר מבין שלוש האפשרויות. הכוונה הזו מאפשרת לכם להפעיל את האפליקציה בזמן מתאים יותר משני הכוונות האחרות, וכך לספק למשתמש חוויה טובה יותר.
שליחת בקשה לגישה ל-NFC במניפסט של Android
כדי לגשת לחומרה של NFC במכשיר ולטפל כראוי בכוונות NFC, צריך להצהיר על הפריטים הבאים בקובץ AndroidManifest.xml
:
- הרכיב
<uses-permission>
של NFC כדי לגשת לחומרה של NFC:<uses-permission android:name="android.permission.NFC" />
- גרסת ה-SDK המינימלית שהאפליקציה יכולה לתמוך בה. רמת API 9 תומכת רק בשליחת תגים מוגבלת דרך
ACTION_TAG_DISCOVERED
, ומספקת גישה להודעות NDEF רק דרך התוסףEXTRA_NDEF_MESSAGES
. אי אפשר לגשת לתכונות אחרות של התג או לפעולות קלט/פלט. ברמה 10 של ה-API יש תמיכה מקיפה בקריאה/כתיבה, וגם דחיפה של NDEF בחזית. ברמה 14 של ה-API יש שיטות נוחות נוספות ליצירת רשומות 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
כדי לשלוט בצורה הטובה ביותר במועד שבו האפליקציה תתחיל לפעול. הכוונה (intent) 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
החל מגרסה 16 של Android, סריקה של תגי NFC שמאחסנים קישורי URL תפעיל את ה-Intent ACTION_VIEW
. כדי לסנן לפי ACTION_VIEW
, אפשר לעיין במאמר this
. משתמשים ב-Android app links
כדי לפתוח את האפליקציה של כתובת ה-URL.
אחזור מידע מכוונות
אם פעילות מתחילה בגלל כוונה ל-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. החל מגרסה 4.0 של Android (רמת API 14), השיטה createUri()
זמינה כדי לעזור לכם ליצור רשומות URI באופן אוטומטי. החל מגרסה 4.1 של Android (רמת API 16), אפשר להשתמש ב-createExternal()
וב-createMime()
כדי ליצור רשומות NDEF מסוג 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]);
מסנן ה-Intent של רשומת ה-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")));
מסנן ה-Intent של רשומת ה-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; }
מסנן ה-Intent של רשומת ה-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);
מסנן ה-Intent של רשומת ה-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);
מסנן ה-Intent של רשומת ה-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.
הערה: ל-URNs של TNF_EXTERNAL_TYPE
יש פורמט קנוני של:
urn:nfc:ext:example.com:externalType
, אבל במפרט RTD של NFC Forum מצוין שצריך להשמיט את החלק 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) הוצגה ב-Android 4.0 (רמת API 14) ומספקת ודאות גבוהה יותר שהאפליקציה תופעל כשתסרקו תג NFC. קובץ AAR מכיל את שם החבילה של אפליקציה שמוטמעת בתוך רשומת NDEF. אפשר להוסיף AAR לכל רשומת NDEF של הודעת ה-NDEF, כי Android מחפשת AARs בכל הודעת ה-NDEF. אם הוא מוצא קובץ AAR, הוא מפעיל את האפליקציה על סמך שם החבילה בתוך קובץ ה-AAR. אם האפליקציה לא מותקנת במכשיר, תופיע בקשה להורדת האפליקציה מ-Google Play.
AARs שימושיים אם אתם רוצים למנוע מאפליקציות אחרות לסנן לפי אותה כוונת שימוש, וגם אם אתם רוצים למנוע מהן לטפל בתגים ספציפיים שפרסמתם. אפשר להשתמש ב-AARs רק ברמת האפליקציה, בגלל האילוץ על שם החבילה, ולא ברמת הפעילות כמו בסינון לפי כוונה. אם רוצים לטפל בכוונה ברמת הפעילות, צריך להשתמש במסנני כוונות.
אם תג מכיל AAR, מערכת השליחה של התגים שולחת אותו באופן הבא:
- מנסים להפעיל פעילות באמצעות מסנן כוונה כרגיל. אם הפעילות שתואמת לכוונה תואמת גם ל-AAR, מתחילים את הפעילות.
- אם הפעילות שמסננת את הכוונה לא תואמת ל-AAR, אם כמה פעילויות יכולות לטפל בכוונה או אם אף פעילות לא מטפלת בכוונה, מפעילים את האפליקציה שצוינה ב-AAR.
- אם אף אפליקציה לא יכולה להתחיל באמצעות ה-AAR, עוברים אל Google Play כדי להוריד את האפליקציה על סמך ה-AAR.
הערה: אפשר לשנות את ההגדרות של AAR ושל מערכת שליחת הכוונות באמצעות מערכת שליחת הכוונות בחזית, שמאפשרת לפעילות בחזית לקבל עדיפות כשמתגלה תג NFC. כשמשתמשים בשיטה הזו, הפעילות צריכה להיות בחזית כדי לשנות את ההגדרות של AAR ושל מערכת שליחת הכוונות.
אם אתם עדיין רוצים לסנן לפי תגים סרוקים שלא מכילים AAR, תוכלו להצהיר על מסנני כוונה כרגיל. האפשרות הזו שימושית אם האפליקציה שלכם מתעניינת בתגים אחרים שלא מכילים AAR. לדוגמה, יכול להיות שאתם רוצים להבטיח שהאפליקציה שלכם תטפל בתגים קנייניים שאתם פורסים, וגם בתגים כלליים שצדדים שלישיים פורסים. חשוב לזכור ש-AARs ספציפיים למכשירי Android מגרסה 4.0 ואילך, ולכן כשפורסים תגים, מומלץ להשתמש בשילוב של AARs וסוגי MIME/URI כדי לתמוך במגוון הרחב ביותר של מכשירים. בנוסף, כשפורסים תגי NFC, כדאי לחשוב איך רוצים לכתוב את תגי ה-NFC כדי לאפשר תמיכה ברוב המכשירים (מכשירי Android ומכשירים אחרים). כדי לעשות זאת, אפשר להגדיר סוג MIME או URI ייחודיים יחסית כדי שיהיה קל יותר לאפליקציות להבדיל ביניהם.
ל-Android יש ממשק API פשוט ליצירת קובץ AAR, createApplicationRecord()
. כל מה שצריך לעשות הוא להטמיע את ה-AAR בכל מקום ב-NdefMessage
. לא כדאי להשתמש ברשומה הראשונה של NdefMessage
, אלא אם ה-AAR הוא הרשומה היחידה ב-NdefMessage
. הסיבה לכך היא שמערכת Android בודקת את הרשומה הראשונה של NdefMessage
כדי לקבוע את סוג ה-MIME או את ה-URI של התג, שמשמשים ליצירת כוונה (intent) לאפליקציות לסינון. הקוד הבא מראה איך יוצרים קובץ 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
החל מגרסה 16 של Android, משתמשים מקבלים התראה כשאפליקציה מקבלת את הכוונה הראשונה ל-NFC לסריקה של תגי NFC. בהתראה, המשתמש מקבל אפשרות לאסור על האפליקציה לסרוק תגי NFC.
- אפליקציות יכולות לבדוק אם המשתמש העניק לאפליקציה הרשאה לסרוק תגי NFC באמצעות
NfcAdapter.isTagIntentAllowed()
. - אפליקציות יכולות לשלוח את ה-intent
ACTION_CHANGE_TAG_INTENT_PREFERENCE
כדי לבקש מהמשתמש לאשר שוב את הסריקה של תגי NFC.
הערה: אפשר לגשת לרשימת ההיתרים של אפליקציות לסריקה של תגי NFC בקטע Settings > Apps > Special app access > Launch via NFC
.