במסמך הזה מתוארות הפעולות הבסיסיות של 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 שמזהה את המטען הייעודי (payload) של הנתונים בתג.
- אנקפסולציה של סוג ה-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
, צריך להשתמש בשדה הזה כדי לציין את הערך Record Type Definition (RTD). ערכי RTD חוקיים מתוארים בטבלה 2. - מזהה אורך משתנה
- מזהה ייחודי של הרשומה. לא נעשה שימוש בשדה הזה לעיתים קרובות, אבל אם אתם צריכים לזהות תג באופן ייחודי, תוכלו ליצור לו מזהה.
- מטען נתונים באורך משתנה
- מטען הייעודי (payload) בפועל של הנתונים שרוצים לקרוא או לכתוב. הודעת NDEF יכולה להכיל כמה רשומות NDEF, לכן אל תניחו שהמטען המועיל המלא נמצא ברשומת NDEF הראשונה של הודעת ה-NDEF.
מערכת שליחת התגים משתמשת בשדות TNF ו-type כדי לנסות למפות סוג MIME או URI להודעת NDEF. אם הפעולה מצליחה, היא עוטפת את המידע הזה בתוך כוונה (intent) מסוג ACTION_NDEF_DISCOVERED
יחד עם עומס העבודה בפועל. אבל יש מקרים שבהם מערכת שליחת התגים לא יכולה לקבוע את סוג הנתונים על סמך רשומת ה-NDEF הראשונה. זה קורה כשלא ניתן למפות את נתוני NDEF לסוג MIME או URI, או כאשר התג NFC לא מכיל נתוני NDEF מלכתחילה. במקרים כאלה, אובייקט Tag
שמכיל מידע על הטכנולוגיות של התג ועל המטען הייעודי (Payload) נכלל ב-Intent מסוג ACTION_TECH_DISCOVERED
.
טבלה 1 מתארת איך מערכת שליחת התגים ממפה שדות TNF וסוגי שדות לסוגי MIME או למזהי URI. בנוסף, מוסבר אילו TNF לא ניתן למפות לסוג MIME או ל-URI.
במקרים כאלה, מערכת השליחה של התגים חוזרת ל-ACTION_TECH_DISCOVERED
.
לדוגמה, אם מערכת שליחת התגים נתקלת ברשומה מסוג TNF_ABSOLUTE_URI
, היא ממפה את שדה סוג האורך המשתנה של הרשומה הזו ל-URI. מערכת השליחה של התגים עוטפת את ה-URI הזה בשדה הנתונים של כוונה ACTION_NDEF_DISCOVERED
, יחד עם מידע נוסף על התג, כמו עומס העבודה. לעומת זאת, אם המערכת נתקלת ברשומה מסוג TNF_UNKNOWN
, היא יוצרת כוונה שמכילה את הטכנולוגיות של התג במקום זאת.
Type Name Format (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. |
הגדרת סוג רשומה (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 מבוסס על מטען ייעודי (payload). |
איך תגי NFC מועברים לאפליקציות
כשמערכת שליחת התגים מסיימת ליצור כוונה שמכילה את תג ה-NFC ואת פרטי הזיהוי שלו, היא שולחת את הכוונה לאפליקציה שמתעניינת בכך ומסננת את הכוונה. אם יש יותר מאפליקציה אחת שיכולה לטפל ב-Intent, מוצג בורר הפעילויות כדי שהמשתמש יוכל לבחור את הפעילות. מערכת השליחה של התגים מגדירה שלושה כוונות, שמפורטות לפי סדר העדיפות הגבוה ביותר לנמוך ביותר:
-
ACTION_NDEF_DISCOVERED
: ה-intent הזה משמש להפעלת פעילות כשנסרק תג שמכיל עומס נתונים של NDEF והוא מסוג מוכר. זאת ה-Intent בעדיפות הגבוהה ביותר, ומערכת שליחת התגים תנסה להתחיל פעילות עם כוונת הרכישה הזו לפני כל כוונה אחרת, כשהדבר יתאפשר. ACTION_TECH_DISCOVERED
: אם לא נרשמו פעילויות לטיפול בכוונהACTION_NDEF_DISCOVERED
, מערכת שליחת התגים תנסה להפעיל אפליקציה עם הכוונה הזו. הכוונה הזו מופעלת ישירות גם (בלי להפעיל קודם אתACTION_NDEF_DISCOVERED
) אם התג שנסרק מכיל נתוני NDEF שאי אפשר למפות לסוג MIME או ל-URI, או אם התג לא מכיל נתוני NDEF אבל הוא מתבסס על טכנולוגיית תגים ידועה.ACTION_TAG_DISCOVERED
: ה-Intent הזה מתחיל אם אין פעילויות שמטפלות באובייקטים מסוגACTION_NDEF_DISCOVERED
אוACTION_TECH_DISCOVERED
.
כך פועלת המערכת הבסיסית לשליחת תגים:
- כדאי לנסות להתחיל פעילות עם הכוונה שנוצרה על ידי מערכת שליחת התגים בזמן ניתוח תג ה-NFC (
ACTION_NDEF_DISCOVERED
אוACTION_TECH_DISCOVERED
). - אם אין פעילות שמסננת את הכוונה הזו, מנסים להפעיל פעילות עם הכוונה הבאה ברמת העדיפות הנמוכה ביותר (
ACTION_TECH_DISCOVERED
אוACTION_TAG_DISCOVERED
) עד שאפליקציה מסננת את הכוונה הזו או עד שמערכת שליחת התגים מנסה את כל הכוונות האפשריות. - אם אף אפליקציה לא מסננת אף אחד מהכוונות, לא עושים כלום.
כשאפשר, כדאי לעבוד עם הודעות NDEF ועם Intent מסוג 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
. אי אפשר לגשת לתכונות אחרות של התג או לפעולות קלט/פלט. רמת 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
.
סינון לפי Intentים של NFC
כדי להפעיל את האפליקציה כשמתבצע סריקה של תג NFC שאתם רוצים לטפל בו, האפליקציה יכולה לסנן את אחד, שניים או את כל שלושת הכוונות של 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
אם מסננים את הפעילות לפי ה-Intent 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
ראו עבודה עם טכנולוגיות תגים נתמכות במסמך Advanced 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 שנותחו מהתג. התוסף הזה הוא חובה ב-intents של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 (רמת API 14), ה-method createUri()
זמינה כדי לעזור לכם ליצור רשומות URI באופן אוטומטי. החל מ-Android 4.1 (רמת API 16), createExternal()
ו-createMime()
זמינים כדי לעזור ליצור רשומות MIME ורשומות NDEF חיצוניות. כדאי להשתמש ב-methods העוזרות האלה ככל האפשר, כדי למנוע טעויות ביצירה ידנית של רשומות 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 רק ברמת האפליקציה, בגלל האילוץ על שם החבילה, ולא ברמת הפעילות כמו בסינון לפי כוונה. אם רוצים לטפל ב-Intent ברמת הפעילות, צריך להשתמש במסנני Intent.
אם תג מכיל AAR, מערכת שליחת התגים נשלחת באופן הבא:
- כדאי לנסות להתחיל פעילות באמצעות מסנן Intent כרגיל. אם הפעילות שתואמת לכוונה תואמת גם ל-AAR, מתחילים את הפעילות.
- אם הפעילות שמסננת את Intent לא תואמת ל-AAR, אם יש כמה פעילויות שיכולות לטפל ב-Intent, או אם אין פעילות שמטפלת ב-Intent, צריך להפעיל את האפליקציה שצוינה ב-AAR.
- אם אף אפליקציה לא יכולה להתחיל באמצעות ה-AAR, עוברים אל Google Play כדי להוריד את האפליקציה על סמך ה-AAR.
הערה: אפשר לשנות את ההגדרות של AAR ושל מערכת שליחת הכוונות באמצעות מערכת שליחת הכוונות בחזית, שמאפשרת לפעילות בחזית לקבל עדיפות כשמתגלה תג NFC. בשיטה הזו, הפעילות חייבת להיות בחזית כדי לבטל את ה-AAR ואת המערכת של שליחת Intent.
אם אתם עדיין רוצים לסנן לפי תגים סרוקים שלא מכילים AAR, תוכלו להצהיר על מסנני כוונה כרגיל. האפשרות הזו שימושית אם האפליקציה שלכם מתעניינת בתגים אחרים שלא מכילים AAR. לדוגמה, יכול להיות שאתם רוצים להבטיח שהאפליקציה שלכם תטפל בתגים קנייניים שאתם פורסים, וגם בתגים כלליים שצדדים שלישיים פורסים. חשוב לזכור שמזהי AAR הם ספציפיים למכשירי Android 4.0 ואילך, כך שכאשר פורסים תגים, סביר להניח שתרצו להשתמש בשילוב של AAR וסוגי 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")} ); )