O Android permite que os apps aprendam sobre mudanças dinâmicas na conectividade. Use as classes a seguir para monitorar e responder a mudanças de conectividade:
ConnectivityManager
informa o app sobre o estado da conectividade no sistema.- A classe
Network
representa uma das redes a que o dispositivo está conectado. Use o objetoNetwork
como uma chave para coletar informações sobre a rede comConnectivityManager
ou para vincular soquetes na rede. Quando a rede é desconectada, o objetoNetwork
não pode mais ser usado. Mesmo se o dispositivo se conectar novamente à mesma rede, um novo objetoNetwork
representará a nova rede. - O objeto
LinkProperties
contém informações sobre o link de uma rede, como a lista de servidores DNS, endereços IP locais e as rotas instaladas na rede. - O objeto
NetworkCapabilities
contém informações sobre as propriedades de uma rede, como os transportes (Wi-Fi, móvel, Bluetooth) e os recursos da rede. Por exemplo, você pode consultar o objeto para determinar se a rede é capaz de enviar MMS, se tem um portal cativo ou se é limitada.
Os apps interessados no estado imediato da conectividade podem
chamar métodos ConnectivityManager
a qualquer momento para descobrir que tipo de rede está
disponível. Esses métodos são úteis para depuração e, ocasionalmente, para analisar um
snapshot de conectividade disponível no momento.
No entanto, os métodos síncronos
ConnectivityManager
não informam o app sobre o que acontece
após uma chamada, então eles não permitem atualizar a interface. Eles também não podem ajustar o comportamento
do app com base na desconexão da rede ou quando os recursos da rede
mudarem.
A conectividade pode mudar a qualquer momento e a maioria dos apps precisa ter uma
visualização sempre atualizada do estado da rede no dispositivo. Os apps podem
registrar um callback com ConnectivityManager
para serem alertados sobre mudanças importantes
para eles. Ao usar o callback, o app pode reagir imediatamente a qualquer
mudança relevante da conectividade sem precisar recorrer a pesquisas custosas
que podem não refletir atualizações rápidas.
O uso de NetworkCallback
, assim como outras maneiras de descobrir o
estado de conectividade do dispositivo, não exige nenhuma permissão específica.
No entanto, algumas redes estão sujeitas a essas permissões.
Por
exemplo, pode haver redes restritas que não estejam disponíveis para apps. A vinculação a uma
rede em segundo plano requer a permissão CHANGE_NETWORK_STATE
. Além disso, algumas
chamadas podem precisar de permissões específicas para serem executadas. Para saber mais detalhes, consulte a documentação específica
de cada chamada.
Acessar o estado instantâneo
Um dispositivo Android pode manter muitas conexões ao mesmo tempo.
Para saber mais sobre o estado atual da rede, extraia
uma instância de ConnectivityManager
:
Kotlin
val connectivityManager = getSystemService(ConnectivityManager::class.java)
Java
ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);
Em seguida, use essa instância para acessar uma referência à rede padrão atual do app:
Kotlin
val currentNetwork = connectivityManager.getActiveNetwork()
Java
Network currentNetwork = connectivityManager.getActiveNetwork();
Com uma referência a uma rede, o app poderá exigir informações sobre ela:
Kotlin
val caps = connectivityManager.getNetworkCapabilities(currentNetwork) val linkProperties = connectivityManager.getLinkProperties(currentNetwork)
Java
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(currentNetwork); LinkProperties linkProperties = connectivityManager.getLinkProperties(currentNetwork);
Para recursos mais úteis, registre um
NetworkCallback
.
Para mais informações sobre como registrar callbacks de rede, consulte
Ouvir eventos de rede.
NetworkCapabilities e LinkProperties
Os objetos NetworkCapabilities
e LinkProperties
fornecem informações sobre
todos os atributos que o sistema sabe sobre uma rede.
O objeto LinkProperties
sabe sobre rotas, endereços de link, nome da interface, informações do proxy (se
houver) e servidores DNS. Chame o método relevante no objeto LinkProperties
para acessar as informações necessárias.
O objeto NetworkCapabilities
encapsula informações sobre os transportes de rede e os respectivos recursos.
Um transporte é uma abstração de um meio físico pelo qual uma rede
opera. Exemplos comuns de transportes são Ethernet, Wi-Fi e dados móveis.
VPNs e Wi-Fi ponto a ponto também podem cumprir essa função.
No Android, uma rede pode ter vários transportes ao mesmo tempo. Um exemplo
é uma VPN que opera em redes Wi-Fi e móveis. Ela tem os
transportes Wi-Fi, móveis e VPN. Para descobrir se uma
rede tem um transporte específico, use o método
NetworkCapabilities.hasTransport(int)
com uma das constantes NetworkCapabilities.TRANSPORT_*
.
Um recurso descreve uma propriedade da rede. Os recursos de exemplo incluem
MMS
, NOT_METERED
e INTERNET
. Uma rede com o recurso de MMS pode enviar
e receber mensagens de serviços de mensagens multimídia, enquanto uma rede sem esse
recurso não pode. Redes com o recurso NOT_METERED
não cobram o
usuário pelo uso de dados. O app pode verificar os recursos adequados usando o método
NetworkCapabilities.hasCapability(int)
com uma das constantes NetworkCapabilities.NET_CAPABILITY_*
.
As constantes NET_CAPABILITY_*
mais úteis incluem:
NET_CAPABILITY_INTERNET
: indica que a rede está configurada para acessar a Internet. Isso está relacionado à configuração, e não à capacidade real de acessar servidores públicos. Por exemplo, uma rede pode estar configurada para acessar a Internet, mas estar sujeita a um portal cativo.A rede móvel de uma operadora normalmente tem o recurso
INTERNET
, enquanto uma rede Wi-Fi P2P local normalmente não tem. Para conferir a conectividade real, consulteNET_CAPABILITY_VALIDATED
.NET_CAPABILITY_NOT_METERED
: indica que a rede não é limitada. Uma rede é classificada como limitada quando o usuário precisa se preocupar com o uso intenso de dados nessa conexão devido a custos monetários, limitações de dados ou problemas de desempenho da bateria.NET_CAPABILITY_NOT_VPN
: indica que a rede não é uma rede privada virtual.NET_CAPABILITY_VALIDATED
: indica que a rede fornece acesso real à Internet pública quando é sondada. Uma rede protegida por um portal cativo ou uma rede que não fornece resolução de nome de domínio não tem esse recurso. Esse é o máximo de precisão que o sistema pode ter ao indicar se uma rede está realmente fornecendo acesso. No entanto, uma rede validada ainda pode, a princípio, estar sujeita à filtragem baseada em IP ou sofrer perdas repentinas de conectividade devido a problemas, como sinal fraco.NET_CAPABILITY_CAPTIVE_PORTAL
: indica que a rede tem um portal cativo quando é sondada.
Há outros recursos pelos quais apps mais especializados podem se interessar.
Para mais informações, leia as definições de parâmetro em
NetworkCapabilities.hasCapability(int)
.
Os recursos de uma rede podem mudar a qualquer momento. Quando o sistema detectar um
portal cativo, ele mostrará uma notificação pedindo que o usuário faça login. Enquanto isso
estiver em andamento, a rede terá os recursos NET_CAPABILITY_INTERNET
e
NET_CAPABILITY_CAPTIVE_PORTAL
, mas não o
NET_CAPABILITY_VALIDATED
.
Quando o usuário realizar ações e fizer login na
página do portal cativo, o dispositivo poderá acessar a Internet pública.
A rede passará a ter o recurso NET_CAPABILITY_VALIDATED
e perderá o recurso
NET_CAPABILITY_CAPTIVE_PORTAL
.
Da mesma forma, os transportes de uma
rede podem mudar dinamicamente.
Por exemplo, uma VPN pode ser reconfigurada para usar
uma rede mais rápida que acabou de ficar disponível, como alternar a rede atual de móvel
para Wi-Fi. Nesse caso, a rede vai perder o transporte TRANSPORT_CELLULAR
e receber o transporte TRANSPORT_WIFI
, mantendo o
TRANSPORT_VPN
.
Ouvir eventos de rede
Para saber mais sobre eventos de rede, use a classe
NetworkCallback
com
ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback)
e
ConnectivityManager.registerNetworkCallback(NetworkCallback)
. Esses dois métodos têm propósitos
distintos.
Todos os apps Android têm uma rede padrão determinada pelo sistema. Normalmente, o sistema prefere usar as redes ilimitadas em vez das limitadas, e as redes mais rápidas em vez das lentas.
Quando um app enviar uma solicitação de rede, como
HttpsURLConnection
, o
sistema completa essa solicitação usando a rede padrão. Os apps também podem enviar tráfego
em outras redes. Para saber mais, consulte a seção sobre outras
redes.
A rede definida como padrão pode mudar a qualquer momento durante o ciclo de vida de um app. Um exemplo típico seria o dispositivo entrando no alcance de um ponto de acesso Wi-Fi ilimitado, ativo e mais rápido que o sinal da rede móvel. O dispositivo se conecta a esse ponto de acesso e muda a rede padrão de todos os apps para a nova rede Wi-Fi.
Quando uma nova rede se tornar a rede padrão, qualquer nova conexão aberta por um app usará essa rede. Em algum momento posterior, todas as conexões restantes na rede padrão anterior serão encerradas à força. Se for importante que o app saiba quando a rede padrão mudar, ele precisará registrar um callback de rede padrão desta forma:
Kotlin
connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network : Network) { Log.e(TAG, "The default network is now: " + network) } override fun onLost(network : Network) { Log.e(TAG, "The application no longer has a default network. The last default network was " + network) } override fun onCapabilitiesChanged(network : Network, networkCapabilities : NetworkCapabilities) { Log.e(TAG, "The default network changed capabilities: " + networkCapabilities) } override fun onLinkPropertiesChanged(network : Network, linkProperties : LinkProperties) { Log.e(TAG, "The default network changed link properties: " + linkProperties) } })
Java
connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { Log.e(TAG, "The default network is now: " + network); } @Override public void onLost(Network network) { Log.e(TAG, "The application no longer has a default network. The last default network was " + network); } @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { Log.e(TAG, "The default network changed capabilities: " + networkCapabilities); } @Override public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { Log.e(TAG, "The default network changed link properties: " + linkProperties); } });
Quando uma nova rede se tornar a padrão, o app receberá uma chamada de
onAvailable(Network)
para a nova rede. Implemente
onCapabilitiesChanged(Network,NetworkCapabilities)
,
onLinkPropertiesChanged(Network,LinkProperties)
ou ambos para reagir de maneira adequada a mudanças na conectividade.
Para um callback registrado com registerDefaultNetworkCallback()
, onLost()
significa que a rede perdeu o status de rede padrão. Ela pode estar desconectada.
Para saber mais sobre os transportes que a rede padrão está usando,
consulte
NetworkCapabilities.hasTransport(int)
.
Esse é um proxy ruim em relação à largura de banda ou redes limitadas. O app
não pode presumir que o Wi-Fi sempre seja ilimitado e sempre forneça uma largura de banda melhor
do que a rede móvel.
Em vez disso, use
NetworkCapabilities.getLinkDownstreamBandwidthKbps()
para medir a largura de banda e
NetworkCapabilites.hasCapability(int)
com argumentos
NET_CAPABILITY_NOT_METERED
para determinar a limitação da rede. Para mais informações, consulte a seção
NetworkCapabilities e LinkProperties.
Por padrão, os métodos de callback são chamados na linha de execução de conectividade do
app, que é uma linha de execução separada usada por ConnectivityManager
. Se a
implementação dos callbacks precisar realizar trabalhos mais longos, chame-os em uma
linha de execução de worker separada usando a variante
ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler)
.
Chame ConnectivityManager.unregisterNetworkCallback(NetworkCallback)
para cancelar o registro do seu callback quando não precisar mais usá-lo.
O método onPause()
da sua atividade principal é um bom lugar para fazer isso, especialmente se você registrar o callback em
onResume()
.
Mais redes
Embora a rede padrão seja a única rede relevante para a maioria dos apps, alguns
podem
precisar de outras redes disponíveis. Para saber mais sobre essas redes, os apps
criam uma NetworkRequest
que corresponde às
necessidades deles e chamam
ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback)
.
O processo é semelhante à detecção
de uma rede padrão. Embora possa haver apenas uma
rede padrão que se aplique a um app por vez, essa versão permite que o
app verifique todas as redes disponíveis simultaneamente. Dessa forma, uma chamada para
onLost(Network)
significa que a rede foi completamente desconectada, e não que ela deixou de ser a rede
padrão.
O app cria uma NetworkRequest
para informar ao ConnectivityManager
sobre o tipo
de rede que ele quer detectar. O exemplo abaixo mostra como criar uma
NetworkRequest
para um app que está interessado apenas em conexões de Internet
ilimitadas:
Kotlin
val request = NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .build() connectivityManager.registerNetworkCallback(request, myNetworkCallback)
Java
NetworkRequest request = new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .build(); connectivityManager.registerNetworkCallback(request, myNetworkCallback);
Isso significa que o app detecta todas as mudanças relacionadas a qualquer rede ilimitada no sistema.
Para o callback de rede padrão, há uma versão do
registerNetworkCallback(NetworkRequest, NetworkCallback, Handler)
que aceita um Handler
para que ele não carregue a linha de execução Connectivity
do seu
app.
Chame
ConnectivityManager.unregisterNetworkCallback(NetworkCallback)
quando o callback não for mais relevante. Um app pode registrar simultaneamente
vários callbacks de rede.
Por conveniência, o objeto
NetworkRequest
contém os
recursos comuns que a maioria dos apps precisa, incluindo:
Ao criar seu app, verifique se padrões correspondem ao caso de uso e apague-os se quiser que o app seja notificado sobre redes que não têm esses recursos. Por outro lado, adicione recursos para evitar chamadas para qualquer mudança de conectividade nas redes com as quais o app não interage.
Por exemplo, se o app precisar enviar mensagens MMS, adicione
NET_CAPABILITY_MMS
ao NetworkRequest
para evitar notificações sobre todas as redes que não podem
enviar mensagens MMS. Adicione
TRANSPORT_WIFI_AWARE
se o app só tiver interesse na conectividade Wi-Fi P2P.
NET_CAPABILITY_INTERNET
e
NET_CAPABILITY_VALIDATED
são úteis se você tiver interesse em transferir dados com um servidor
na Internet.
Exemplo de sequência de callbacks
Esta seção descreve a sequência de callbacks que um app pode receber se registrar um callback padrão e um callback normal em um dispositivo que tenha conectividade móvel. Neste exemplo, o dispositivo se conecta a um bom ponto de acesso Wi-Fi e depois se desconecta. O exemplo também pressupõe que o dispositivo tenha ativado a configuração Dados móveis sempre ativados.
Ocorre o seguinte:
Quando o app chamar
registerNetworkCallback()
, o callback receberá imediatamente chamadas deonAvailable()
,onNetworkCapabilitiesChanged()
eonLinkPropertiesChanged()
da rede móvel, porque apenas essa rede está disponível. Se outra rede estiver disponível, o app também vai receber callbacks para a outra rede.
Figura 1. Estado do app depois de chamarregisterNetworkCallback()
.Depois, o app chamará
registerDefaultNetworkCallback()
. O callback de rede padrão começa a receber chamadas paraonAvailable()
,onNetworkCapabilitiesChanged()
eonLinkPropertiesChanged()
na rede móvel porque ela é a rede padrão. Se outra rede não padrão estiver ativa, o app não vai poder receber chamadas dessa rede.
Figura 2. Estado do app depois de registrar uma rede padrão.Em seguida, o dispositivo se conectará a uma rede Wi-Fi (ilimitada). O callback normal da rede recebe chamadas de
onAvailable()
,onNetworkCapabilitiesChanged()
eonLinkPropertiesChanged()
na rede Wi-Fi.
Figura 3. Estado do app depois de se conectar a uma rede Wi-Fi ilimitada.Talvez leve algum tempo até que a rede Wi-Fi seja validada. Nesse caso, as chamadas
onNetworkCapabilitiesChanged()
para o callback normal da rede não incluem o recursoNET_CAPABILITY_VALIDATED
. Depois de um curto período, ele recebe uma chamada paraonNetworkCapabilitiesChanged()
, em que os novos recursos incluemNET_CAPABILITY_VALIDATED
. Na maioria dos casos, a validação é muito rápida.Quando a rede Wi-Fi é validada, o sistema a prioriza em relação à rede móvel, principalmente porque é ilimitada. A rede Wi-Fi se tornará a rede padrão. O callback da rede padrão vai receber uma chamada para
onAvailable()
,onNetworkCapabilitiesChanged()
eonLinkPropertiesChanged()
da rede Wi-Fi. A rede móvel será movida para o segundo plano, e o callback de rede normal vai receber uma chamadaonLosing()
da rede móvel.Como este exemplo supõe que os dados móveis estejam sempre ativados neste dispositivo, a rede móvel nunca é desconectada. Se a configuração for desativada, após um tempo a rede móvel será desconectada e o callback de rede normal vai receber uma chamada para
onLost()
.
Figura 4. Estado do app após a validação da rede Wi-Fi.Mais tarde, o dispositivo se desconecta do Wi-Fi subitamente porque saiu do alcance. Como o Wi-Fi se desconecta, o callback de rede normal receberá uma chamada
onLost()
da conexão Wi-Fi. Como a rede móvel passa a ser a padrão, o callback de rede padrão receberá chamadasonAvailable()
,onNetworkCapabilitiesChanged()
eonLinkPropertiesChanged()
da rede móvel.
Figura 5. Estado do app após a desconexão da rede Wi-Fi.
Se a configuração Dados móveis sempre ativados estiver desativada, quando o Wi-Fi
for desconectado, o dispositivo tentará se reconectar à rede móvel. O cenário é
semelhante, mas com um pequeno atraso extra para as chamadas onAvailable()
, e
o callback de rede normal também recebe chamadas para onAvailable()
,
onNetworkCapabilitiesChanged()
e onLinkPropertiesChanged()
porque a rede
móvel fica disponível.
Restrições do uso da rede para transferência de dados
Conseguir detectar uma rede com um callback de rede não significa que seu app pode
usá-la para transferência de dados. Algumas redes não oferecem conectividade
com a Internet e outras podem estar restritas a
apps privilegiados. Para verificar a conectividade de Internet, consulte
NET_CAPABILITY_INTERNET
e
NET_CAPABILITY_VALIDATED
.
O uso de redes em segundo plano também está sujeito a verificações de permissão. Se o app
quiser usar uma rede em segundo plano, ele vai precisar da
permissão
CHANGE_NETWORK_STATE
.
Apps com essa permissão deixam o sistema tentar
abrir uma rede que não esteja ativa, como a rede móvel,
quando o dispositivo está conectado a uma rede Wi-Fi. Esse app chama
ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback)
com um NetworkCallback
para ser chamado quando a rede for ativada.