יכולות של מודעות ל-Wi-Fi מאפשרות למכשירים שפועלת בהם גרסת Android 8.0 (רמת API 26) וגם גבוה יותר כדי לגלות זה את זה ולהתחבר ישירות זה לזה ללא שום סוג אחר של את הקישוריות ביניהם. המודעות ל-Wi-Fi נקראת גם מוּדעוּת בסביבה Networking (NAN).
רשתות מודעות ל-Wi-Fi פועלות על ידי יצירת אשכולות עם מכשירים קרובים, או באמצעות יצירת אשכול חדש, אם המכשיר הוא הראשון באזור. הזה הקיבוץ באשכולות חל על כל המכשיר ומנוהל באמצעות ה-Wi-Fi שירות מערכת ידוע; לאפליקציות אין שליטה על ההתנהגות של אשכולות. שימוש באפליקציות את ממשקי ה-API של מודעות ל-Wi-Fi כדי לדבר עם שירות מערכת המודעות ל-Wi-Fi, שמנהל חומרת Wi-Fi Aware במכשיר.
ממשקי ה-API של מודעות ל-Wi-Fi מאפשרים לאפליקציות לבצע את הפעולות הבאות:
גילוי מכשירים אחרים: ל-API יש מנגנון למציאת מכשירים אחרים של מכשירים בקרבת מקום. התהליך מתחיל כשמכשיר אחד מפרסם אחד או שירותים נוספים לגילוי. לאחר מכן, כשמכשיר יירשם לערוץ אחד או יותר ונכנס לטווח ה-Wi-Fi של בעל האתר, המנוי מקבל התראה על כך שנמצא בעל אתר תואם. אחרי המנוי מגלה בעל אתר, והמנוי יכול לשלוח סרטון Shorts או ליצור חיבור לרשת עם המכשיר שאותר. המכשירים יכולים להיות בו-זמנית גם בעלי תוכן דיגיטלי וגם מנויים.
יצירת חיבור לרשת: אחרי ששני מכשירים יגלו את כל המכשירים הם יכולים ליצור חיבור דו-כיווני לרשת Wi-Fi Aware ללא נקודת גישה.
חיבור לרשתות Wi-Fi Aware תומך בתפוקה גבוהה יותר לאורך זמן במרחקים מאשר ב-Bluetooth בחיבורים. סוגי חיבורים אלה שימושיים עבור אפליקציות שמשתפים כמויות של נתונים בין משתמשים, לדוגמה, אפליקציות של שיתוף תמונות.
שיפורים ב-Android 13 (רמת API 33)
במכשירים עם Android בגרסה 13 (רמת API 33) ואילך עם תמיכה באפליקציות ללא התקנה
במצב תקשורת, אפליקציות יכולות להשתמש
PublishConfig.Builder.setInstantCommunicationModeEnabled()
ו-
SubscribeConfig.Builder.setInstantCommunicationModeEnabled()
אמצעים להשגת
להפעיל או להשבית את מצב התקשורת המיידית עבור בעל אתר או מנוי
סשן הגילוי. מצב תקשורת מיידית מאיץ את חילופי ההודעות,
גילוי שירות, וכל נתיב נתונים שהוגדר כחלק מבעל תוכן דיגיטלי או מנוי
סשן הגילוי. כדי לקבוע אם המכשיר תומך בתקשורת מיידית
משתמשים בשיטה isInstantCommunicationModeSupported()
.
שיפורים ב-Android 12 (רמת API 31)
מערכת Android 12 (רמת API 31) מוסיפה כמה שיפורים ל-Wi-Fi Aware:
- במכשירים שמותקנת בהם גרסת Android 12 (API ברמה 31) ואילך, אפשר להשתמש
onServiceLost()
התראה חוזרת (callback) כשהאפליקציה איבדה שירות שהתגלה כתוצאה הפסקת השירות או יציאה מהטווח. - ההגדרה של נתיבי נתונים של Wi-Fi Aware פשוטה יותר. גרסאות קודמות השתמשה בהודעות L2 כדי לספק את כתובת ה-MAC של היוזם, זמן אחזור. במכשירים עם Android מגרסה 12 ואילך, התגובה (שרת) כך שניתן יהיה לקבל כל אפליקציה להשוואה – כלומר, הוא לא צריך לדעת מראש את כתובת ה-MAC של המאתחל. הפעולה הזו האצת את נתיב הנתונים מאפשר להציג מספר קישורים מנקודה לנקודה באמצעות רשת אחת בלבד בקשה.
- אפליקציות שפועלות ב-Android מגרסה 12 ואילך יכולות להשתמש ב
WifiAwareManager.getAvailableAwareResources()
כדי לקבל את המספר של נתיבי הנתונים הזמינים כרגע, לפרסם סשנים, ולהירשם כמנויים. זה יכול לעזור לאפליקציה לקבוע אם יש מספיק משאבים זמינים לביצוע הפונקציונליות הרצויה.
הגדרה ראשונית
כדי להגדיר את האפליקציה לשימוש באיתור וברשתות של Wi-Fi Aware, צריך לבצע את את השלבים הבאים:
צריך לבקש את ההרשאות הבאות במניפסט של האפליקציה:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- If your app targets Android 13 (API level 33) or higher, you must declare the NEARBY_WIFI_DEVICES permission. --> <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" <!-- If your app derives location information from Wi-Fi APIs, don't include the "usesPermissionFlags" attribute. --> android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" <!-- If any feature in your app relies on precise location information, don't include the "maxSdkVersion" attribute. --> android:maxSdkVersion="32" />
בודקים אם המכשיר תומך ב-Wi-Fi Aware עם
PackageManager
API, כפי שמוצג בהמשך:Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
בודקים אם Wi-Fi Aware זמין כרגע. יכול להיות שחיבור Wi-Fi Aware פועל במכשיר, אבל ייתכן שהוא לא זמין כרגע כי המשתמש השבית Wi-Fi או מיקום. בהתאם ליכולות החומרה והקושחה שלהם, מכשירים מסוימים ייתכן שלא יתמוך ב-Wi-Fi Aware אם Wi-Fi ישיר, SoftAP או שיתוף אינטרנט בין מכשירים מחוברים לשימוש. כדי לבדוק אם רשת Wi-Fi Aware זמינה כרגע, צריך להתקשר
isAvailable()
הזמינות של Wi-Fi Aware יכולה להשתנות בכל שלב. האפליקציה שלך צריכה לרשום
BroadcastReceiver
כדי לקבלACTION_WIFI_AWARE_STATE_CHANGED
, שנשלחת בכל פעם שהזמינות משתנה. כשהאפליקציה מקבלת את כוונת שידור, היא צריכה למחוק את כל ההפעלות הקיימות (בהנחה שירות Wi-Fi Aware הופסק), ולאחר מכן יש לבדוק את את מצב הזמינות הנוכחי ולשנות את ההתנהגות בהתאם. לדוגמה:Kotlin
val wifiAwareManager = context.getSystemService(Context.WIFI_AWARE_SERVICE) as WifiAwareManager? val filter = IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED) val myReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { // discard current sessions if (wifiAwareManager?.isAvailable) { ... } else { ... } } } context.registerReceiver(myReceiver, filter)
Java
WifiAwareManager wifiAwareManager = (WifiAwareManager)context.getSystemService(Context.WIFI_AWARE_SERVICE) IntentFilter filter = new IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED); BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // discard current sessions if (wifiAwareManager.isAvailable()) { ... } else { ... } } }; context.registerReceiver(myReceiver, filter);
למידע נוסף, ראו שידורים.
השגת סשן
כדי להתחיל להשתמש ב-Wi-Fi Aware, האפליקציה צריכה לקבל
WifiAwareSession
על ידי התקשרות
attach()
. השיטה הזו
מבצע את הפעולות הבאות:
- הפעלת החומרה של Wi-Fi Aware.
- מתחבר או יוצר אשכול מודע ל-Wi-Fi.
- יצירת סשן Wi-Fi Aware עם מרחב שמות ייחודי שפועל מאגר לכל סשנים של גילוי שנוצרו בו.
אם האפליקציה תצורף בהצלחה, המערכת תריץ את הקובץ
התקשרות חזרה onAttached()
.
הקריאה החוזרת (callback) הזו מספקת אובייקט WifiAwareSession
שהאפליקציה צריכה להשתמש בו לכל פעולות סשן נוספות. אפליקציה יכולה להשתמש
סשן כדי לפרסם שירות או
הרשמה לשירות.
האפליקציה צריכה להתקשר
attach()
פעם אחת בלבד. אם המיקום
האפליקציה קוראת לattach()
מספר פעמים, כל שיחה מקבלת סשן שונה
מרחב שמות משלו. האפשרות הזו יכולה להיות שימושית בתרחישים מורכבים, אבל
בדרך כלל.
פרסום שירות
כדי להפוך שירות לגלוי, קוראים לפונקציה
השיטה publish()
,
כוללת את הפרמטרים הבאים:
PublishConfig
מציין את השם של שירות ומאפייני תצורה אחרים, כמו מסנן התאמה.DiscoverySessionCallback
מציין את הערך פעולות לביצוע כשאירועים מתרחשים, למשל כשהמנוי מקבל הודעה.
הנה דוגמה:
Kotlin
val config: PublishConfig = PublishConfig.Builder() .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME) .build() awareSession.publish(config, object : DiscoverySessionCallback() { override fun onPublishStarted(session: PublishDiscoverySession) { ... } override fun onMessageReceived(peerHandle: PeerHandle, message: ByteArray) { ... } })
Java
PublishConfig config = new PublishConfig.Builder() .setServiceName(“Aware_File_Share_Service_Name”) .build(); awareSession.publish(config, new DiscoverySessionCallback() { @Override public void onPublishStarted(PublishDiscoverySession session) { ... } @Override public void onMessageReceived(PeerHandle peerHandle, byte[] message) { ... } }, null);
אם הפרסום מצליח,
onPublishStarted()
בשיטת הקריאה החוזרת קוראים.
אחרי הפרסום, כשמכשירים שפועלות בהם אפליקציות תואמות למנויים עוברים אל
טווח ה-Wi-Fi של מכשיר הפרסום, המנויים מגלים את השירות. מתי
מנוי מגלה מוציא לאור, המו"ל לא מקבל
התראה; אם המנוי שולח הודעה למו"ל, אז
המו"ל מקבל התראה. במקרה כזה,
onMessageReceived()
בשיטת הקריאה החוזרת קוראים. אפשר להשתמש
ארגומנט אחד (PeerHandle
) מהשיטה הזו עד
לשלוח הודעה בחזרה למשתמש הרשום, או
ליצור חיבור אליו.
כדי להפסיק את הפרסום של השירות, צריך להתקשר
DiscoverySession.close()
סשנים מסוג Discovery משויכים להורה שלהם
WifiAwareSession
אם סשן ההורה הוא
נסגרה, וסשנים של גילוי שמשויכים אליו סגורים גם הם. בזמן מחיקה
גם האובייקטים סגורים, המערכת לא יכולה להבטיח שהם לא נמצאים בטווח
הסשנים סגורים, לכן מומלץ לקרוא באופן מפורש ל-close()
שיטות.
הרשמה לשירות
כדי להירשם לשירות, צריך להתקשר אל
אמצעי תשלום אחד (subscribe()
),
שכולל את הפרמטרים הבאים:
-
SubscribeConfig
מציין את השם של שירות להרשמה ולמאפייני תצורה אחרים, כמו התאמה DiscoverySessionCallback
מציין את הערך פעולות שיבוצעו כשאירועים מתרחשים, למשל כשמגלים בעל אתר.
הנה דוגמה:
Kotlin
val config: SubscribeConfig = SubscribeConfig.Builder() .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME) .build() awareSession.subscribe(config, object : DiscoverySessionCallback() { override fun onSubscribeStarted(session: SubscribeDiscoverySession) { ... } override fun onServiceDiscovered( peerHandle: PeerHandle, serviceSpecificInfo: ByteArray, matchFilter: List<ByteArray> ) { ... } }, null)
Java
SubscribeConfig config = new SubscribeConfig.Builder() .setServiceName("Aware_File_Share_Service_Name") .build(); awareSession.subscribe(config, new DiscoverySessionCallback() { @Override public void onSubscribeStarted(SubscribeDiscoverySession session) { ... } @Override public void onServiceDiscovered(PeerHandle peerHandle, byte[] serviceSpecificInfo, List<byte[]> matchFilter) { ... } }, null);
אם פעולת ההרשמה מצליחה, המערכת קוראת ל
onSubscribeStarted()
קריאה חוזרת (callback) באפליקציה. מאחר שאפשר להשתמש
ארגומנט SubscribeDiscoverySession
ב
קריאה חוזרת כדי לתקשר עם בעל אפליקציה אחרי שהאפליקציה גילתה את התג,
יש לשמור את ההפניה. אפשר לעדכן את סשן ההרשמה בכל שלב עד
שיחות
updateSubscribe()
בפעילות הגילוי.
בשלב הזה, המינוי שלכם ממתין לתוצאות של בעלי תוכן דיגיטלי תואמים
טווח Wi-Fi. במקרה כזה, המערכת עורכת את
onServiceDiscovered()
שיטת קריאה חוזרת. אפשר להשתמש ב-PeerHandle
מהקריאה החוזרת לארגומנט הזה כדי לשלוח הודעה או
ליצור חיבור אל המו"ל.
כדי להפסיק את ההרשמה לשירות, צריך להתקשר
DiscoverySession.close()
סשנים מסוג Discovery משויכים להורה שלהם
WifiAwareSession
אם סשן ההורה הוא
נסגרה, וסשנים של גילוי שמשויכים אליו סגורים גם הם. בזמן מחיקה
גם האובייקטים סגורים, המערכת לא יכולה להבטיח שהם לא נמצאים בטווח
הסשנים סגורים, לכן מומלץ לקרוא באופן מפורש ל-close()
שיטות.
שליחת הודעה
כדי לשלוח הודעה למכשיר אחר, צריך את האובייקטים הבאים:
DiscoverySession
. האובייקט הזה מאפשר כדי להתקשרsendMessage()
האפליקציה שלך מקבלתDiscoverySession
על ידי פרסום שירות או הרשמה לשירות .PeerHandle
של המכשיר האחר, כדי לנתב את הודעה. האפליקציה שלך מקבלת אישור של מכשיר אחרPeerHandle
באחת משתי הדרכים הבאות:- האפליקציה מפרסמת שירות ומקבלת הודעה ממנו.
האפליקציה שלך מקבלת את
PeerHandle
מonMessageReceived()
קריאה חוזרת. - האפליקציה רשומה לשירות. ואז, כשהיא מוצאת התאמה
בעל אפליקציה, האפליקציה שלך מקבלת
PeerHandle
מ-onServiceDiscovered()
קריאה חוזרת.
- האפליקציה מפרסמת שירות ומקבלת הודעה ממנו.
האפליקציה שלך מקבלת את
כדי לשלוח הודעה, צריך להתקשר
sendMessage()
לאחר מכן עשויות להתרחש הקריאות החוזרות הבאות:
- כשההודעה מתקבלת בהצלחה על ידי האפליקציה להשוואה, המערכת קוראת ל-
onMessageSendSucceeded()
להתקשרות חזרה באפליקציה שליחה. - כשהעמית מקבל הודעה, המערכת קוראת ל-
onMessageReceived()
באפליקציה הקבלה.
PeerHandle
נדרש כדי לתקשר עם אפליקציות להשוואה, אבל לא כדאי
מסתמכים עליו כמזהה קבוע של אפליקציות להשוואה. מזהים ברמה גבוהה יותר יכולים להיות
שבו האפליקציה משתמשת - מוטמעת בשירות הגילוי עצמו
בהודעות הבאות. אפשר להטמיע מזהה בשירות הגילוי עם
ה
setMatchFilter()
או
setServiceSpecificInfo()
שיטה של PublishConfig
או
SubscribeConfig
.
השיטה setMatchFilter()
משפיעה על הגילוי, ואילו
השיטה setServiceSpecificInfo()
לא משפיעה על הגילוי.
הטמעת מזהה בהודעה מרמזת על שינוי מערך הבייטים של ההודעה לכלול מזהה (לדוגמה, כשני הבייטים הראשונים).
יצירת חיבור
Wi-Fi Aware תומך ברשת שרת לקוח בין שני מכשירי Wi-Fi Aware.
כדי להגדיר את החיבור לשרת-לקוח:
להשתמש ב-Wi-Fi Aware Discovery כדי לפרסם שירות ( ולהירשם לשירות (ב לקוח).
אחרי שהמנוי מגלה את המוציא לאור, לשלוח הודעה מהמנוי אל אתר החדשות.
יצירת
ServerSocket
אצל בעל התוכן הדיגיטלי של המכשיר ולהגדיר או להשיג את היציאה שלו:Kotlin
val ss = ServerSocket(0) val port = ss.localPort
Java
ServerSocket ss = new ServerSocket(0); int port = ss.getLocalPort();
אפשר להשתמש ב
ConnectivityManager
כדי לבקש רשת Wi-Fi Aware אצל בעל התוכן הדיגיטלי באמצעותWifiAwareNetworkSpecifier
, שמציין את סשן הגילויPeerHandle
מהמנוי, שקיבלת מההודעה ששודרה על ידי המנוי:Kotlin
val networkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("somePassword") .setPort(port) .build() val myNetworkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(networkSpecifier) .build() val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { ... } override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { ... } override fun onLost(network: Network) { ... } } connMgr.requestNetwork(myNetworkRequest, callback);
Java
NetworkSpecifier networkSpecifier = new WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("somePassword") .setPort(port) .build(); NetworkRequest myNetworkRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(networkSpecifier) .build(); ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { ... } @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { ... } @Override public void onLost(Network network) { ... } }; ConnectivityManager connMgr.requestNetwork(myNetworkRequest, callback);
ברגע שבעל האפליקציה יבקש רשת, היא אמורה לשלוח הודעה למנויים.
לאחר שהמנוי יקבל את ההודעה מספק החדשות, עליך לבקש חיבור Wi-Fi רשת המודעות של המנוי שמשתמש באותה שיטה כמו באתר של בעל התוכן הדיגיטלי. מומלץ לא לציין יציאה בעת יצירת
NetworkSpecifier
השיטות המתאימות של קריאה חוזרת (callback) מופעלות כאשר חיבור הרשת זמין, השתנה או אבד.לאחר קריאה לשיטה
onAvailable()
אצל המנוי, אובייקטNetwork
זמין עם שאפשר לפתוחSocket
כדי לתקשר עםServerSocket
באתר של בעל האתר, אבל עליך לדעת כתובת ה-IPv6 והיציאה שלServerSocket
. אתם מקבלים את אובייקטNetworkCapabilities
סופקו בקריאה החוזרת (callback) שלonCapabilitiesChanged()
:Kotlin
val peerAwareInfo = networkCapabilities.transportInfo as WifiAwareNetworkInfo val peerIpv6 = peerAwareInfo.peerIpv6Addr val peerPort = peerAwareInfo.port ... val socket = network.getSocketFactory().createSocket(peerIpv6, peerPort)
Java
WifiAwareNetworkInfo peerAwareInfo = (WifiAwareNetworkInfo) networkCapabilities.getTransportInfo(); Inet6Address peerIpv6 = peerAwareInfo.getPeerIpv6Addr(); int peerPort = peerAwareInfo.getPort(); ... Socket socket = network.getSocketFactory().createSocket(peerIpv6, peerPort);
כאשר מסיים עם החיבור לרשת, התקשר
unregisterNetworkCallback()
טווח של אפליקציות להשוואה וגילוי מבוסס-מיקום
מכשיר עם מיקום באמצעות Wi-Fi RTT יכולות למדוד ישירות את המרחק אל אפליקציות אחרות ולהשתמש במידע הזה כדי להגביל את גילוי שירות ה-Wi-Fi Aware.
ממשק ה-Wi-Fi RTT API מאפשר טווח ישיר לעמית עם Wi-Fi Aware באמצעות כתובת ה-MAC או ה-PeerHandle שלה.
ניתן להגביל את החשיפה ל-Wi-Fi Aware כך שיגלו שירותים רק במסגרת
גבול וירטואלי מסוים. לדוגמה, אפשר להגדיר גבולות וירטואליים שמאפשרים גילוי
של מכשיר שמפרסם שירות "Aware_File_Share_Service_Name"
שלא
קרוב ל-3 מטרים (מצוין כ-3,000 מ"מ) ולא יותר מ-10 מטרים
(מצוין כ-10,000 מ"מ).
כדי להפעיל גבולות וירטואליים, בעל התוכן הדיגיטלי וגם המנוי צריכים לבצע את הפעולות הבאות:
בעל התוכן הדיגיטלי חייב להפעיל טווח בשירות שפורסם באמצעות setRangingEnabled(true).
אם בעל התוכן הדיגיטלי לא מפעיל טווח, אזי מגבלות כלשהן שקשורות לגבולות וירטואליים שהמנוי התעלל מהן, ומתבצע גילוי רגיל, תוך התעלמות מהמרחק.
המנוי חייב לציין גבולות וירטואליים באמצעות שילוב כלשהו של setMinDestinationMm וגם setMaxMaxMm
בכל אחד מהערכים האלה, מרחק שלא צוין לא מרמז על מגבלה. מציין רק המרחק המקסימלי מייצג מרחק מינימלי של 0. ציון של רק מרחק מינימלי לא מרמז על מספר מקסימלי.
כשמתגלה שירות אפליקציות להשוואה בתוך גבולות וירטואליים, onServiceDiscoveredWithinRange מופעלת קריאה חוזרת (callback), שמציינת את המרחק שנמדד מהעמית. לאחר מכן ניתן לקרוא לממשק ה-API של RTT ישיר ב-Wi-Fi לפי הצורך כדי למדוד את המרחק במועדים מאוחרים יותר.