Localisation en Wi-Fi: portée avec DAR

Vous pouvez utiliser la fonctionnalité de localisation Wi-Fi fournie par l'API Wi-Fi RTT (Round-Trip-Time) pour mesurer la distance jusqu'aux points d'accès Wi-Fi compatibles RTT et aux appareils Wi-Fi Aware pairs à proximité.

Si vous mesurez la distance par rapport à au moins trois points d'accès, vous pouvez utiliser un algorithme de multilatération pour estimer la position de l'appareil qui correspond le mieux à ces mesures. Le résultat est généralement précis à un ou deux mètres près.

Cette précision vous permet de développer des services basés sur la localisation précis, tels que la navigation en intérieur, la commande vocale désambiguïsée (par exemple, "Allume cette lumière") et les informations basées sur la localisation (par exemple, "Y a-t-il des offres spéciales pour ce produit ?").

L'appareil demandeur n'a pas besoin de se connecter aux points d'accès pour mesurer la distance avec le Wi-Fi RTT. Pour préserver la confidentialité, seul l'appareil demandeur peut déterminer la distance jusqu'au point d'accès. Les points d'accès ne disposent pas de ces informations. Les opérations Wi-Fi RTT sont illimitées pour les applications au premier plan, mais sont limitées pour les applications en arrière-plan.

Le Wi-Fi RTT et les fonctionnalités FTM (Fine-Time-Measurement) associées sont spécifiés par la norme IEEE 802.11-2016. Le Wi-Fi RTT nécessite la mesure précise du temps fournie par le FTM, car il calcule la distance entre deux appareils en mesurant le temps nécessaire à un paquet pour effectuer un aller-retour entre les appareils et en multipliant ce temps par la vitesse de la lumière.

Android 15 (niveau d'API 35) est compatible avec la mesure de distance non basée sur un déclencheur (NTB) IEEE 802.11az.

Différences d'implémentation en fonction de la version d'Android

Le Wi-Fi RTT a été introduit dans Android 9 (niveau d'API 28). Lorsque vous utilisez ce protocole pour déterminer la position d'un appareil à l'aide de la multilatération avec des appareils équipés d'Android 9, vous devez avoir accès aux données de localisation des points d'accès (PA) prédéterminés dans votre application. C'est à vous de décider comment stocker et récupérer ces données.

Sur les appareils équipés d'Android 10 (niveau d'API 29) ou version ultérieure, les données de localisation du point d'accès peuvent être représentées sous forme d'objets ResponderLocation, qui incluent la latitude, la longitude et l'altitude. Pour les points d'accès Wi-Fi RTT compatibles avec les données LCI/LCR (Location Configuration Information/Location Civic Report), le protocole renvoie un objet ResponderLocation pendant le processus de télémétrie.

Cette fonctionnalité permet aux applications d'interroger directement les points d'accès pour leur demander leur position, plutôt que de devoir stocker ces informations à l'avance. Votre application peut donc trouver des points d'accès et déterminer leur position, même s'ils n'étaient pas connus auparavant, par exemple lorsqu'un utilisateur entre dans un nouveau bâtiment.

La mesure de distance NTB IEEE 802.11az est disponible sur les appareils équipés d'Android 15 (niveau d'API 35) ou version ultérieure. Cela signifie que si l'appareil est compatible avec le mode initiateur NTB IEEE 802.11az (indiqué par WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR), votre application peut trouver des points d'accès compatibles IEEE 802.11mc et IEEE 802.11az avec une seule requête de plage. L'API RangingResult a été étendue pour fournir des informations sur les valeurs minimale et maximale pouvant être utilisées pour l'intervalle entre les mesures de télémétrie, laissant l'intervalle exact sous le contrôle de votre application.

