במסמך הזה מתוארות משימות NFC בסיסיות שמבצעים ב-Android. במאמר מוסבר איך לשלוח ולקבל נתוני NFC בצורה של הודעות NDEF, ומתוארים ממשקי ה-API של מסגרת Android שתומכים בתכונות האלה. במאמר NFC מתקדם יש מידע על נושאים מתקדמים יותר, כולל דיון על עבודה עם נתונים שאינם NDEF.
קריאת נתוני NDEF מתג NFC מתבצעת באמצעות מערכת העברת התגים, שמנתחת תגי NFC שאותרו, מסווגת את הנתונים בצורה מתאימה ומפעילה אפליקציה שמתעניינת בנתונים המסווגים. אפליקציה שרוצה לטפל בתג NFC שנסרק יכולה להצהיר על מסנן כוונות ולבקש לטפל בנתונים.
מערכת שליחת התגים
בדרך כלל, מכשירים עם Android מחפשים תגי NFC כשהמסך לא נעול, אלא אם NFC מושבת בתפריט ההגדרות של המכשיר. כשמכשיר עם Android מזהה תג NFC, ההתנהגות הרצויה היא שהפעילות המתאימה ביותר תטפל ב-Intent בלי לבקש מהמשתמש לבחור אפליקציה. מכשירים סורקים תגי 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 Forum.
נתוני NDEF מוצפנים בתוך הודעה (NdefMessage) שמכילה רשומה אחת (NdefRecord) או יותר. כל רשומת NDEF חייבת להיות מעוצבת היטב בהתאם למפרט של סוג הרשומה שרוצים ליצור. Android תומך גם בסוגים אחרים של תגים שלא מכילים נתוני NDEF, שאפשר לעבוד איתם באמצעות המחלקות בחבילה android.nfc.tech. מידע נוסף על הטכנולוגיות האלה זמין במאמר בנושא NFC מתקדם. כדי לעבוד עם סוגים אחרים של תגים, צריך לכתוב מחסנית פרוטוקולים משלכם כדי לתקשר עם התגים. לכן, מומלץ להשתמש ב-NDEF כשזה אפשרי, כדי להקל על הפיתוח ולקבל תמיכה מקסימלית במכשירים עם Android.
הערה: כדי להוריד מפרטים מלאים של NDEF, אפשר לעבור לאתר NFC Forum Specifications & Application Documents ולעיין במאמר Creating common types of NDEF records (יצירת סוגים נפוצים של רשומות NDEF) כדי לראות דוגמאות לאופן שבו יוצרים רשומות NDEF.
אחרי שקיבלתם רקע מסוים בנושא תגי NFC, בקטעים הבאים מוסבר בפירוט איך מערכת Android מטפלת בתגים בפורמט NDEF. כשמכשיר עם Android סורק תג NFC שמכיל נתונים בפורמט NDEF, הוא מנתח את ההודעה ומנסה להבין את סוג ה-MIME של הנתונים או את ה-URI המזהה. לשם כך, המערכת קוראת את NdefRecord הראשון בתוך NdefMessage כדי לקבוע איך לפרש את כל הודעת ה-NDEF (הודעת NDEF יכולה לכלול כמה רשומות NDEF). בהודעת NDEF תקינה, הרשומה הראשונה NdefRecord
כוללת את השדות הבאים:
- 3-bit TNF (Type Name Format)
- מציין איך לפרש את השדה של סוג האורך המשתנה. הערכים התקינים מפורטים בטבלה 1.
- סוג אורך משתנה
- מתאר את סוג הרשומה. אם משתמשים ב-
TNF_WELL_KNOWN, צריך להשתמש בשדה הזה כדי לציין את הגדרת סוג הרשומה (RTD). ערכי ה-RTD התקפים מתוארים בטבלה 2. - מזהה באורך משתנה
- מזהה ייחודי של הרשומה. לא משתמשים בשדה הזה לעיתים קרובות, אבל אם אתם צריכים לזהות תג באופן ייחודי, אתם יכולים ליצור לו מזהה.
- מטען ייעודי (payload) באורך משתנה
- מטען הנתונים בפועל שרוצים לקרוא או לכתוב. הודעת NDEF יכולה להכיל כמה רשומות NDEF, לכן אל תניחו שהמטען הייעודי (payload) המלא נמצא ברשומת ה-NDEF הראשונה של הודעת ה-NDEF.
מערכת שליחת התגים משתמשת בשדות TNF ובשדות הסוג כדי לנסות למפות סוג MIME או URI להודעת NDEF. אם הפעולה מצליחה, המידע הזה נכלל ב-intent ACTION_NDEF_DISCOVERED יחד עם מטען הייעודי (payload) בפועל. עם זאת, יש מקרים שבהם מערכת שליחת התגים לא יכולה לקבוע את סוג הנתונים על סמך רשומת ה-NDEF הראשונה. זה קורה כשאי אפשר למפות את נתוני ה-NDEF לסוג MIME או למזהה URI, או כשמלכתחילה תג ה-NFC לא מכיל נתוני NDEF. במקרים כאלה, אובייקט Tag שמכיל מידע על הטכנולוגיות של התג ואת מטען הנתונים, מוכל בתוך כוונת ACTION_TECH_DISCOVERED.
בטבלה 1 מוסבר איך מערכת שליחת התגים ממפה את השדות TNF ו-type לסוגי MIME או ל-URI. בנוסף, הוא מתאר אילו TNFs אי אפשר למפות לסוג MIME או ל-URI.
במקרים כאלה, מערכת שליחת התגים חוזרת לערך ACTION_TECH_DISCOVERED.
לדוגמה, אם מערכת שליחת התגים נתקלת ברשומה מסוג TNF_ABSOLUTE_URI, היא ממפה את השדה מסוג אורך משתנה של הרשומה הזו ל-URI. מערכת שליחת התגים כוללת את ה-URI בשדה הנתונים של ACTION_NDEF_DISCOVERED intent יחד עם מידע נוסף על התג, כמו המטען הייעודי (payload). מצד שני, אם היא נתקלת ברשומה מסוג 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) שהגדרתם בשדה הסוג. מידע נוסף על 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 מבוסס על ניתוח המטען הייעודי (payload). |
RTD_TEXT |
סוג ה-MIME של text/plain. |
RTD_URI |
URI שמבוסס על מטען ייעודי (payload). |
איך תגי NFC נשלחים לאפליקציות
כשמערכת שליחת התגים מסיימת ליצור כוונה שמכילה את תג ה-NFC ואת פרטי הזיהוי שלו, היא שולחת את הכוונה לאפליקציה שמתעניינת בה ומסננת אותה. אם יותר מאפליקציה אחת יכולה לטפל ב-Intent, מוצג בורר הפעילויות כדי שהמשתמש יוכל לבחור את הפעילות. מערכת שליחת התגים מגדירה שלוש כוונות, שמופיעות בסדר יורד לפי רמת העדיפות:
-
ACTION_NDEF_DISCOVERED: הכוונה הזו משמשת להפעלת Activity כשסורקים תג שמכיל מטען ייעודי (payload) של NDEF והוא מסוג מוכר. זוהי כוונת המשתמש בעדיפות הכי גבוהה, ומערכת שליחת התגים מנסה להפעיל פעילות עם כוונת המשתמש הזו לפני כל כוונת משתמש אחרת, בכל הזדמנות אפשרית.הערה: החל מ-Android 16, סריקה של תגי NFC שמאחסנים קישורי כתובות URL (כלומר, סכמת ה-URI היא "https://" או "http://") תפעיל את כוונת
ACTION_VIEWבמקום את כוונתACTION_NDEF_DISCOVERED. -
ACTION_TECH_DISCOVERED: אם לא נרשמו פעילויות לטיפול ב-intentACTION_NDEF_DISCOVERED, מערכת שליחת התגים מנסה להפעיל אפליקציה עם ה-intent הזה. הכוונה הזו מופעלת גם באופן ישיר (בלי להפעיל את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:
- רכיב ה-NFC
<uses-permission>כדי לגשת לחומרת ה-NFC:<uses-permission android:name="android.permission.NFC" />
- גרסת ה-SDK המינימלית שהאפליקציה יכולה לתמוך בה. API level 9 תומך רק בשליחת תגים מוגבלת דרך
ACTION_TAG_DISCOVERED, ומאפשר גישה רק להודעות NDEF דרך התוסףEXTRA_NDEF_MESSAGES. אין גישה למאפיינים אחרים של תגים או לפעולות קלט/פלט. API ברמה 10 כולל תמיכה מקיפה בקריאה/כתיבה, וגם בדחיפה של NDEF בחזית, ו-API ברמה 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 שרוצים לטפל בו, האפליקציה יכולה לסנן את אחד, שניים או שלושת ה-Intents של NFC בקובץ המניפסט של Android. עם זאת, בדרך כלל כדאי לסנן לפי הכוונה ACTION_NDEF_DISCOVERED כדי לקבל את השליטה המרבית על מועד ההפעלה של האפליקציה. ה-Intent ACTION_TECH_DISCOVERED הוא חלופה ל-ACTION_NDEF_DISCOVERED אם לא חל מסנן אפליקציות על ACTION_NDEF_DISCOVERED או אם מטען הייעודי (payload) הוא לא 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 הבא:
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
ACTION_VIEW
החל מ-Android 16, סריקה של תגי NFC שמאחסנים קישורים לכתובות URL תפעיל את Intent ACTION_VIEW. כדי לסנן לפי ACTION_VIEW
אפשר לעיין במאמר this. משתמשים בAndroid app links כדי לפתוח את האפליקציה של כתובת ה-URL.
קבלת מידע מ-Intents
אם פעילות מתחילה בגלל Intent של NFC, אפשר לקבל מידע על תג ה-NFC שנסרק מה-Intent. ה-Intents יכולים להכיל את התוספים הבאים, בהתאם לתג שנסרק:
-
EXTRA_TAG(חובה): אובייקטTagשמייצג את התג שנסרק. -
EXTRA_NDEF_MESSAGES(אופציונלי): מערך של הודעות NDEF שנותחו מהתג. התוספת הזו היא חובה בכוונותACTION_NDEF_DISCOVERED. -
EXTRA_ID(אופציונלי): המזהה ברמה הנמוכה של התג.
כדי לקבל את התוספים האלה, צריך לבדוק אם הפעילות הופעלה באמצעות אחת מהכוונה של NFC כדי לוודא שתג נסרק, ואז לקבל את התוספים מתוך הכוונה. בדוגמה הבאה בודקים את הכוונה ומקבלים את הודעות ה-NDEF מתוספת של כוונה.ACTION_NDEF_DISCOVERED
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 מה-Intent, שיכיל את מטען הייעודי (payload) ויאפשר לכם למנות את הטכנולוגיות של התג:
Kotlin
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
יצירה של סוגים נפוצים של רשומות NDEF
בקטע הזה מוסבר איך ליצור סוגים נפוצים של רשומות NDEF כדי לעזור לכם בכתיבה לתגי NFC. החל מ-Android 4.0 (רמת API 14), ה-method createUri() זמין כדי לעזור לכם ליצור רשומות URI באופן אוטומטי. החל מ-Android 4.1 (רמת API 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]);
מסנן ה-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
אפשר ליצור רשומת 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")));
מסנן ה-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 with 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; }
מסנן ה-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
אפשר ליצור רשומת 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);
מסנן ה-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
אפשר ליצור רשומת 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);
מסנן ה-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.
הערה: ל-URN של 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 מחפשת רשומות AAR בכל הודעת NDEF. אם נמצא קובץ AAR, האפליקציה מופעלת על סמך שם החבילה שבתוך קובץ ה-AAR. אם האפליקציה לא נמצאת במכשיר, מערכת Google Play תופעל כדי להוריד את האפליקציה.
דוחות AAR שימושיים אם רוצים למנוע מאפליקציות אחרות לסנן לפי אותה כוונה, ואולי לטפל בתגים ספציפיים שהטמעתם. יש תמיכה בדוחות AAR רק ברמת האפליקציה, בגלל מגבלת שם החבילה, ולא ברמת הפעילות כמו בסינון כוונות. אם רוצים לטפל בכוונה ברמת הפעילות, משתמשים במסנני כוונות.
אם תג מכיל 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, אלא אם זו הרשומה היחידה ב-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.