Les fonctionnalités Wi-Fi Aware permettent aux appareils équipés d'Android 8.0 (niveau d'API 26) ou version ultérieure de se détecter et de se connecter directement les uns aux autres sans aucun autre type de connectivité entre eux. L'abonnement Wi-Fi Aware est également connu sous le nom de Neighbor Awareness Mise en réseau (NAN).
La mise en réseau Wi-Fi Aware consiste à former des clusters avec les appareils voisins. en créant un cluster si l'appareil est le premier dans une zone donnée. Ce comportement de clustering s'applique à l'ensemble de l'appareil et est géré par le service système Wi-Fi Aware. Les applications n'ont aucun contrôle sur le comportement de clustering. Les applications utilisent les API Wi-Fi Aware pour communiquer avec le service système Wi-Fi Aware, qui gère le matériel Wi-Fi Aware sur l'appareil.
Les API Wi-Fi Aware permettent aux applications d'effectuer les opérations suivantes :
Détecter d'autres appareils:l'API dispose d'un mécanisme permettant de trouver d'autres appareils à proximité. Le processus commence lorsqu'un appareil en publie un ou des services plus visibles. Ensuite, lorsqu'un appareil s'abonne à un ou plusieurs et entre dans la plage Wi-Fi de l'éditeur, l'abonné reçoit une notification indiquant qu'un éditeur correspondant a été détecté. Après le l'abonné découvre un éditeur, il peut envoyer un Short ou établir une connexion réseau avec l'appareil détecté. Les appareils peuvent être à la fois éditeurs et abonnés.
Créez une connexion réseau:après que deux appareils ont détecté chacun. Ils peuvent aussi créer une connexion Wi-Fi-Aware bidirectionnelle sans point d'accès.
Les connexions réseau Wi-Fi Aware permettent des débits plus élevés sur de plus longues distances que les connexions Bluetooth. Ces types de connexions sont utiles pour les applications qui partagent de grandes quantités de données entre les utilisateurs, comme les applications de partage de photos.
Améliorations apportées à Android 13 (niveau d'API 33)
Sur les appareils équipés d'Android 13 (niveau d'API 33) ou version ultérieure prenant en charge les instantanés
mode de communication, les applications peuvent utiliser
PublishConfig.Builder.setInstantCommunicationModeEnabled()
et
Méthodes SubscribeConfig.Builder.setInstantCommunicationModeEnabled()
permettant de
activer ou désactiver le mode de communication instantanée pour un éditeur ou un abonné
la session de découverte. Le mode de communication instantanée accélère l'échange de messages, la découverte de services et tout chemin de données configuré dans le cadre d'une session de découverte d'éditeur ou d'abonné. Pour déterminer si un appareil est compatible avec le mode de communication instantanée, utilisez la méthode isInstantCommunicationModeSupported()
.
Améliorations d'Android 12 (niveau d'API 31)
Android 12 (niveau d'API 31) ajoute quelques améliorations à Wi-Fi Aware:
- Sur les appareils équipés d'Android 12 (niveau d'API 31) ou version ultérieure, vous pouvez utiliser le rappel
onServiceLost()
pour être alerté lorsque votre application a perdu un service découvert en raison de l'arrêt du service ou de son déplacement hors de portée. - La configuration des chemins de données Wi-Fi Aware a été simplifiée. Versions antérieures utilisé la messagerie L2 pour fournir l'adresse MAC de l'initiateur, qui la latence a été introduite. Sur les appareils équipés d'Android 12 ou version ultérieure, (serveur) peut être configuré pour accepter n'importe quel pair, c'est-à-dire qu'il n'a pas besoin de connaître l’adresse MAC de l’initiateur à l’avance. Cela accélère la mise en service du datapath et permet de créer plusieurs liaisons point à point avec une seule requête réseau.
- Les applications fonctionnant sous Android 12 ou version ultérieure peuvent utiliser
WifiAwareManager.getAvailableAwareResources()
pour obtenir le nombre de chemins de données actuellement disponibles, publier des sessions, et "S'abonner". Cela peut aider l'application à déterminer s'il y a suffisamment de ressources disponibles pour exécuter la fonctionnalité souhaitée.
Configuration initiale
Pour configurer votre application afin d'utiliser la détection et la mise en réseau Wi-Fi Aware, effectuez les procédez comme suit:
Demandez les autorisations suivantes dans le fichier manifeste de votre application :
<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" />
Vérifiez si l'appareil est compatible avec Wi-Fi Aware à l'aide de l'API
PackageManager
, comme illustré ci-dessous :Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
Vérifiez si Wi-Fi Aware est actuellement disponible. Wi-Fi Aware peut exister sur l'appareil, mais il est possible qu'il ne soit pas disponible actuellement, car l'utilisateur a désactivé le Wi-Fi ou la localisation. Selon leurs fonctionnalités matérielles et logicielles, certains appareils peuvent ne pas être compatibles avec Wi-Fi Aware si Wi-Fi Direct, SoftAP ou le partage de connexion sont utilisés. Pour vérifier si Wi-Fi Aware est actuellement disponible, appelez
isAvailable()
.La disponibilité de Wi-Fi Aware peut changer à tout moment. Votre application doit enregistrer un
BroadcastReceiver
pour recevoirACTION_WIFI_AWARE_STATE_CHANGED
, qui est envoyé chaque fois que la disponibilité change. Lorsque votre application reçoit l'intent de diffusion, elle doit supprimer toutes les sessions existantes (en supposant que le service Wi-Fi Aware a été interrompu), puis vérifier l'état actuel de la disponibilité et ajuster son comportement en conséquence. Exemple :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);
Pour en savoir plus, consultez la section Diffusions.
Obtenir une session
Pour commencer à utiliser Wi-Fi Aware, votre application doit obtenir un WifiAwareSession
en appelant attach()
. Cette méthode
effectue les opérations suivantes:
- Active le matériel Wi-Fi Aware.
- Rejoint ou forme un cluster Wi-Fi Aware.
- Crée une session Wi-Fi Aware avec un espace de noms unique faisant office de pour toutes les sessions de découverte créées dans celui-ci.
Si l'application est correctement associée, le système exécute
Rappel onAttached()
.
Ce rappel fournit un objet WifiAwareSession
que votre application doit utiliser pour toutes les autres opérations de session. Une application peut utiliser
une session pour publier un service,
s'abonner à un service.
Votre application ne doit appeler attach()
qu'une seule fois. Si votre application appelle attach()
plusieurs fois, elle reçoit une session différente pour chaque appel, chacune avec son propre espace de noms. Cela peut être utile dans des scénarios complexes,
généralement à éviter.
Publier un service
Pour rendre un service détectable, appelez la méthode publish()
, qui utilise les paramètres suivants :
PublishConfig
spécifie le nom du service et d'autres propriétés de configuration, telles que le filtre de correspondance.DiscoverySessionCallback
spécifie des actions à exécuter lorsque des événements se produisent, par exemple lorsque l'abonné reçoit un message.
Exemple :
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);
Si la publication aboutit, la méthode de rappel onPublishStarted()
est appelée.
Après la publication, lorsque les appareils exécutant les applications d'abonnés correspondantes sont déplacés vers le
la portée Wi-Fi de l'appareil publié, les abonnés découvrent le service. Quand ?
un abonné découvre un éditeur, l'éditeur ne reçoit pas
notification si l'abonné envoie un message à l'éditeur :
l'éditeur reçoit une notification. Dans ce cas, la méthode de rappel onMessageReceived()
est appelée. Vous pouvez utiliser
l'argument PeerHandle
de cette méthode pour
renvoyer un message à l'abonné
créer une connexion à celle-ci.
Pour arrêter la publication du service, appelez
DiscoverySession.close()
Les sessions de découverte sont associées à leur WifiAwareSession
parent. Si la session parente est fermée, ses sessions de découverte associées le sont également. Bien que les objets supprimés soient également fermés, le système ne garantit pas le moment où les sessions hors du champ d'application sont fermées. Nous vous recommandons donc d'appeler explicitement les méthodes close()
.
S'abonner à un service
Pour vous abonner à un service, appelez la méthode subscribe()
, qui accepte les paramètres suivants :
-
SubscribeConfig
spécifie le nom du auquel s'abonner et d'autres propriétés de configuration, telles que la correspondance filtre. DiscoverySessionCallback
spécifie les actions à exécuter lorsque des événements se produisent, par exemple lorsqu'un éditeur est détecté.
Exemple :
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);
Si l'opération d'abonnement aboutit, le système appelle le rappel onSubscribeStarted()
dans votre application. Étant donné que vous pouvez utiliser l'argument SubscribeDiscoverySession
dans le rappel pour communiquer avec un éditeur après que votre application en a découvert un, vous devez enregistrer cette référence. Vous pouvez mettre à jour la session d'abonnement à tout moment en
Appel en cours
updateSubscribe()
lors de la session de découverte.
À ce stade, votre abonnement attend que les éditeurs correspondants
Portée du Wi-Fi. Dans ce cas, le système exécute
onServiceDiscovered()
. Vous pouvez utiliser l'argument PeerHandle
de ce rappel pour envoyer un message ou créer une connexion avec cet éditeur.
Pour cesser de vous abonner à un service, appelez
DiscoverySession.close()
Les sessions de découverte sont associées à leurs parents
WifiAwareSession
Si la session parente est
les sessions de découverte associées sont également fermées. Après suppression
sont également fermés, le système ne garantit pas s'ils sont hors du champ d'application
sessions sont fermées. Nous vous recommandons donc d'appeler explicitement close()
méthodes.
Envoyer un message
Pour envoyer un message à un autre appareil, vous avez besoin des objets suivants:
Un
DiscoverySession
. Cet objet vous permet d'appelersendMessage()
. Votre application obtient uneDiscoverySession
de l'une des manières suivantes : la publication d'un service ou l'abonnement à un Google Cloud.Le
PeerHandle
de l'autre appareil, pour acheminer le . Votre application obtient l'PeerHandle
d'un autre appareil de deux manières :- Votre application publie un service et reçoit un message d'un abonné.
Votre application reçoit
PeerHandle
dansonMessageReceived()
. - Votre application s'abonne à un service. Ensuite, lorsqu'elle détecte un éditeur correspondant, votre application obtient le
PeerHandle
de l'éditeur à partir du rappelonServiceDiscovered()
.
- Votre application publie un service et reçoit un message d'un abonné.
Votre application reçoit
Pour envoyer un message, appelez sendMessage()
. Les rappels suivants peuvent alors se produire :
- Lorsque le message est reçu avec succès par le pair, le système appelle la méthode
onMessageSendSucceeded()
dans l'application sending. - Lorsque le pair reçoit un message, le système appelle la méthode
onMessageReceived()
dans l'application receve.
Bien que PeerHandle
soit obligatoire pour communiquer avec les pairs, vous ne devez pas
l'utiliser comme identifiant permanent des pairs. L'application peut utiliser des identifiants de niveau supérieur, intégrés au service de découverte lui-même ou dans des messages ultérieurs. Vous pouvez intégrer un identifiant dans le service de découverte à l'aide de la méthode setMatchFilter()
ou setServiceSpecificInfo()
de PublishConfig
ou SubscribeConfig
. La méthode setMatchFilter()
a une incidence sur la visibilité, contrairement à la méthode setServiceSpecificInfo()
.
L'intégration d'un identifiant dans un message implique la modification du tableau d'octets du message pour incluent un identifiant (par exemple, dans les premiers octets).
Créer une connexion
Wi-Fi Aware prend en charge la mise en réseau client-serveur entre deux appareils Wi-Fi Aware.
Pour configurer la connexion client-serveur :
Utilisez la détection Wi-Fi Aware pour publier un service (sur la serveur) et vous abonner à un service (sur le client).
Une fois que l'abonné a trouvé l'éditeur, Envoyer un message de l'abonné à l'éditeur
Démarrez un
ServerSocket
sur l'appareil de l'éditeur et définissez ou obtenez son port :Kotlin
val ss = ServerSocket(0) val port = ss.localPort
Java
ServerSocket ss = new ServerSocket(0); int port = ss.getLocalPort();
Utilisez
ConnectivityManager
pour demander un réseau Wi-Fi Aware sur l'éditeur à l'aide d'unWifiAwareNetworkSpecifier
, en spécifiant la session de découverte et lePeerHandle
de l'abonné, que vous avez obtenus à partir du message transmis par l'abonné :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);
Lorsque l'éditeur demande un réseau, envoyer un message à l'abonné.
Une fois que l'abonné a reçu le message de l'éditeur, demandez un réseau Wi-Fi Aware sur l'abonné en utilisant la même méthode que sur l'éditeur. À faire et non de port lors de la création
NetworkSpecifier
La les méthodes de rappel appropriées sont appelées lorsque la connexion réseau est disponibles, modifiées ou perdues.Une fois la méthode
onAvailable()
appelée sur l'abonné, un objetNetwork
est disponible avec lequel vous pouvez ouvrir unSocket
pour communiquer avec leServerSocket
sur l'éditeur, mais vous devez connaître l'adresse IPv6 et le port duServerSocket
. Vous pouvez les obtenir via ObjetNetworkCapabilities
fournies dans le rappelonCapabilitiesChanged()
: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);
Lorsque vous n'avez plus besoin de la connexion réseau, appelez
unregisterNetworkCallback()
.
Évaluation de la portée des pairs et découverte basée sur la position
Un appareil avec localisation texte en temps réel via le Wi-Fi peuvent mesurer directement la distance par rapport aux pairs et utiliser ces informations pour la détection de services Wi-Fi Aware.
L'API Wi-Fi DAR permet de mettre les distances directement jusqu'à un pair Wi-Fi Aware à l'aide de son adresse MAC ou son PeerHandle.
La détection Wi-Fi Aware peut être limitée à la découverte de services dans une zone géographique spécifique. Par exemple, vous pouvez configurer une zone de géorepérage pour permettre la découverte
d'un appareil publiant un service "Aware_File_Share_Service_Name"
qui n'est pas
entre moins de 3 mètres (3 000 mm) et 10 mètres au maximum
(valeur spécifiée : 10 000 mm).
Pour activer le géorepérage, l'éditeur et l'abonné doivent tous deux effectuer des actions :
L'éditeur doit activer la mesure de la portée sur le service publié à l'aide de setRangingEnabled(true).
Si l'éditeur n'active pas la mesure de la distance, toutes les contraintes de géorepérage spécifiées par l'abonné sont ignorées et la découverte normale est effectuée, en ignorant la distance.
L'abonné doit spécifier une zone de géorepérage en utilisant une combinaison des éléments suivants : setMinDistanceMm. et setMaxDistanceMm.
Pour les deux valeurs, une distance non spécifiée implique qu'il n'y a pas de limite. Spécifier uniquement la distance maximale implique une distance minimale de 0. Spécifier uniquement la distance minimale n'implique pas de valeur maximale.
Lorsqu'un service de pair est détecté dans une zone de géorepérage, le rappel onServiceDiscoveredWithinRange est déclenché, ce qui fournit la distance mesurée par rapport au pair. L'API RTT Wi-Fi directe peut ensuite être appelée si nécessaire pour mesurer la distance à un autre moment.