Conditions requises

  • Le matériel de l'appareil qui effectue la requête de mesure de distance doit implémenter la norme FTM 802.11-2016 ou la norme 802.11az (mesure de distance non basée sur un déclencheur).
  • L'appareil qui effectue la requête de télémétrie doit être équipé d'Android 9 (niveau d'API 28) ou version ultérieure. La mesure de distance non basée sur un déclencheur IEEE 802.11az est activée sur les appareils équipés d'Android 15 (niveau d'API 35) ou version ultérieure.
  • Les services de localisation et la recherche Wi-Fi doivent être activés sur l'appareil qui effectue la requête de mesure de la distance (sous Paramètres > Localisation).
  • Si l'application qui effectue la requête de télémétrie cible Android 13 (niveau d'API 33) ou une version ultérieure, elle doit disposer de l'autorisation NEARBY_WIFI_DEVICES. Si une telle application cible une version antérieure d'Android, elle doit disposer de l'autorisation ACCESS_FINE_LOCATION.
  • L'application doit interroger la plage de points d'accès lorsqu'elle est visible ou dans un service de premier plan. L'application ne peut pas accéder aux informations de localisation en arrière-plan.
  • Le point d'accès doit implémenter la norme IEEE 802.11-2016 FTM ou la norme IEEE 802.11az (mesure de distance sans déclencheur).

Configuration

Pour configurer votre application afin qu'elle utilise le Wi-Fi RTT, procédez comme suit.

1. Demander des autorisations

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" />
<!-- 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" />

Les autorisations NEARBY_WIFI_DEVICES et ACCESS_FINE_LOCATION sont des autorisations dangereuses. Vous devez donc les demander au moment de l'exécution chaque fois que l'utilisateur souhaite effectuer une opération d'analyse RTT. Votre application devra demander l'autorisation de l'utilisateur si elle n'a pas déjà été accordée. Pour en savoir plus sur les autorisations d'exécution, consultez Exiger des autorisations d'applications.

2. Vérifier si l'appareil est compatible avec le Wi-Fi RTT

Pour vérifier si l'appareil est compatible avec le Wi-Fi RTT, utilisez l'API PackageManager :

Kotlin

context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)

Java

context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);

3. Vérifier si le Wi-Fi RTT est disponible

Le Wi-Fi RTT peut exister sur l'appareil, mais il peut ne pas être disponible, car l'utilisateur a désactivé le Wi-Fi. En fonction de leurs capacités matérielles et de micrologiciel, certains appareils peuvent ne pas être compatibles avec le Wi-Fi RTT si SoftAP ou le partage de connexion sont utilisés. Pour vérifier si le Wi-Fi RTT est disponible, appelez isAvailable().

La disponibilité du Wi-Fi RTT peut changer à tout moment. Votre application doit enregistrer un BroadcastReceiver pour recevoir ACTION_WIFI_RTT_STATE_CHANGED, qui est envoyé lorsque la disponibilité change. Lorsque votre application reçoit l'intent de diffusion, elle doit vérifier l'état de disponibilité actuel et adapter son comportement en conséquence.

Exemple :

Kotlin

val filter = IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED)
val myReceiver = object: BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (wifiRttManager.isAvailable) {
            …
        } else {
            …
        }
    }
}
context.registerReceiver(myReceiver, filter)

Java

IntentFilter filter =
    new IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED);
BroadcastReceiver myReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (wifiRttManager.isAvailable()) {
            …
        } else {
            …
        }
    }
};
context.registerReceiver(myReceiver, filter);

Pour en savoir plus, consultez Diffusions.

Créer une requête de mesure de distance

Une requête de mesure de distance (RangingRequest) est créée en spécifiant une liste de points d'accès ou de pairs Wi-Fi Aware pour lesquels une distance est demandée. Plusieurs points d'accès ou pairs Wi-Fi Aware peuvent être spécifiés dans une seule requête de mesure de distance. Les distances de tous les appareils sont mesurées et renvoyées.

Par exemple, une requête peut utiliser la méthode addAccessPoint() pour spécifier un point d'accès à partir duquel mesurer la distance :

Kotlin

val req: RangingRequest = RangingRequest.Builder().run {
    addAccessPoint(ap1ScanResult)
    addAccessPoint(ap2ScanResult)
    build()
}

Java

RangingRequest.Builder builder = new RangingRequest.Builder();
builder.addAccessPoint(ap1ScanResult);
builder.addAccessPoint(ap2ScanResult);

