Você pode usar o recurso de localização de Wi-Fi fornecido pela API Wi-Fi RTT (Round-Trip-Time) para medir a distância dos pontos de acesso e dos dispositivos Wi-Fi Aware próximos e compatíveis com RTT.
Ao medir a distância de até três ou mais pontos de acesso, será possível usar um algoritmo de multilateração para estimar a posição do dispositivo que melhor se encaixa nessas medidas. Normalmente, o resultado é preciso a uma distância de 1 a 2 metros.
Com essa precisão, é possível desenvolver serviços com base na localização detalhados, como navegação em ambientes fechados, controle de voz sem ambiguidade (por exemplo, "Acenda esta luz") e informações com base na localização (por exemplo, "Há ofertas especiais para este produto?").
O dispositivo que faz a solicitação não precisa se conectar aos pontos de acesso para medir a distância com o Wi-Fi RTT. Para manter a privacidade, apenas o dispositivo solicitante pode determinar a distância até o ponto de acesso. Os pontos de acesso não têm essas informações. As operações de Wi-Fi RTT são ilimitadas para aplicativos em primeiro plano, mas não para os em segundo plano.
O Wi-Fi RTT e os recursos relacionados de medição de tempo de precisão (FTM, na sigla em inglês) são especificados pelo padrão IEEE 802.11-2016. O Wi-Fi RTT exige o uso da medição de tempo precisa fornecida pelo FTM, já que ele calcula a distância medindo o tempo que um pacote leva para fazer uma viagem de ida e volta entre dois dispositivos e depois multiplica esse tempo pela velocidade da luz.
O Android 15 (nível 35 da API) introduziu suporte para medição de distância não baseada em acionador (NTB, na sigla em inglês) IEEE 802.11az.
Diferenças de implementação baseadas na versão Android
O Wi-Fi RTT foi introduzido no Android 9 (API de nível 28). Para usar esse protocolo para determinar a posição de um dispositivo usando multilateration com dispositivos que executam o Android 9, você precisará ter acesso aos dados de localização do ponto de acesso (AP, na sigla em inglês) predeterminados no seu aplicativo. Você pode decidir a melhor forma de armazenar e recuperar esses dados.
Em dispositivos que executam Android 10 (API de nível 29) e versões mais recentes, os dados da localização do ponto de acesso podem ser representados por objetos ResponderLocation, que incluem latitude, longitude e altitude. Para os pontos de acesso do Wi-Fi RTT compatíveis com informações de configuração da localização/relatório cívico de localização (dados de LCI/LCR), o protocolo retornará um objeto ResponderLocation durante o processo de alcance.
Esse recurso permite que os aplicativos consultem diretamente os pontos de acesso para solicitar a posição deles, em vez de precisar armazenar essas informações antecipadamente. Dessa forma, seu aplicativo poderá encontrar pontos de acesso e determinar as posições relacionadas, mesmo que esses pontos sejam desconhecidos. Por exemplo, quando um usuário entra em um novo prédio.
O suporte à medição de distância NTB IEEE 802.11az está disponível em dispositivos com o Android 15
(nível 35 da API) e versões mais recentes. Isso significa que, se o dispositivo for compatível com o modo iniciador NTB
do IEEE 802.11az (indicado por
WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR),
o app poderá encontrar APs compatíveis com o IEEE 802.11mc e o IEEE 802.11az com uma única
solicitação de intervalo. A API RangingResult foi estendida para fornecer informações
sobre o valor mínimo e máximo que pode ser usado para o intervalo entre
as medições de alcance, deixando o intervalo exato sob o controle do app.
Requisitos
- O hardware do dispositivo que faz a solicitação de medição precisa implementar o padrão FTM 802.11-2016 ou 802.11az (medição não baseada em acionador).
- O dispositivo que faz a solicitação de alcance precisa executar o Android 9 (API de nível 28) ou versão mais recente. A medição de distância não baseada em acionador IEEE 802.11az está ativada em dispositivos com o Android 15 (nível 35 da API) e versões mais recentes.
- O dispositivo que faz a solicitação de alcance precisa ter a busca por Wi-Fi e os serviços de localização ativados (em Configurações > Localização).
- Se o app que faz a solicitação de medição de distância for destinado ao
Android 13 (nível 33 da API) ou versões mais recentes, ele precisará ter a
permissão
NEARBY_WIFI_DEVICES. Se esse app for destinado a uma versão anterior do Android, ele precisará ter a permissãoACCESS_FINE_LOCATION. - O aplicativo deve consultar o alcance de pontos de acesso enquanto o aplicativo está visível ou em um serviço em primeiro plano. O aplicativo não pode acessar as informações de localização em segundo plano.
- O ponto de acesso precisa implementar o padrão FTM IEEE 802.11-2016 ou o padrão IEEE 802.11az (medição de distância não baseada em acionador).
Configuração
Se você quiser configurar o aplicativo para usar o Wi-Fi RTT, siga estas etapas:
1. Solicite permissões
Solicite as seguintes permissões no manifesto do app:
<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" />
As permissões NEARBY_WIFI_DEVICES e ACCESS_FINE_LOCATION são perigosas.
Portanto, é necessário solicitá-las no momento da execução sempre que o usuário quiser
realizar uma operação de verificação de RTT. Seu app precisará solicitar a permissão do usuário
caso ela ainda não tenha sido concedida. Para mais informações
sobre permissões de execução, consulte
Solicitar permissões do app.
2. Verifique se o dispositivo é compatível com Wi-Fi RTT
Para verificar se o dispositivo é compatível com o Wi-Fi RTT, use a
API PackageManager:
Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
3. Verifique se o Wi-Fi RTT está disponível
O RTT de Wi-Fi pode existir no dispositivo, mas pode não estar disponível porque o usuário
desativou o Wi-Fi. Dependendo dos recursos de hardware e firmware, alguns
dispositivos podem não oferecer suporte ao Wi-Fi RTT se o SoftAP ou o tethering estiverem em uso. Para verificar
se o RTT Wi-Fi está disponível, chame
isAvailable().
A disponibilidade do Wi-Fi RTT pode mudar a qualquer momento. Seu app precisa registrar um
BroadcastReceiver
para receber
ACTION_WIFI_RTT_STATE_CHANGED,
que é enviado quando a disponibilidade muda. Ao receber o intent de transmissão, seu aplicativo deverá verificar o estado atual da disponibilidade e ajustar o próprio comportamento de acordo com essa informação.
Por exemplo:
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);
Para mais informações, consulte Visão geral de transmissões.
Criar uma solicitação de alcance
Uma solicitação de medição de distância
(RangingRequest) é criada
especificando uma lista de APs ou de dispositivos Wi-Fi Aware para os quais uma distância
é solicitada. É possível especificar vários pontos de acesso ou pontos do Wi-Fi Aware em uma única solicitação. As distâncias para todos os dispositivos são medidas e retornadas.
Por exemplo, uma solicitação pode usar o método
addAccessPoint()
para especificar um ponto de acesso para medir a distância:
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();
Um ponto de acesso é identificado pelo objeto
ScanResult, que pode ser
obtido chamando
WifiManager.getScanResults().
É possível usar
addAccessPoints(List<ScanResult>)
para adicionar vários pontos de acesso em um lote.
Os objetos ScanResult podem conter APs compatíveis com IEEE 802.11mc (is80211mcResponder()) e
IEEE 802.11az com base em medição de distância não acionada (is80211azNtbResponder()). Os dispositivos compatíveis com o alcance NTB do IEEE 802.11az realizam o alcance 802.11mc ou
802.11az, dependendo da capacidade do AP, usando o 802.11az como padrão quando
o AP é compatível com ambos. Os dispositivos que não são compatíveis com o IEEE 802.11az realizam todas as
medições usando o protocolo IEEE 802.11mc.
Da mesma forma, uma solicitação de medição pode adicionar um par do Wi-Fi Aware usando o endereço MAC
ou o PeerHandle, usando
os
métodos
addWifiAwarePeer(MacAddress peer)
e addWifiAwarePeer(PeerHandle peer), respectivamente. Para mais informações sobre como descobrir dispositivos semelhantes com Wi-Fi Aware,
consulte a documentação do Wi-Fi Aware.
Solicitar o alcance
Um app emite uma solicitação de medição usando o método
WifiRttManager.startRanging()
e fornecendo o seguinte: um
RangingRequest para especificar a
operação, um Executor para especificar
o contexto de callback e um
RangingResultCallback
para receber os resultados.
Exemplo:
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) { … } });
A operação de medição de distância é realizada de forma assíncrona, e os resultados são
retornados em um dos callbacks de
RangingResultCallback:
- Se toda a operação de medição falhar, o callback
onRangingFailureserá acionado com um código de status descrito emRangingResultCallback. Esse erro ocorrerá caso o serviço não possa executar uma operação de alcance no momento. Por exemplo, o Wi-Fi está desativado, o aplicativo ultrapassou o limite de solicitações de alcance ou devido a um problema de permissão. - Quando a operação de medição de distância é concluída, o callback
onRangingResultsé acionado com uma lista de resultados que corresponde à lista de solicitações, um resultado para cada solicitação. A ordem dos resultados não corresponderá necessariamente à das solicitações. A operação de alcance talvez seja concluída, mas cada resultado ainda poderá indicar uma falha nessa medição específica.
Interpretar os resultados de alcance
Cada um dos resultados retornados pelo callback onRangingResults é especificado por um objeto RangingResult. Em cada solicitação, faça o seguinte:
1. Identifique a solicitação
Identifique a solicitação com base nas informações fornecidas ao criar o
RangingRequest:
na maioria das vezes, um endereço MAC fornecido no ScanResult que identifica um ponto de
acesso. O endereço MAC pode ser recebido do resultado da medição usando o método
getMacAddress().
A lista de resultados de alcance pode estar em ordem diferente dos pontos (pontos de acesso) especificados na solicitação. Por isso, use o endereço MAC para identificar o ponto, não a ordem dos resultados.
2. Determine se cada medição foi concluída
Para determinar se uma medição foi bem-sucedida, use o método
getStatus(). Qualquer valor diferente de
STATUS_SUCCESS
indica uma falha. Uma falha significa que todos os outros campos desse resultado
(exceto a identificação da solicitação acima) são inválidos, e o método
get* correspondente vai falhar com uma
exceção IllegalStateException.
3. Veja os resultados para cada medição concluída
Para cada medição bem-sucedida (RangingResult), é possível recuperar valores de resultado
com os respectivos métodos get:
Confira a distância em mm e o desvio padrão da medição:
Veja o RSSI dos pacotes utilizados para as medições:
Confira o tempo em milissegundos da mediação (indicando o tempo desde a inicialização):
Saiba o número de tentativas de medição e quantos processos foram concluídos (e em quais ocorrências a medição da distância se baseia):
Tempo mínimo e máximo que um dispositivo cliente precisa esperar entre as medições de NTB do 11az:
getMinTimeBetweenNtbMeasurementsMicros()egetMaxTimeBetweenNtbMeasurementsMicros()retornam o tempo mínimo e máximo. Se a próxima medição de alcance for solicitada antes do tempo mínimo, a API vai retornar o resultado de alcance armazenado em cache. Se a próxima medição de alcance for solicitada após o tempo máximo, a API vai encerrar a sessão de alcance sem acionamento e negociar uma nova sessão com a estação de resposta. Evite solicitar uma nova sessão de medição, porque isso adiciona sobrecarga ao tempo de medição. Para aproveitar ao máximo a eficiência de medição de distância não baseada em acionador do 802.11az, acione a próxima solicitação de medição de distância entre o tempo mínimo e máximo de medição especificado na mediçãoRangingResultanterior.Repetições de campo de treinamento longo (LTF, na sigla em inglês) que as estações de resposta e de inicialização usaram no preâmbulo para o resultado do NTB IEEE 802.11az:
Número de fluxos de tempo espacial (STS, na sigla em inglês) de transmissão e recepção que a estação iniciadora usou para o resultado do NTB IEEE 802.11az:
Dispositivos Android compatíveis com Wi-Fi RTT
As tabelas a seguir listam alguns smartphones, pontos de acesso e dispositivos de varejo, armazenamento e centro de distribuição que oferecem suporte ao Wi-Fi RTT. Elas não abrangem todos os dispositivos compatíveis. Entre em contato conosco para listar seus produtos compatíveis com RTT aqui.
Pontos de acesso
| Fabricante e modelo | Data do suporte | Protocolo |
|---|---|---|
| Nest Wifi Pro (Wi-Fi 6E) | Compatível | mc |
| Compulab WILD AP | Compatível | mc |
| Google Wi-Fi | Compatível | mc |
| Roteador Wi-Fi Google Nest | Compatível | mc |
| Ponto Google Nest Wifi | Compatível | mc |
| Aruba AP-635 | Compatível | mc |
| Cisco 9130 | Compatível | mc |
| Cisco 9136 | Compatível | mc |
| Cisco 9166 | Compatível | mc |
| Cisco 9164 | Compatível | mc |
| Cisco CW9172I | Compatível | mc/az |
| Cisco CW9172H | Compatível | mc/az |
| Cisco CW9176I | Compatível | mc/az |
| Cisco CW9178I | Compatível | mc/az |
| Aruba AP-505 | Compatível | mc |
| Aruba AP-515 | Compatível | mc |
| Aruba AP-575 | Compatível | mc |
| Aruba AP-518 | Compatível | mc |
| Aruba AP-505H | Compatível | mc |
| Aruba AP-565 | Compatível | mc |
| Aruba AP-535 | Compatível | mc |
| Aruba AP567 | Compatível | mc |
| Aruba AP577 | Compatível | mc |
| Aruba AP555 | Compatível | mc |
| Aruba AP635 | Compatível | mc |
| Aruba AP655 | Compatível | mc |
| Aruba AP615 | Compatível | mc |
| Aruba AP734 | Compatível | mc/az |
| Aruba AP735 | Compatível | mc/az |
| Aruba AP754 | Compatível | mc/az |
| Aruba AP755 | Compatível | mc/az |
Smartphones
| Fabricante e modelo | Versão do 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+ |
Dispositivos de varejo, armazenamento e centro de distribuição
| Fabricante e modelo | Versão do 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 e HC) | 10.0+ |
| Zebra EC55 (WAN) | 10.0+ |
| Zebra WT6300 | 10.0+ |
| Skorpio X5 | 10.0+ |