Wi-Fi Aware-Funktionen sind für Geräte mit Android 8.0 (API-Level 26) und und eine direkte Verbindung zueinander herstellen, ohne dass Konnektivität zwischen ihnen. Wi-Fi Aware wird auch als Neighbor Awareness Awareness bezeichnet. Netzwerk (NAN).
Bei einem Wi-Fi Aware-Netzwerk werden Cluster mit benachbarten Geräten gebildet. indem ein neuer Cluster erstellt wird, wenn das Gerät das erste Gerät in einem Bereich ist. Dieses Das Clustering-Verhalten gilt für das gesamte Gerät und wird vom WLAN verwaltet. Ein bewusster Systemdienst: Anwendungen haben keine Kontrolle über das Clustering-Verhalten. App-Nutzung über die Wi-Fi Aware APIs mit dem Wi-Fi Aware-Systemdienst kommunizieren, der die Wi-Fi Aware-Hardware des Geräts.
Mit den Wi-Fi Aware APIs können Apps die folgenden Vorgänge ausführen:
Andere Geräte entdecken:Die API hat einen Mechanismus, mit dem Geräte in der Nähe. Der Prozess beginnt, wenn ein Gerät ein Gerät veröffentlicht oder besser auffindbaren Diensten. Wenn ein Gerät ein oder mehrere Abos abonniert und in den WLAN-Bereich des Verlags oder Webpublishers gelangt, erhält der Abonnent dass ein übereinstimmender Publisher gefunden wurde. Nach dem einen Verlag oder Webpublisher entdeckt, kann er entweder ein kurzes oder eine Netzwerkverbindung mit dem erkannten Gerät herstellen. Geräte können gleichzeitig Publisher und Abonnenten sein.
Netzwerkverbindung herstellen:Nachdem zwei Geräte jedes Gerät erkannt haben andere können sie eine Bidirektionale Wi-Fi Aware-Netzwerkverbindung ohne Zugangspunkt.
Wi-Fi Aware-Netzwerkverbindungen unterstützen höhere Durchsatzraten bei längeren Entfernungen als bei Bluetooth Verbindungen. Diese Verbindungstypen eignen sich für Apps, die große große Datenmengen zwischen Nutzern, z. B. in Apps für das Teilen von Fotos.
Verbesserungen unter Android 13 (API-Level 33)
Auf Geräten mit Android 13 (API-Level 33) und höher, die die Instant-Version
Kommunikationsmodus verwenden, können Apps
PublishConfig.Builder.setInstantCommunicationModeEnabled()
und
SubscribeConfig.Builder.setInstantCommunicationModeEnabled()
-Methoden zum
Modus für sofortige Kommunikation für einen Publisher oder Abonnenten aktivieren oder deaktivieren
Discovery-Sitzung. Der Modus für die sofortige Kommunikation
beschleunigt den Nachrichtenaustausch,
Diensterkennung und alle Datenpfade, die als Teil eines Publishers oder Abonnenten eingerichtet wurden
Discovery-Sitzung. Bestimmen, ob ein Gerät die Sofortkommunikation unterstützt
verwenden Sie die Methode isInstantCommunicationModeSupported()
.
Verbesserungen unter Android 12 (API-Level 31)
Android 12 (API-Level 31) bietet einige Verbesserungen für Wi‐Fi Aware:
- Auf Geräten mit Android 12 (API-Level 31) oder höher kannst du die
onServiceLost()
um benachrichtigt zu werden, wenn in deiner App ein erkannter Dienst aufgrund des wenn der Dienst anhält oder sich außerhalb des zulässigen Bereichs befindet. - Die Einrichtung von Wi-Fi Aware-Datenpfaden wurde vereinfacht. Frühere Versionen L2-Messaging verwendet, um die MAC-Adresse des Initiators bereitzustellen, die verursachte Latenz. Auf Geräten mit Android 12 und höher (Server) kann so konfiguriert werden, dass er jeden Peer akzeptiert. um die MAC-Adresse des Initators zu erfahren. Dadurch wird der Datenpfad mehrere Point-to-Point-Links mit nur einem Netzwerk ermöglichen
- Apps mit Android 12 oder höher können die
WifiAwareManager.getAvailableAwareResources()
die Anzahl der aktuell verfügbaren Datenpfade, Veröffentlichungssitzungen, und abonnieren Sitzungen. So kann die App feststellen, ob genügend Ressourcen verfügbar sind, um die gewünschte Funktionalität auszuführen.
Ersteinrichtung
Um Ihre App für die Verwendung der Wi-Fi Aware-Erkennung und -Netzwerk einzurichten, führen Sie die folgenden Schritten:
Fordern Sie im Manifest Ihrer App die folgenden Berechtigungen an:
<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" />
Überprüfe, ob das Gerät Wi-Fi Aware unterstützt mit der
PackageManager
API, wie unten gezeigt:Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
Prüfen Sie, ob WLAN Aware derzeit verfügbar ist. Wi-Fi Aware ist möglicherweise vorhanden auf Gerät, aber möglicherweise nicht verfügbar, weil der Nutzer das Gerät deaktiviert hat WLAN oder Standort. Je nach Hardware- und Firmwarefunktionen können einige Geräte unterstützt möglicherweise Wi-Fi Aware nicht, wenn Wi-Fi Direct, SoftAP oder Tethering aktiviert ist verwenden. Um herauszufinden, ob WLAN Aware derzeit verfügbar ist, rufen Sie
isAvailable()
Die Verfügbarkeit von Wi-Fi Aware kann sich jederzeit ändern. Ihre App sollte
BroadcastReceiver
registrieren, umACTION_WIFI_AWARE_STATE_CHANGED
, die gesendet wird, wenn sich die Verfügbarkeit ändert. Wenn deine App die Broadcast-Intent alle vorhandenen Sitzungen verwerfen der Wi-Fi Aware-Dienst unterbrochen wurde, und überprüfe die den aktuellen Verfügbarkeitsstatus und passen das Verhalten entsprechend an. Beispiel: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);
Weitere Informationen finden Sie unter Broadcasts.
Sitzung abrufen
Um Wi-Fi Aware nutzen zu können, benötigt deine App ein
WifiAwareSession
über folgenden Anruf
attach()
. Diese Methode
führt Folgendes aus:
- Aktiviert die Wi-Fi Aware-Hardware.
- Stellt einen Wi-Fi Aware-Cluster her oder bildet ihn.
- Erstellt eine Wi-Fi Aware-Sitzung mit einem eindeutigen Namespace, der als Container für alle darin erstellten Erkennungssitzungen.
Wenn die Anwendung erfolgreich angehängt wurde, führt das System die
onAttached()
-Callback.
Dieser Callback stellt ein WifiAwareSession
-Objekt bereit.
die Ihre App für alle weiteren Sitzungsvorgänge verwenden soll. Eine App kann das
um einen Dienst zu veröffentlichen, oder
einen Dienst abonnieren.
Ihre App sollte folgende Aktionen ausführen:
attach()
nur einmal. Wenn
Deine App ruft attach()
auf
erhalten die App für jeden Anruf eine andere Sitzung,
eigenen Namespace. Dies kann in komplexen Szenarien nützlich sein,
im Allgemeinen vermieden werden.
Dienst veröffentlichen
Um einen Dienst auffindbar zu machen, rufen Sie die Methode
publish()
-Methode, die
Für sind folgende Parameter erforderlich:
PublishConfig
gibt den Namen der und andere Konfigurationseigenschaften wie den Abgleichsfilter an.DiscoverySessionCallback
gibt die Aktionen, die ausgeführt werden sollen, wenn Ereignisse eintreten, z. B. wenn der Abonnent eine Nachricht.
Beispiel:
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);
Wenn die Veröffentlichung erfolgreich ist,
onPublishStarted()
Callback-Methode aufgerufen.
Geräte, auf denen übereinstimmende Abonnenten-Apps ausgeführt werden, werden nach der Veröffentlichung in den
WLAN-Reichweite des Verlagsgeräts erkennen die Abonnenten den Dienst. Wann?
ein Abonnent einen Verlag oder Webpublisher entdeckt, erhält der Verlag oder Webpublisher
Mitteilung; wenn der Abonnent dem
Publisher eine Nachricht sendet,
erhält der Publisher eine Benachrichtigung. In diesem Fall
onMessageReceived()
Callback-Methode aufgerufen. Sie können die
Argument PeerHandle
von dieser Methode in
sende eine Nachricht an den Abonnenten oder
erstellen Sie eine Verbindung.
Um die Veröffentlichung des Dienstes zu beenden, rufen Sie
DiscoverySession.close()
Discovery-Sitzungen sind mit dem übergeordneten Element verknüpft
WifiAwareSession
Wenn die übergeordnete Sitzung
geschlossen wurden, werden die zugehörigen Discovery-Sitzungen ebenfalls geschlossen. Während verworfen
ebenfalls geschlossen sind, gibt das System keine Garantie,
wenn die Objekte nicht im Projektumfang enthalten sind,
Sitzungen sind geschlossen, daher empfehlen wir, den close()
explizit aufzurufen
.
Dienst abonnieren
Rufen Sie zum Abonnieren eines Dienstes die Methode
Methode subscribe()
,
Hierfür werden folgende Parameter verwendet:
-
SubscribeConfig
gibt den Namen der zu abonnierender Dienst und andere Konfigurationsattribute wie „match“ aus. DiscoverySessionCallback
gibt die Aktionen, die ausgeführt werden sollen, wenn Ereignisse eintreten, z. B. wenn ein Publisher entdeckt wird
Beispiel:
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);
Wenn der Abovorgang erfolgreich ist, ruft das System die
onSubscribeStarted()
in deiner App zurück. Mit der Funktion
SubscribeDiscoverySession
-Argument im
um mit einem Publisher zu kommunizieren, nachdem Ihre App einen gefunden hat,
diese Referenz speichern. Sie können die Abonnieren-Sitzung jederzeit aktualisieren, indem Sie
Anrufen
updateSubscribe()
in der Discovery-Sitzung.
Zu diesem Zeitpunkt wird für Ihr Abo gewartet, bis übereinstimmende Publisher in Ihrem Konto angezeigt werden
WLAN-Reichweite. In diesem Fall führt das System
onServiceDiscovered()
. Sie können die PeerHandle
verwenden
Argument aus diesem Callback, um eine Nachricht zu senden, oder
eine Verbindung zu diesem Publisher herstellen.
Wenn Sie einen Dienst nicht mehr abonnieren möchten, rufen Sie
DiscoverySession.close()
Discovery-Sitzungen sind mit dem übergeordneten Element verknüpft
WifiAwareSession
Wenn die übergeordnete Sitzung
geschlossen wurden, werden die zugehörigen Discovery-Sitzungen ebenfalls geschlossen. Während verworfen
ebenfalls geschlossen sind, gibt das System keine Garantie,
wenn die Objekte nicht im Projektumfang enthalten sind,
Sitzungen sind geschlossen, daher empfehlen wir, den close()
explizit aufzurufen
.
Eine Nachricht posten
Wenn Sie eine Nachricht an ein anderes Gerät senden möchten, benötigen Sie folgende Objekte:
Ein
DiscoverySession
. Mit diesem Objekt können Sie zum AnrufensendMessage()
Deine App erhält einDiscoverySession
, indem du entweder das Veröffentlichen eines Dienstes oder das Abonnieren einesDen
PeerHandle
des anderen Geräts, um den angezeigt. Deine App erhält die Berechtigungen eines anderen GerätsPeerHandle
auf eine der beiden folgenden Arten:- Ihre App veröffentlicht einen Dienst und empfängt eine Nachricht von einem Abonnenten.
Ihre App erhält die
PeerHandle
vononMessageReceived()
Callback des Nutzers an. - Ihre App abonniert einen Dienst. Wenn eine Übereinstimmung gefunden wird,
erhält Ihre App
PeerHandle
vomonServiceDiscovered()
Callback des Nutzers an.
- Ihre App veröffentlicht einen Dienst und empfängt eine Nachricht von einem Abonnenten.
Ihre App erhält die
Um eine Nachricht zu senden, ruf an
sendMessage()
Die
können dann folgende Callbacks auftreten:
- Wenn die Nachricht erfolgreich vom Peer empfangen wurde, ruft das System die
onMessageSendSucceeded()
in der Senden-App zurückgegeben. - Wenn der Peer eine Nachricht erhält, ruft das System die
onMessageReceived()
in der empfangenden App zurück.
Obwohl die PeerHandle
für die Kommunikation mit Gleichgesinnten erforderlich ist, sollten Sie Folgendes nicht tun:
als permanente Peer-ID. Übergeordnete Kennungen können
die von der Anwendung verwendet werden und in den Discovery-Dienst selbst oder in
nachfolgenden Nachrichten. Sie können eine Kennung mit
die
setMatchFilter()
oder
setServiceSpecificInfo()
PublishConfig
- oder
SubscribeConfig
Die
Die setMatchFilter()
-Methode wirkt sich auf die Erkennung aus, während die Methode
Die Methode setServiceSpecificInfo()
wirkt sich nicht auf die Erkennung aus.
Das Einbetten einer Kennung in eine Nachricht impliziert das Ändern des Nachrichtenbyte-Arrays auf eine Kennung enthalten (z. B. als erstes Byte).
Verbindung erstellen
Wi-Fi Aware unterstützt Client-Server-Netzwerke zwischen zwei Wi-Fi Aware-Geräten.
So richten Sie die Client-Server-Verbindung ein:
Nutzen Sie die Wi-Fi Aware-Erkennung, um einen Dienst zu veröffentlichen (auf der und abonnieren einen Dienst (auf der Client).
Sobald der Abonnent den Verleger entdeckt hat, Sende eine Nachricht vom Abonnenten an den Publisher.
ServerSocket
auf dem Publisher starten Gerät und legen Sie den Port fest oder rufen Sie diesen ab:Kotlin
val ss = ServerSocket(0) val port = ss.localPort
Java
ServerSocket ss = new ServerSocket(0); int port = ss.getLocalPort();
Mit dem
ConnectivityManager
können Sie Wi-Fi Aware-Netzwerk beim Verlag oder Webpublisher über eineWifiAwareNetworkSpecifier
, unter Angabe der Erkennungssitzung und derPeerHandle
des Abonnenten, die Sie aus der vom Abonnenten übertragenen Nachricht erhalten haben: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);
Sobald der Publisher ein Werbenetzwerk anfordert, Sende eine Nachricht an den Abonnenten.
Fordere ein WLAN an, sobald der Abonnent die Nachricht vom Verlag oder Webpublisher erhalten hat Aware-Netzwerk beim Abonnenten mit derselben Methode wie beim Verlag oder Webpublisher. Das sollten Sie tun: keinen Port beim Erstellen der
NetworkSpecifier
Die werden die entsprechenden Callback-Methoden aufgerufen, wenn die Netzwerkverbindung verfügbar, geändert oder verloren gehen.Wenn die Methode
onAvailable()
für den Abonnenten aufgerufen wird, ObjektNetwork
ist verfügbar mit Sie können einSocket
öffnen, mit demServerSocket
auf dem Herausgeber. Sie müssen jedoch wissen, IPv6-Adresse und -Port vonServerSocket
Sie erhalten diese aus dem ObjektNetworkCapabilities
imonCapabilitiesChanged()
-Callback angegeben: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);
Wenn Sie die Netzwerkverbindung hergestellt haben, rufen Sie
unregisterNetworkCallback()
Verschiedene Freunde und Standorterkennung
Ein Gerät mit WLAN-RTT-Standort können die Entfernungen zu Gleichaltrigen direkt messen und anhand dieser Informationen die Erkennung von Wi-Fi Aware-Diensten einschränken.
Mit der Wi-Fi RTT API können Sie die Verbindung zu einem Wi-Fi Aware-Peer mithilfe ihrer MAC-Adresse oder ihr PeerHandle.
Die Wi-Fi Aware-Erkennung kann eingeschränkt werden, sodass nur Dienste in einem
bestimmten Geofence. Sie können z. B. einen Geofence einrichten,
eines Geräts, das einen "Aware_File_Share_Service_Name"
-Dienst veröffentlicht, der nicht
näher als 3 Meter (angegeben als 3.000 mm) und nicht weiter als 10 Meter
(angegeben als 10.000 mm).
Um Geofencing zu aktivieren, müssen sowohl der Publisher als auch der Abonnent Folgendes tun:
Der Verlag oder Webpublisher muss das Bereichserkennung für den veröffentlichten Dienst mithilfe von setRangingEnabled(true)
Wenn der Publisher kein Ranging aktiviert, gibt es Geofence-Einschränkungen, werden ignoriert und die normale Erkennung wird durchgeführt. ohne die Distanz zu ignorieren.
Der Abonnent muss einen Geofence mit einer Kombination aus setMinDistanceMm und setMaxDistanceMm auf.
Bei beiden Werten gibt es keine Begrenzung, wenn die Entfernung nicht angegeben ist. Nur Angabe der maximale Abstand impliziert eine minimale Entfernung von 0. Nur die Angabe des Mindestabstand impliziert kein Maximum.
Wenn ein Peer-Dienst innerhalb eines Geofence erkannt wird, onServiceDiscoveredWithinRange -Callback ausgelöst, der die gemessene Entfernung zum Peer angibt. Die die direkte Wi-Fi RTT API aufrufen, um die Entfernung später ansehen.