RangingRequest req = builder.build();

Un point d'accès est identifié par son objet ScanResult, qui peut être obtenu en appelant WifiManager.getScanResults(). Vous pouvez utiliser addAccessPoints(List<ScanResult>) pour ajouter plusieurs points d'accès par lot.

Les objets ScanResult peuvent contenir des points d'accès compatibles avec les normes IEEE 802.11mc (is80211mcResponder()) et IEEE 802.11az (is80211azNtbResponder()). Les appareils compatibles avec la mesure de distance IEEE 802.11az NTB effectuent une mesure de distance 802.11mc ou 802.11az en fonction des capacités du point d'accès, par défaut 802.11az lorsque le point d'accès est compatible avec les deux. Les appareils qui ne sont pas compatibles avec la norme IEEE 802.11az effectuent toutes les mesures de distance à l'aide du protocole IEEE 802.11mc.

De même, une requête de télémétrie peut ajouter un pair Wi-Fi Aware à l'aide de son adresse MAC ou de son PeerHandle, en utilisant respectivement les méthodes addWifiAwarePeer(MacAddress peer) et addWifiAwarePeer(PeerHandle peer). Pour en savoir plus sur la détection des pairs Wi-Fi Aware, consultez la documentation sur Wi-Fi Aware.

Demander la détection de proximité

Une application émet une requête de télémétrie à l'aide de la méthode WifiRttManager.startRanging() et fournit les éléments suivants : un RangingRequest pour spécifier l'opération, un Executor pour spécifier le contexte de rappel et un RangingResultCallback pour recevoir les résultats.

Exemple :

Kotlin

val mgr = context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE) as WifiRttManager
val request: RangingRequest = myRequest
mgr.startRanging(request, executor, object : RangingResultCallback() {

    override fun onRangingResults(results: List<RangingResult>) { … }

    override fun onRangingFailure(code: Int) { … }
})

Java

WifiRttManager mgr =
      (WifiRttManager) Context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE);

RangingRequest request ...;
mgr.startRanging(request, executor, new RangingResultCallback() {

  @Override
  public void onRangingFailure(int code) { … }

  @Override
  public void onRangingResults(List<RangingResult> results) { … }
});

L'opération de télémétrie est effectuée de manière asynchrone, et les résultats sont renvoyés dans l'un des rappels de RangingResultCallback :

  • Si l'ensemble de l'opération de télémétrie échoue, le rappel onRangingFailure est déclenché avec un code d'état décrit dans RangingResultCallback. Un tel échec peut se produire si le service ne peut pas exécuter une opération de télémétrie à ce moment-là, par exemple parce que le Wi-Fi est désactivé, parce que l'application a demandé trop d'opérations de télémétrie et est limitée, ou en raison d'un problème d'autorisation.
  • Une fois l'opération de télémétrie terminée, le rappel onRangingResults est déclenché avec une liste de résultats correspondant à la liste des requêtes (un résultat pour chaque requête). L'ordre des résultats ne correspond pas nécessairement à l'ordre des requêtes. Notez que l'opération de télémétrie peut se terminer, mais que chaque résultat peut toujours indiquer un échec de cette mesure spécifique.

Interpréter les résultats de la télémétrie

Chacun des résultats renvoyés par le rappel onRangingResults est spécifié par un objet RangingResult. Pour chaque requête, procédez comme suit :

1. Identifier la requête

Identifiez la requête en fonction des informations fournies lors de la création de l'objet RangingRequest : le plus souvent, une adresse MAC fournie dans l'objet ScanResult identifiant un point d'accès. L'adresse MAC peut être obtenue à partir du résultat de la télémétrie à l'aide de la méthode getMacAddress().

