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 esse nível de precisão, é possível criar serviços aprimorados baseados na localização, como a navegação interna, o controle de voz sem ambiguidades (por exemplo, "acenda esta luz") e informações baseadas na localização (por exemplo, "este produto tem ofertas especiais?").
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, somente o dispositivo solicitante pode determinar a distância até o ponto de acesso. Os pontos de acesso não têm essa informação. 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 de medição de tempo preciso (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 o IEEE 802.11az de determinação de alcance não baseada em gatilho (NTB, na sigla em inglês).
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 ao IEEE 802.11az NTB 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 de iniciador IEEE 802.11az
NTB (indicado por
WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR
),
o app poderá encontrar APs compatíveis com IEEE 802.11mc e IEEE 802.11az com uma única
solicitação de alcance. A API RangingResult
foi ampliada para fornecer informações
sobre o valor mínimo e máximo que pode ser usado para o intervalo entre
medições de alcance, deixando o intervalo exato sob o controle do app.
Requisitos
- O hardware do dispositivo que faz a solicitação de alcance precisa implementar o padrão de FTM 802.11-2016 ou o padrão 802.11az (alcance não baseado em gatilho).
- O dispositivo que faz a solicitação de alcance precisa executar o Android 9 (API de nível 28) ou versão mais recente. O alcance sem gatilho IEEE 802.11az é ativado 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 está fazendo a solicitação de medição de distância for direcionado ao
Android 13 (nível 33 da API) ou mais recente, ele precisará ter a
permissão
NEARBY_WIFI_DEVICES
. Se o 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 de FTM IEEE 802.11-2016 ou o padrão IEEE 802.11az (alcance não baseado em gatilho).
Configurar
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.
Por isso, você precisa solicitá-las no tempo de execução toda vez 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 do tempo 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 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 Wi-Fi RTT pode estar presente no dispositivo, mas 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 ser compatíveis com o Wi-Fi RTT se o SoftAP ou o tethering estiverem em uso. Para verificar
se o Wi-Fi RTT 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 alcance
(RangingRequest
) é criada
especificando uma lista de pontos de acesso ou pontos do Wi-Fi Aware para os quais um alcance
é solicitado. É 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 e fazer a medição da distância correspondente:
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
recebido chamando
WifiManager.getScanResults()
.
Você pode usar
addAccessPoints(List<ScanResult>)
para adicionar vários pontos de acesso em um lote.
Os objetos ScanResult
podem conter APs com suporte para IEEE 802.11mc (is80211mcResponder()
) e
IEEE 802.11az (is80211azNtbResponder()
) de medição de distância sem gatilho. Os dispositivos com suporte para o alcance NTB IEEE 802.11az executam o alcance 802.11mc ou
802.11az, dependendo da capacidade do AP, com padrão 802.11az quando
o AP oferece suporte a ambos. Os dispositivos que não oferecem suporte ao IEEE 802.11az realizam todo
o alcance usando o protocolo IEEE 802.11mc.
Da mesma forma, uma solicitação de alcance pode adicionar um ponto do Wi-Fi Aware usando o endereço
MAC ou o PeerHandle
, com os métodos
addWifiAwarePeer(MacAddress peer)
e addWifiAwarePeer(PeerHandle peer)
, respectivamente. Para saber mais sobre como descobrir pontos do Wi-Fi Aware,
consulte a documentação do Wi-Fi Aware.
Solicitar o alcance
Um app envia uma solicitação de alcance usando o método
WifiRttManager.startRanging()
e fornecendo as seguintes informações: um
RangingRequest
para especificar a
operação, um Executor
para especificar
o contexto do 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 alcance é executada de forma assíncrona, e os resultados são
retornados em um dos callbacks de
RangingResultCallback
:
- Se a operação de alcance falhar, o callback
onRangingFailure
será 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 alcance for concluída, o callback
onRangingResults
será 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 obtido a partir do resultado de alcance 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 concluída, 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 concluída (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 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 ter decorrido, a API encerrará a sessão de alcance não acionado e negociará uma nova sessão de alcance com a estação que responder. Evite solicitar uma nova sessão de medição, porque isso aumenta a sobrecarga do tempo de medição. Para aproveitar ao máximo a eficiência de medição sem gatilho do 802.11az, acione a próxima solicitação de medição entre o tempo mínimo e máximo de medição especificado na mediçãoRangingResult
anterior.Repetições de campo de treinamento longo (LTF, na sigla em inglês) que as estações de acionador e de resposta usaram no preâmbulo para o resultado de NTB do IEEE 802.11az:
Número de streams de tempo espacial (STS) de transmissão e recebimento que a estação iniciadora usou para o resultado de NTB do 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, armazém e centro de distribuição compatíveis com o WiFi-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 de suporte |
---|---|
Nest Wifi Pro (Wi-Fi 6E) | Compatível |
Compulab WILD AP | Compatível |
Google Wi-Fi | Compatível |
Roteador Google Nest Wifi | Compatível |
Ponto Google Nest Wifi | Compatível |
Aruba AP-635 | Compatível |
Cisco 9130 | Compatível |
Cisco 9136 | Compatível |
Cisco 9166 | Compatível |
Cisco 9164 | Compatível |
Aruba AP-505 | Compatível |
Aruba AP-515 | Compatível |
Aruba AP-575 | Compatível |
Aruba AP-518 | Compatível |
Aruba AP-505H | Compatível |
Aruba AP-565 | Compatível |
Aruba AP-535 | Compatível |
Smartphones
Fabricante e Modelo | Versão do Android |
---|---|
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, centro de distribuição e armazém
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+ |