Com o Wear OS by Google, um smartwatch pode se conectar diretamente a uma rede, sem acesso a um smartphone Android ou iOS. Esse acesso direto substitui o uso (no Wear 1.x) da API Data Layer para se conectar a uma rede.
Acesso à rede
Os apps Wear OS podem fazer solicitações de rede. Quando um smartwatch tem conexão Bluetooth com um smartphone, o tráfego de rede do relógio geralmente é colocado em proxy pelo smartphone. Porém, quando o smartphone não está disponível, as redes celulares e Wi-Fi são usadas, dependendo do hardware. A plataforma Wear OS processa as transições entre redes.
Você pode usar protocolos como HTTP, TCP e UDP. Entretanto, as APIs android.webkit, incluindo a classe CookieManager, não estão disponíveis. Você pode usar cookies lendo e gravando cabeçalhos em solicitações e respostas.
Além disso, recomendamos que você use o seguinte:
- A API JobScheduler para tarefas assíncronas, incluindo pesquisas em intervalos regulares (descritos abaixo).
- APIs para várias redes, se você precisar se conectar a tipos de rede específicos. Consulte Diversas conexões de rede.
Acesso à rede de alta largura de banda
A plataforma Wear OS gerencia a conectividade de rede para proporcionar a melhor experiência geral do usuário. A plataforma escolhe a rede padrão ativa considerando dois fatores:
- Necessidade de uma longa duração da bateria
- Necessidade de largura de banda da rede
Quando a economia da bateria é priorizada, a rede ativa pode ter largura de banda insuficiente para realizar tarefas de rede que exijam alta largura de banda, como enviar arquivos grandes ou fazer streaming de mídia.
Esta seção traz instruções sobre o uso da classe ConnectivityManager para garantir que a largura de banda necessária esteja disponível para seu app. Para ver informações gerais sobre controle detalhado de recursos de rede, consulte Gerenciar o uso da rede.
Adquirir uma rede de alta largura de banda
No Wear OS, não presuma que uma rede de alta largura de banda sempre estará disponível. Para casos que precisam de acesso a uma rede de alta largura de banda, como envio de arquivos grandes ou streaming de mídia, recomendamos que você siga os seguintes passos:
- Verifique se há uma rede ativa. Caso haja alguma, verifique a largura de banda.
- Se não houver nenhuma rede ativa ou se a largura de banda for insuficiente, solicite acesso a uma rede celular ou Wi-Fi ilimitada.
Você pode usar a classe ConnectivityManager para verificar se há alguma rede ativa e se ela tem largura de banda suficiente:
Kotlin
const val MIN_BANDWIDTH_KBPS = 320 connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val bandwidth: Int = connectivityManager.activeNetwork?.let { activeNetwork -> connectivityManager.getNetworkCapabilities(activeNetwork).linkDownstreamBandwidthKbps } ?: -1 when { bandwidth < 0 -> { // No active network } bandwidth in (0 until MIN_BANDWIDTH_KBPS) -> { // Request a high-bandwidth network } else -> { // You already are on a high-bandwidth network, so start your network request } }
Java
int MIN_BANDWIDTH_KBPS = 320; connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); Network activeNetwork = connectivityManager.getActiveNetwork(); if (activeNetwork != null) { int bandwidth = connectivityManager.getNetworkCapabilities(activeNetwork).getLinkDownstreamBandwidthKbps(); if (bandwidth < MIN_BANDWIDTH_KBPS) { // Request a high-bandwidth network } else { // You already are on a high-bandwidth network, so start your network request } } else { // No active network }
Você pode solicitar uma rede de alta largura de banda ilimitada usando o
ConnectivityManager. Com uma única solicitação de rede, você pode solicitar
uma rede celular ou Wi-Fi ilimitada. Quando a rede estiver pronta (por exemplo,
se o rádio Wi-Fi do dispositivo se conectar a uma rede salva), o
método onAvailable()
da sua instância NetworkCallback
será chamado. Se nenhuma rede adequada for encontrada, o
método onAvailable()
não será chamado. Por isso, você precisará
definir o tempo limite da sua solicitação manualmente. Consulte Aguardar a disponibilidade de rede.
Kotlin
networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { if (bindProcessToNetwork(network)) { // socket connections will now use this network } else { // app doesn't have android.permission.INTERNET permission } } } val request: NetworkRequest = NetworkRequest.Builder().run { addTransportType(NetworkCapabilities.TRANSPORT_WIFI) addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) build() } connectivityManager.requestNetwork(request, networkCallback)
Java
networkCallback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { if (bindProcessToNetwork(network)) { // socket connections will now use this network } else { // app doesn't have android.permission.INTERNET permission } } }; NetworkRequest request = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .build(); connectivityManager.requestNetwork(request, networkCallback);
Liberar rede
Quando seu app não precisar mais da rede de alta largura de banda, você precisará liberar a rede usando a classe ConnectivityManager para garantir que a plataforma possa retomar o gerenciamento do acesso à rede.
Kotlin
connectivityManager.bindProcessToNetwork(null) connectivityManager.unregisterNetworkCallback(networkCallback)
Java
connectivityManager.bindProcessToNetwork(null); connectivityManager.unregisterNetworkCallback(networkCallback);
Para otimizar o consumo da bateria, uma conexão de rede precisa ficar
registrada somente durante a atividade. Por isso, recomendamos
liberar a rede no método onStop()
da sua
atividade.
Aguardar a disponibilidade de rede
A aquisição de uma rede pode não ser instantânea, porque o rádio Wi-Fi ou
celular de um smartphone pode estar desativado para economizar bateria. Além disso, se um relógio
não puder se conectar a uma rede, o método onAvailable()
da
sua instância NetworkCallback
não será chamado. Por isso, você
precisa definir o tempo limite da solicitação após um período predeterminado e
liberar os recursos associados.
Kotlin
const val MESSAGE_CONNECTIVITY_TIMEOUT = 1 const val NETWORK_CONNECTIVITY_TIMEOUT_MS: Long = 10000 ... handler = MyHandler() networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { handler.removeMessages(MESSAGE_CONNECTIVITY_TIMEOUT) ... } } connectivityManager.requestNetwork(request, networkCallback) handler.sendMessageDelayed( handler.obtainMessage(MESSAGE_CONNECTIVITY_TIMEOUT), NETWORK_CONNECTIVITY_TIMEOUT_MS ) ... // Don't make this an inner class otherwise there is the potential to leak the parent class private class MyHandler : Handler() { override fun handleMessage(msg: Message) { when (msg.what) { MESSAGE_CONNECTIVITY_TIMEOUT -> { // unregister the network } } } }
Java
int MESSAGE_CONNECTIVITY_TIMEOUT = 1; long NETWORK_CONNECTIVITY_TIMEOUT_MS = 10000; handler = new MyHandler(); networkCallback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { handler.removeMessages(MESSAGE_CONNECTIVITY_TIMEOUT); ... } }; connectivityManager.requestNetwork(request, networkCallback); handler.sendMessageDelayed( handler.obtainMessage(MESSAGE_CONNECTIVITY_TIMEOUT), NETWORK_CONNECTIVITY_TIMEOUT_MS); ... // This needs to be static to avoid potentially leaking the parent class private static class MyHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_CONNECTIVITY_TIMEOUT: // unregister the network break; } } }
Monitorar o status da rede
A interface NetworkCallback
tem métodos para o monitoramento
de mudanças de status da rede vinculada, como mudanças de largura de banda e
perda de conectividade.
Kotlin
networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { val bandwidth: Int = networkCapabilities.linkDownstreamBandwidthKbps if (bandwidth < MIN_BANDWIDTH_KBPS) { // handle insufficient network bandwidth } } override fun onLost(network: Network) { // handle network loss } }
Java
networkCallback = ConnectivityManager.NetworkCallback { @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { int bandwidth = networkCapabilities.getLinkDownstreamBandwidthKbps(); if (bandwidth < MIN_BANDWIDTH_KBPS) { // handle insufficient network bandwidth } } @Override public void onLost(Network network) { // handle network loss } }
Iniciar a atividade de configuração de Wi-Fi
Ao solicitar uma rede Wi-Fi, o sistema tenta se conectar a uma rede salva
se alguma tiver sido configurada e estiver dentro do alcance. No entanto, se nenhuma
rede Wi-Fi salva estiver disponível, o método de callback onAvailable()
para sua instância NetworkCallback
nunca será chamado. Se
você estiver usando um Handler
para definir o tempo limite da solicitação de rede, será
possível direcionar o usuário a uma rede Wi-Fi quando o tempo limite for atingido.
Você pode levar o usuário diretamente ao usuário para adicionar uma rede Wi-Fi
usando a seguinte intent:
Kotlin
context.startActivity(Intent("com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS"))
Java
context.startActivity(new Intent("com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS"));
Para iniciar a atividade de configuração, o app precisa ter a seguinte
permissão: android.permission.CHANGE_WIFI_STATE
Considerações sobre a interface do usuário
Se seu app precisar de uma conexão com uma nova rede Wi-Fi para uma operação de alta largura de banda, verifique se o motivo para a conexão está claro para o usuário antes de iniciar as configurações de Wi-Fi. Só solicite que um usuário adicione uma nova rede Wi-Fi quando a rede de alta largura de banda for necessária. Não bloqueie o acesso de um usuário a recursos do app que não precisem de uma rede de alta largura de banda.
A Figura 1 mostra, por exemplo, um app de música. O app precisa permitir que o usuário procure músicas e só solicitar que ele adicione uma nova rede Wi-Fi se ele quiser fazer o download ou streaming de músicas.

Figura 1. Fluxo de um app para download de música.
Se seu app precisar de uma rede de alta largura de banda para funcionar, você precisa mostrar uma justificativa clara antes de solicitar que o usuário adicione uma nova rede Wi-Fi. Além disso, para operações de rede longas, como o download de uma playlist de mídia, você precisa apresentar um indicador de progresso com uma descrição de que a operação está sendo realizada.
A Figura 2 mostra o app em um fluxo de streaming de música. Se o usuário quiser fazer streaming de músicas e precisar de uma rede de alta largura de banda, o app terá que explicar claramente por que a rede Wi-Fi é necessária antes de levar o usuário às configurações de Wi-Fi.

Figura 2. Fluxo de um app para streaming de música.
Mensagens na nuvem
Para enviar notificações, os apps podem usar diretamente o Firebase Cloud Messaging (FCM), que substitui o Google Cloud Messaging (GCM). O FCM é compatível com o Wear 2.0 e o GCM não.
Nenhuma API para acesso à rede ou FCM é específica do Wear OS. Consulte a documentação existente sobre como se conectar a uma rede e sobre mensagens na nuvem.
O FCM funciona bem com a Soneca e é a forma recomendada de enviar notificações para um smartwatch.
Forneça mensagens do FCM coletando um token de registro para um dispositivo quando o app Wear for executado. Em seguida, inclua o token como parte do destino quando o servidor enviar mensagens para o endpoint REST do FCM. O FCM enviará mensagens para o dispositivo identificado pelo token.
As mensagens do FCM estão no formato JSON e podem incluir um dos seguintes payloads ou ambos:
- Payload de notificação: Quando um payload de notificação é recebido por um smartwatch, os dados são exibidos ao usuário no stream de notificações. Quando o usuário toca na notificação, o app é iniciado.
- Payload de dados: o payload tem um conjunto de pares de chave-valor personalizados. O payload é entregue como dados para o app Wear.
Para ver mais informações e exemplos de payloads, consulte Sobre as mensagens do FCM.
Por padrão, as notificações são compartilhadas de um app do smartphone para um smartwatch. Se você tiver um app Wear independente e um app de smartphones correspondente, pode haver notificações duplicadas. Por exemplo, a mesma notificação do FCM, recebida tanto pelo smartphone como pelo smartwatch, pode ser exibida por ambos os dispositivos de maneira independente.
Usar serviços em segundo plano
Para garantir que as tarefas em segundo plano sejam executadas corretamente, é preciso considerar a Soneca. No Android 6.0, a Soneca e o App em espera melhoraram a duração da bateria.
A Soneca foi aprimorada no Android Nougat e no Wear OS. Quando uma tela é desligada ou entra no modo ambiente por um certo período, pode ocorrer uma subconfiguração da Soneca, e tarefas em segundo plano podem ser adiadas por algum tempo. Depois, quando um dispositivo fica inativo por um tempo prolongado, a Soneca normal ocorre.
Você precisa programar tarefas com a API JobScheduler, que permite que o app registre uma execução de código que não seja afetada pela Soneca. Ao programar tarefas, você pode selecionar limites, como a execução periódica e a necessidade de conectividade ou carregamento do dispositivo. Configure tarefas de uma maneira que não afete negativamente a duração da bateria. As tarefas precisam usar um objeto JobInfo.Builder para criar limites e metadados, como um ou mais dos seguintes métodos para tarefa:
- Para programar uma tarefa que exija rede, use
setRequiredNetworkType(int networkType)
, especificandoNETWORK_TYPE_ANY
ouNETWORK_TYPE_UNMETERED
.NETWORK_TYPE_UNMETERED
é usado para grandes transferências de dados, enquantoNETWORK_TYPE_ANY
é para transferências pequenas - Para programar uma tarefa durante o carregamento, use
setRequiresCharging(boolean requiresCharging)
- Para especificar que o dispositivo está inativo para uma tarefa, use
setRequiresDeviceIdle(boolean requiresDeviceIdle)
. Esse método é útil para trabalhos ou sincronizações em segundo plano de baixa prioridade, especialmente quando usado comsetRequiresCharging
Observe que algumas redes de baixa largura de banda, como Bluetooth LE, são consideradas limitadas.
Agendar restrições
Você pode programar uma tarefa que precise de restrições. No exemplo abaixo,
um objeto JobScheduler
ativa MyJobService
quando as seguintes restrições são respeitadas:
- Rede ilimitada
- Carregamento do dispositivo
Você pode usar o método do builder setExtras
para anexar um pacote
de metadados específicos do app à solicitação de tarefa. Quando a tarefa for executada, esse
pacote será fornecido ao serviço da tarefa. O valor MY_JOB_ID
transmitido ao construtor JobInfo.Builder
. Esse
valor MY_JOB_ID
é um identificador fornecido pelo app. Chamadas
de cancelamento e tarefas subsequentes criadas com o mesmo valor
atualizarão a tarefa existente:
Kotlin
JobInfo.Builder(MY_JOB_ID, ComponentName(this, MyJobService::class.java)) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .setExtras(extras) .build() .also { jobInfo -> (getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler) .schedule(jobInfo) }
Java
JobInfo jobInfo = new JobInfo.Builder(MY_JOB_ID, new ComponentName(this, MyJobService.class)) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .setExtras(extras) .build(); ((JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE)) .schedule(jobInfo);
Abaixo, há uma implementação de um
JobService para processar a tarefa acima. Quando a tarefa é executada, um
objeto JobParameters
é transmitido ao
método onStartJob
. O objeto JobParameters
permite que você tenha acesso ao valor do ID da tarefa juntamente a quaisquer pacotes
extras fornecidos ao programar a tarefa. O método onStartJob
é chamado na
linha de execução principal do aplicativo e, por isso, qualquer lógica de alto custo precisa ser
executada em uma linha diferente. No exemplo, uma AsyncTask
é
usada para executar códigos em segundo plano. Quando o trabalho for concluído, você chamará
o método jobFinished
para notificar JobScheduler
de que a tarefa foi concluída:
Kotlin
private class MyJobService : JobService() { override fun onStartJob(params: JobParameters): Boolean { JobAsyncTask().execute(params) return true } private class JobAsyncTask : AsyncTask<...>() { ... } }
Java
public class MyJobService extends JobService { @Override public boolean onStartJob(JobParameters params) { new JobAsyncTask().execute(params); return true; } private class JobAsyncTask extends AsyncTask