La liste des résultats de télémétrie peut être dans un ordre différent de celui des pairs (points d'accès) spécifiés dans la requête de télémétrie. Vous devez donc utiliser l'adresse MAC pour identifier le pair, et non l'ordre des résultats.

2. Déterminer si chaque mesure a réussi

Pour déterminer si une mesure a réussi, utilisez la méthode getStatus(). Toute valeur autre que STATUS_SUCCESS indique un échec. Un échec signifie que tous les autres champs de ce résultat (à l'exception de l'identification de la requête ci-dessus) ne sont pas valides et que la méthode get* correspondante échouera avec une exception IllegalStateException.

3. Obtenez des résultats pour chaque mesure réussie

Pour chaque mesure réussie (RangingResult), vous pouvez récupérer les valeurs de résultat à l'aide des méthodes get correspondantes :

  • Distance, en mm, et écart-type de la mesure :

    getDistanceMm()

    getDistanceStdDevMm()

  • RSSI des paquets utilisés pour les mesures :

    getRssi()

  • Heure en millisecondes à laquelle la mesure a été effectuée (indiquant le temps écoulé depuis le démarrage) :

    getRangingTimestampMillis()

  • Nombre de tentatives de mesure et nombre de mesures réussies (sur lesquelles les mesures de distance sont basées) :

    getNumAttemptedMeasurements()

    getNumSuccessfulMeasurements()

  • Durée minimale et maximale qu'un appareil client doit attendre entre les mesures NTB 11az :

    getMinTimeBetweenNtbMeasurementsMicros() et getMaxTimeBetweenNtbMeasurementsMicros() renvoient l'heure minimale et l'heure maximale. Si la mesure de télémétrie suivante est demandée avant l'expiration du délai minimal, l'API renvoie le résultat de télémétrie mis en cache. Si la mesure de télémétrie suivante est demandée après l'expiration du délai maximal, l'API met fin à la session de télémétrie sans déclencheur et négocie une nouvelle session de télémétrie avec la station de réponse. Évitez de demander une nouvelle session de télémétrie, car cela ajoute une surcharge au temps de mesure de la télémétrie. Pour profiter pleinement de l'efficacité de la mesure de distance non basée sur un déclencheur 802.11az, déclenchez la requête de mesure de distance suivante entre la durée de mesure minimale et maximale spécifiée dans la mesure RangingResult précédente.

  • Répétitions du champ d'entraînement long (LTF) utilisées par les stations de réponse et d'initiation dans le préambule pour le résultat NTB IEEE 802.11az :

    get80211azResponderTxLtfRepetitionsCount()

    get80211azInitiatorTxLtfRepetitionsCount()

  • Nombre de flux spatio-temporels (STS) de transmission et de réception utilisés par la station initiatrice pour le résultat NTB IEEE 802.11az :

    get80211azNumberOfTxSpatialStreams()

    get80211azNumberOfRxSpatialStreams()

Appareils Android compatibles avec le Wi-Fi RTT

Les tableaux suivants répertorient certains téléphones, points d'accès et appareils de vente au détail, d'entreposage et de centre de distribution compatibles avec le Wi-Fi RTT. Cette liste est loin d'être exhaustive. Nous vous encourageons à nous contacter pour lister ici vos produits compatibles avec le RTT.

Points d'accès

Fabricant et modèle Date de compatibilité Protocole
Nest Wifi Pro (Wi-Fi 6E) Compatible mc
Compulab WILD AP Compatible mc
Google Wifi Compatible mc
Routeur Google Nest Wifi Compatible mc
Point d'accès Google Nest Wifi Compatible mc
Aruba AP-635 Compatible mc
Cisco 9130 Compatible mc
Cisco 9136 Compatible mc
Cisco 9166 Compatible mc
Cisco 9164 Compatible mc
Cisco CW9172I Compatible mc/az
Cisco CW9172H Compatible mc/az
Cisco CW9176I Compatible mc/az
Cisco CW9178I Compatible mc/az
Aruba AP-505 Compatible mc
Aruba AP-515 Compatible mc
Aruba AP-575 Compatible mc
Aruba AP-518 Compatible mc
Aruba AP-505H Compatible mc
Aruba AP-565 Compatible mc
Aruba AP-535 Compatible mc
Aruba AP567 Compatible mc
Aruba AP577 Compatible mc
Aruba AP555 Compatible mc
Aruba AP635 Compatible mc
Aruba AP655 Compatible mc
Aruba AP615 Compatible mc
Aruba AP734 Compatible mc/az
Aruba AP735 Compatible mc/az
Aruba AP754 Compatible mc/az
Aruba AP755 Compatible mc/az

Téléphones

Fabricant et modèle Version d'Android
Google Pixel 9 Pro XL 14+
Google Pixel 9 14+
Google Pixel 9 Pro 14+
Google Pixel 9 Pro XL 14+
Google Pixel 7a 14+
Google Pixel 7 14+
Google Pixel 8 14+
Google Pixel 8 Pro 14+
Google Pixel 8a 14+
Samsung SM-S918B 14+
Samsung SM-A515F 14+
Google Pixel 9 Pro 14+
Samsung SM-A546E 14+
Samsung SM-S928B 14+
Samsung SM-A217F 14+
Samsung SM-A715F 14+
Samsung SM-A528B 14+
Samsung SM-A135F 14+
Samsung SM-S911B 14+
Xiaomi 21091116AI 14+
Google Pixel 9 14+
Samsung SM-A127F 14+
Google Pixel 7 Pro 14+
Samsung SM-A556E 14+
Pixel 6 9.0+
Pixel 6 Pro 9.0+
Pixel 5 9.0+
Pixel 5a 9.0+
Pixel 5a (5G) 9.0+
Xiaomi Mi 10 Pro 9.0+
Xiaomi Mi 10 9.0+
Xiaomi Redmi Mi 9T Pro 9.0+
Xiaomi Mi 9T 9.0+
Xiaomi Mi 9 9.0+
Xiaomi Mi Note 10 9.0+
Xiaomi Mi Note 10 Lite 9.0+
Xiaomi Redmi Note 9S 9.0+
Xiaomi Redmi Note 9 Pro 9.0+
Xiaomi Redmi Note 8T 9.0+
Xiaomi Redmi Note 8 9.0+
Xiaomi Redmi K30 Pro 9.0+
Xiaomi Redmi K20 Pro 9.0+
Xiaomi Redmi K20 9.0+
Xiaomi Redmi Note 5 Pro 9.0+
Xiaomi Mi CC9 Pro 9.0+
LG G8X ThinQ 9.0+
LG V50S ThinQ 9.0+
LG V60 ThinQ 9.0+
LG V30 9.0+
Samsung Galaxy Note 10+ 5G 9.0+
Samsung Galaxy S20+ 5G 9.0+
Samsung Galaxy S20+ 9.0+
Samsung Galaxy S20 5G 9.0+
Samsung Galaxy S20 Ultra 5G 9.0+
Samsung Galaxy S20 9.0+
Samsung Galaxy Note 10+ 9.0+
Samsung Galaxy Note 10 5G 9.0+
Samsung Galaxy Note 10 9.0+
Samsung A9 Pro 9.0+
Google Pixel 4 XL 9.0+
Google Pixel 4 9.0+
Google Pixel 4a 9.0+
Google Pixel 3 XL 9.0+
Google Pixel 3 9.0+
Google Pixel 3a XL 9.0+
Google Pixel 3a 9.0+
Google Pixel 2 XL 9.0+
Google Pixel 2 9.0+
Google Pixel 1 XL 9.0+
Google Pixel 1 9.0+
Poco X2 9.0+
Sharp Aquos R3 SH-04L 9.0+

Appareils pour le commerce, l'entreposage et les centres de distribution

Fabricant et modèle Version d'Android
Zebra PS20 10.0+
Zebra TC52/TC52HC 10.0+
Zebra TC57 10.0+
Zebra TC72 10.0+
Zebra TC77 10.0+
Zebra MC93 10.0+
Zebra TC8300 10.0+
Zebra VC8300 10.0+
Zebra EC30 10.0+
Zebra ET51 10.0+
Zebra ET56 10.0+
Zebra L10 10.0+
Zebra CC600/CC6000 10.0+
Zebra MC3300x 10.0+
Zebra MC330x 10.0+
Zebra TC52x 10.0+
Zebra TC57x 10.0+
Zebra EC50 (LAN et HC) 10.0+
Zebra EC55 (WAN) 10.0+
Zebra WT6300 10.0+
Skorpio X5 10.0+