Funkcje Wi-Fi Aware umożliwiają urządzeniom z Androidem 8.0 (poziom interfejsu API 26) oraz i odkrywać innych i nawiązywać z nimi bezpośredni kontakt, bez żadnego między nimi. Wi-Fi Aware jest też znane jako Znajomość sąsiadów Networking (NAN).
Sieć Wi-Fi Aware tworzy klastry z sąsiadującymi urządzeniami. przez utworzenie nowego klastra, jeśli urządzenie jest pierwsze w danym obszarze. Ten Grupowanie ma zastosowanie do całego urządzenia i jest zarządzane przez Wi-Fi usługa systemowa Aware; aplikacje nie mają kontroli nad zachowaniem grupowania. Aplikacje używają interfejsów API Wi-Fi Aware, by komunikować się z usługą systemową Wi-Fi Aware, która zarządza sprzęt Wi-Fi Aware na urządzeniu.
Interfejsy Wi-Fi Aware API umożliwiają aplikacjom wykonywanie tych operacji:
Wykrywanie innych urządzeń: interfejs API ma mechanizm znajdowania innych urządzeń. urządzenia w pobliżu. Proces rozpoczyna się, gdy jedno urządzenie opublikuje nowe lub bardziej wykrywalne usługi. Następnie, gdy urządzenie zasubskrybuje co najmniej i połączenia się z siecią Wi-Fi wydawcy, subskrybent otrzymuje powiadomienie o znalezieniu pasującego wydawcy. Po gdy subskrybent odkrywa wydawcę, może wysłać lub nawiązać połączenie sieciowe z wykrytym urządzeniem. Urządzeniami mogą być równocześnie wydawców i subskrybentów.
Utwórz połączenie sieciowe: gdy 2 urządzenia wykryją każde a potem mogą utworzyć dwukierunkowe połączenie sieciowe Wi-Fi Aware bez punktu dostępu.
Połączenia sieciowe Wi-Fi Aware obsługują większą przepustowość w dłuższym okresie odległości niż Bluetooth połączeń. Tego typu połączenia są przydatne w aplikacjach, które dzielą się dużą ilością danych ilości danych przesyłanych między użytkownikami, np. w aplikacjach do udostępniania zdjęć.
Ulepszenia Androida 13 (poziom interfejsu API 33)
Na urządzeniach z Androidem 13 (poziom interfejsu API 33) lub nowszym, które obsługują aplikacje błyskawiczne
w trybie komunikacji, aplikacje mogą używać
PublishConfig.Builder.setInstantCommunicationModeEnabled()
i
SubscribeConfig.Builder.setInstantCommunicationModeEnabled()
metod do
włączanie i wyłączanie trybu komunikacji błyskawicznej w przypadku wydawcy lub subskrybenta
i odkrywania. Tryb błyskawicznej komunikacji przyspiesza wymianę wiadomości,
wykrywanie usług oraz wszelkie ścieżki danych skonfigurowane dla wydawcy lub subskrybenta
i odkrywania. Aby określić, czy urządzenie obsługuje komunikację błyskawiczną
użyj metody isInstantCommunicationModeSupported()
.
Ulepszenia Androida 12 (poziom interfejsu API 31)
Android 12 (poziom interfejsu API 31) wprowadza kilka ulepszeń w Wi-Fi Aware:
- Na urządzeniach z Androidem 12 (poziom interfejsu API 31) lub nowszym możesz używać funkcji
onServiceLost()
wywołanie zwrotne, aby otrzymywać alerty, gdy aplikacja utraci wykrytą usługę z powodu usługa zatrzymuje się lub znajduje się poza zasięgiem. - Konfiguracja ścieżek danych Aware Aware została uproszczona. Wcześniejsze wersje wykorzystała wiadomości L2 do dostarczenia adresu MAC inicjatora, związane z opóźnieniem. Na urządzeniach z Androidem 12 lub nowszym (serwer) można skonfigurować tak, aby akceptował dowolny peer, co oznacza, że nie jest wymagany adres MAC inicjatora. Przyspiesza to ścieżkę danych i umożliwia korzystanie z wielu linków punkt-punkt w jednej sieci użytkownika.
- Aplikacje działające na Androidzie 12 lub nowszym mogą używać
WifiAwareManager.getAvailableAwareResources()
aby poznać liczbę obecnie dostępnych ścieżek danych, opublikować sesje, i sesji subskrypcji. Może to pomóc aplikacji określić, czy wystarczającą ilość dostępnych zasobów, aby uruchomić pożądaną funkcję.
Konfiguracja początkowa
Aby skonfigurować aplikację, tak aby wykorzystywała wykrywanie Wi-Fi Aware i korzystanie z sieci, wykonaj następujące kroki:
W pliku manifestu aplikacji poproś o te uprawnienia:
<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" />
Sprawdź, czy urządzenie obsługuje Wi-Fi Aware za pomocą
PackageManager
API, jak pokazano poniżej:Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
Sprawdź, czy funkcja Wi-Fi Aware jest obecnie dostępna. Włączono Wi-Fi Aware tego urządzenia, ale mogą być niedostępne, ponieważ użytkownik wyłączył Wi-Fi lub Lokalizacja. W zależności od możliwości sprzętowych i oprogramowania może nie obsługiwać Wi-Fi Aware, jeśli włączone jest połączenie Wi-Fi Direct, SoftAP lub tethering i ich używanie. Aby sprawdzić, czy funkcja Wi-Fi Aware jest obecnie dostępna, zadzwoń pod numer
isAvailable()
Dostępność Wi-Fi Aware może się zmienić w każdej chwili. Aplikacja powinna zarejestruj
BroadcastReceiver
, aby otrzymaćACTION_WIFI_AWARE_STATE_CHANGED
, który jest wysyłany przy każdej zmianie dostępności. Gdy aplikacja otrzyma intencji, powinien odrzucić wszystkie istniejące sesje (przy założeniu, usługa Wi-Fi Aware została zakłócona), a następnie sprawdź obecny stan dostępności i odpowiednio dostosować jego działanie. Na przykład: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ęcej informacji znajdziesz w artykule Komunikaty.
Uzyskiwanie sesji
Aby zacząć korzystać z Wi-Fi Aware, aplikacja musi uzyskać
WifiAwareSession
przez połączenie
attach()
Ta metoda
wykonuje te działania:
- Włącza sprzęt Wi-Fi Aware.
- Dołącza do klastra Wi-Fi Aware lub tworzy go.
- Tworzy sesję Wi-Fi Aware z unikalną przestrzenią nazw, która pełni funkcję dla wszystkich utworzonych w nim sesji wykrywania.
Jeśli aplikacja się przyłączy, system wykona polecenie
onAttached()
oddzwonienie.
To wywołanie zwrotne udostępnia obiekt WifiAwareSession
których aplikacja ma używać we wszystkich kolejnych operacjach sesji. Aplikacja może używać funkcji
sesja opublikowania usługi lub
zasubskrybować usługę.
Aplikacja powinna zadzwonić
attach()
tylko raz. Jeśli
aplikacja wywołuje attach()
aplikacji wiele razy, dla każdego połączenia jest odbierana inna sesja, z której każda
ma własną przestrzeń nazw. Może to być przydatne w skomplikowanych scenariuszach, ale powinno
których zasadniczo można uniknąć.
Publikowanie usługi
Aby ustawić usługę jako wykrywalną, wywołaj metodę
publish()
, która
przyjmuje następujące parametry:
PublishConfig
określa nazwę i innych właściwości konfiguracji, takich jak filtr dopasowania.DiscoverySessionCallback
określa działania, które mają być wykonywane w przypadku wystąpienia zdarzeń, np. gdy subskrybent odbiera wiadomość.
Oto przykład:
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);
Jeśli publikowanie się uda,
onPublishStarted()
metoda wywołania zwrotnego.
Po opublikowaniu urządzenia z odpowiednimi aplikacjami dla subskrybentów będą przenoszone do
w zasięgu Wi-Fi urządzenia wydawniczego, subskrybenci odkrywają usługę. Kiedy
gdy subskrybent znajduje wydawcę, wydawca nie otrzymuje
powiadomienia; jeśli subskrybent wyśle wiadomość do wydawcy, to
wydawca otrzyma powiadomienie. W takim przypadku
onMessageReceived()
metoda wywołania zwrotnego. Za pomocą
PeerHandle
argument z tej metody do
Odeślij wiadomość do subskrybenta lub
utworzyć z nim połączenie.
Aby zakończyć publikowanie usługi, wywołaj połączenie
DiscoverySession.close()
Sesje odkrywania są powiązane z rodzicami.
WifiAwareSession
Jeśli sesja nadrzędna to
powiązane z nim sesje odkrywania również zostaną zamknięte. Porzucone
nawet zamknięte obiekty, system nie gwarantuje,
że są poza zakresem
są zamknięte, dlatego zalecamy wywołanie metody close()
.
Subskrybowanie usługi
Aby zasubskrybować usługę, wywołaj metodę
subscribe()
,
, który przyjmuje następujące parametry:
-
SubscribeConfig
określa nazwę usługi, którą chcesz subskrybować, oraz innych właściwości konfiguracji, takich jak dopasowanie filtr. DiscoverySessionCallback
określa działania, które mają być wykonywane w razie wystąpienia zdarzeń, np. po wykryciu wydawcy.
Oto przykład:
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);
Jeśli operacja subskrypcji się powiedzie, system wywoła metodę
onSubscribeStarted()
oddzwanianie. Za pomocą
SubscribeDiscoverySession
w funkcji
gdy aplikacja ją wykryje, możesz użyć funkcji wywołania zwrotnego
powinien zapisać to odwołanie. Sesję subskrypcji możesz zaktualizować w dowolnym momencie,
połączenia
updateSubscribe()
podczas sesji odkrywania.
Na tym etapie Twoja subskrypcja czeka na pojawienie się odpowiednich wydawców.
Zasięg Wi-Fi. W takim przypadku system wykonuje polecenie
onServiceDiscovered()
metody wywołania zwrotnego. Za pomocą usługi PeerHandle
argumentu z tym wywołaniem zwrotnym na send a message lub
utworzyć połączenie z tym wydawcą.
Aby zrezygnować z subskrypcji usługi, zadzwoń pod numer
DiscoverySession.close()
Sesje odkrywania są powiązane z rodzicami.
WifiAwareSession
Jeśli sesja nadrzędna to
powiązane z nim sesje odkrywania również zostaną zamknięte. Porzucone
nawet zamknięte obiekty, system nie gwarantuje,
że są poza zakresem
są zamknięte, dlatego zalecamy wywołanie metody close()
.
Wyślij wiadomość
Aby wysłać wiadomość na inne urządzenie, potrzebne będą te obiekty:
DiscoverySession
. Ten obiekt umożliwia Ci zadzwonićsendMessage()
Twoja aplikacja uzyskujeDiscoverySession
przez: opublikowanie usługi lub subskrybowanie usługi.PeerHandle
drugiego urządzenia, aby kierować . Twoja aplikacja uzyskuje dostęp do usługi na innym urządzeniuPeerHandle
na jeden z dwóch sposobów:- Twoja aplikacja publikuje usługę i otrzymuje wiadomość od subskrybenta.
Twoja aplikacja uzyskuje
PeerHandle
zonMessageReceived()
oddzwanianie. - Aplikacja subskrybuje usługę. Po wykryciu dopasowania
wydawca, aplikacja uzyskuje
PeerHandle
wonServiceDiscovered()
. oddzwanianie.
- Twoja aplikacja publikuje usługę i otrzymuje wiadomość od subskrybenta.
Twoja aplikacja uzyskuje
Aby wysłać wiadomość, zadzwoń pod numer
sendMessage()
mogą wystąpić te wywołania zwrotne:
- Po pomyślnym odebraniu komunikatu przez peera system wywołuje metodę
onMessageSendSucceeded()
wywołanie zwrotne w aplikacji wysyłanie. - Gdy połączenie równorzędne otrzyma wiadomość, system wywoła metodę
onMessageReceived()
wywołanie zwrotne w aplikacji receiving.
Choć interfejs PeerHandle
jest wymagany do komunikacji z innymi wydawcami, nie należy
korzystać z niej jako stałego identyfikatora elementu równorzędnego. Identyfikatory wyższego poziomu mogą być
używane przez aplikację – osadzone w samej usłudze wykrywania lub w
kolejne wiadomości. Identyfikator możesz umieścić w usłudze wykrywania za pomocą
setMatchFilter()
lub
setServiceSpecificInfo()
metoda PublishConfig
lub
SubscribeConfig
.
Metoda setMatchFilter()
wpływa na wykrywanie, a metoda
Metoda setServiceSpecificInfo()
nie wpływa na wykrywanie.
Umieszczenie identyfikatora w wiadomości wymaga modyfikacji tablicy bajtów wiadomości dołączyć identyfikator (np. jako pierwsze kilka bajtów).
Utwórz połączenie
Wi-Fi Aware obsługuje sieć klient-serwer między dwoma urządzeniami Wi-Fi Aware.
Aby skonfigurować połączenie klient-serwer:
Użyj wykrywania Wi-Fi Aware, by opublikować usługę (w serwera) i zasubskrybuj usługę (w klienta).
Gdy subskrybent odkryje wydawcę, Wyślij wiadomość od subskrybenta do wydawcy.
Tworzenie
ServerSocket
u wydawcy i ustawić lub uzyskać jego port:Kotlin
val ss = ServerSocket(0) val port = ss.localPort
Java
ServerSocket ss = new ServerSocket(0); int port = ss.getLocalPort();
Skorzystaj z narzędzia
ConnectivityManager
, aby: żądania sieci Wi-Fi Aware u wydawcy za pomocąWifiAwareNetworkSpecifier
, określając sesję wykrywania iPeerHandle
subskrybenta, uzyskane z wiadomości przesłanej przez subskrybenta: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);
Gdy wydawca poprosi o dostęp do sieci, Wyślij wiadomość do subskrybenta.
Gdy subskrybent otrzyma wiadomość od wydawcy, poproś o połączenie z siecią Wi-Fi Sieć u subskrybenta jest rozpoznawana w ten sam sposób co u wydawcy. Tak nie określaj portu podczas tworzenia
NetworkSpecifier
odpowiednie metody wywołania zwrotnego są wywoływane, gdy połączenie sieciowe jest dostępnych, zmienionych lub utraconych.Po wywołaniu metody
onAvailable()
przez subskrybenta ObiektNetwork
jest dostępny w: otwórzSocket
, aby się z nim skontaktować zServerSocket
na poziomie wydawcy. Adres IPv6 i port serweraServerSocket
. Dane te pochodzą zNetworkCapabilities
obiekt podano w wywołaniu zwrotnymonCapabilitiesChanged()
: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);
Po zakończeniu nawiązywania połączenia sieciowego zadzwoń pod numer
unregisterNetworkCallback()
Różne grupy rówieśników i odkrywanie z uwzględnieniem lokalizacji
Urządzenie z lokalizacją RTT przez Wi-Fi. mogą bezpośrednio mierzyć odległość od rówieśników i używać tych informacji do ograniczyć wykrywanie usług Wi-Fi Aware.
Interfejs Wi-Fi RTT API umożliwia bezpośrednie docieranie do równorzędnej sieci Wi-Fi Aware za pomocą Adres MAC lub jego PeerHandle.
Funkcja wykrywania Wi-Fi Aware może zostać ograniczona do wykrywania usług tylko w
dla konkretnego geofencingu. Można na przykład skonfigurować geofencing, który umożliwia wykrywanie
urządzenia publikującego usługę "Aware_File_Share_Service_Name"
, która nie jest
bliżej niż 3 metry (określone jako 3000 mm) i nie dalej niż 10 metrów
(10 000 mm).
Aby włączyć geofencing, zarówno wydawca, jak i subskrybent muszą wykonać działanie:
Wydawca musi włączyć zakres w opublikowanej usłudze za pomocą funkcji setRangingEnabled(true).
Jeśli wydawca nie włączy zakresu, wszelkie ograniczenia geofencingu określone przez subskrybenta są ignorowane, a wykrywanie odbywa się normalnie. ignorując odległość.
Subskrybent musi określić geofence za pomocą kombinacji setMinOdległośćMm oraz setMaxOdległośćMm.
W przypadku każdej z tych wartości nieokreślony dystans oznacza brak limitu. Tylko określanie maksymalna odległość oznacza minimalną odległość równą 0. Parametr minimalna odległość nie oznacza maksymalnej odległości.
W przypadku wykrycia w obszarze geofencingu usługi równorzędnej onServiceDiscoveredWithinRange (w języku angielskim) wywołanie zwrotne, które podaje zmierzoną odległość do elementu równorzędnego. Interfejs Direct Wi-Fi RTT API można następnie w razie potrzeby wywoływać w celu pomiaru odległości później.