Construindo aplicativos Wear OS com Flutter: um guia muito bom

Tempo de leitura: 11 minutes

Aprenda a criar um aplicativo Wear OS com Flutter e as principais considerações para criar aplicativos Flutter para smartwatches

Desde que executei meu primeiro aplicativo Flutter em um dispositivo Android e um iPhone, não posso deixar de me perguntar sempre que vejo um dispositivo com uma tela: isso pode executar o Flutter?

É tudo especulação até que se aprofunde nas especificações de um dispositivo para ver se o hardware pode lidar com isso. De todos os dispositivos existentes, aqueles com sistemas operacionais baseados no Android provavelmente executarão um aplicativo Flutter sem muitos problemas. Esse é precisamente o caso do Wear OS.

Depois de passar algum tempo experimentando e, finalmente, lançar um jogo Wear OS real, aprendi como fazer o Flutter rodar no pulso de qualquer pessoa, o que levantou algumas questões que eu precisava responder. Perguntas como:

  • Como um aplicativo Wear OS deve funcionar?
  • E a duração da bateria?
  • Os tamanhos e formatos de tela são importantes?
  • Como minha IU deve se comportar?
  • E, finalmente, como enviar o aplicativo?

É disso que estamos falando hoje. Comecemos!

 

Noções básicas sobre o Wear OS

Só porque um aplicativo pode ser executado em diferentes tipos de telas, não significa que o aplicativo deva ter a mesma aparência em todas elas.

Isso ocorre principalmente porque, ao contrário dos smartphones, as restrições físicas de um dispositivo como um wearable podem alterar a usabilidade do aplicativo. Por exemplo, um relógio pode querer refletir um determinado tema durante o dia e durante a noite. Transferir a interface do usuário de um telefone celular diretamente para um smartwatch sem alterações certamente resultará em uma experiência ruim para o usuário.

Do ponto de vista da usabilidade, deve-se considerar o seguinte ao criar aplicativos para smartwatches:

☝️IU com um dedo:
Como se espera que um smartwatch fique preso ao braço do usuário na maior parte do tempo, suponha que toda a entrada que uma tela receberá será de um único dedo. Como resultado, os aplicativos do Wear OS devem evitar gestos multitoque, a menos que sejam totalmente necessários.

🤏 As telas podem ser minúsculas:
Como seria de esperar, os smartwatches têm de estar na moda. Como resultado, as telas podem variar, mas sempre abaixo de alguns centímetros. O relógio Pixel tem 1,24 polegadas, enquanto o Galaxy Watch 5 pro tem 1,4 polegadas. Isso significa que cada pixel na tela é ainda mais precioso do que nos smartphones. Algumas dicas ao criar interface do usuário para telas pequenas:

  • Tente tornar cada visualização autocontida. Use exibições roláveis somente quando necessário e esperado
  • Seja extremamente cuidadoso com as áreas clicáveis dos botões

 

🏠 As telas podem ter formatos estranhos:

O mundo dos smartwatches Android está cheio de telas personalizadas. No caso do Wear OS, é preciso estar preparado para telas quadradas ou circulares.

É essencial notar que dispositivos como o Pixel Watch possuem molduras escuras contínuas nas telas OLED. Isso faz com que fundos escuros ou vinhetas sejam boas opções de design.

⚙️As entradas podem variar:
Os relógios Wear OS têm três tipos principais de entrada de hardware:

  • Tela sensível ao toque
  • Botões físicos
  • Entrada rotativa

Além da tela sensível ao toque, essas entradas não são uniformes entre os diferentes modelos de relógios e podem até estar ausentes em alguns casos.

A entrada rotativa é usada a partir de interações como rolagem. Em relógios como o Samsung Galaxy Watch 4 Classic, ele assume a forma de uma luneta giratória. Em relógios como o Pixel Watch, ele assume a forma de uma coroa lateral que funciona como um único botão de hardware.

Exemplo de diferentes relógios com diferentes entradas de hardware. O da esquerda tem botões de hardware e uma moldura giratória; o do meio tem uma coroa giratória e não tem botões; o da direita não possui entrada rotativa física, mas dois botões físicos. Fotos de mim, Triyansh Gill e Shawn Rain no Unsplash.

 

🔋Reserve a bateria
Os dispositivos Wear OS são bastante poderosos para seu tamanho, mas com grande potência vem o consumo severo de bateria. Ninguém gosta de ver seu relógio morrendo rapidamente porque um aplicativo específico drena toda a sua energia. Esteja ciente de quanta potência de CPU seu aplicativo requer. Vá com calma nas animações e aproveite as UIs escuras em dispositivos baseados em OLED.

⌚️Planeje se seu aplicativo será autônomo
Os aplicativos Wear OS podem ser executados em dispositivos smartwatch sem a necessidade de um aplicativo de smartphone complementar. Esses são chamados de aplicativos autônomos e esse é o tipo de aplicativo que criaremos neste tutorial. Outra consideração é se você oferecerá suporte ao Wear OS 2 e dispositivos anteriores; esta documentação ajuda você a planejar se seu aplicativo Wear OS será ou não um aplicativo independente.

 

Continue lendo
O melhor lugar para saber sobre o Wear OS é sua documentação; aqui estão alguns links úteis sobre o aspecto de usabilidade e anatomia dos aplicativos Wear OS:

 

O estado do suporte do Wear OS no Flutter

Há algumas coisas a se esperar ao criar um aplicativo Wear OS. Mesmo que as pessoas tenham escrito e implantado aplicativos Wear OS feitos com Flutter, ao segmentar smartwatches:

Você deve esperar o seguinte:

  • A maioria (se não todos) os esforços nessa frente são liderados pela comunidade: plugins, exemplos e artigos – como este.
  • A maioria dos recursos disponíveis para Android deve funcionar no Wear OS, incluindo variações e a maioria dos plug-ins.
  • As APIs nativas podem ser acessadas por meio de chamadas de método ou FFIs, como Health Services.

Você não deve esperar o seguinte:

  • Esforços primários, como o suporte oficial para smartwatch da Flutter, são listados como não objetivos.
  • Use recursos específicos do sistema operacional para serem inseridos na estrutura, por exemplo, Platform.isWear. Do ponto de vista do Framework, um aplicativo Wear OS é um aplicativo Android.
  • Um aplicativo para ter diferentes corredores para Wear OS e Android. O código do Wear OS ficará no diretório android; não há suporte para algo em um diretório wearos com um código de plataforma específico.

💡 Que tal criar aplicativos para o Apple Watch? Mais sobre isso no final deste artigo.

 

Como criar um aplicativo Wear OS com o Flutter

Agora que sabemos o que devemos considerar ao criar qualquer aplicativo anexado aos pulsos das pessoas, vamos aprender como usar o Flutter para fazer isso.

 

💡 Antes de começar, você pode preparar um dispositivo para depurar seu aplicativo. Você pode ler sobre como criar um emulador de relógio ou como depurá-lo em um dispositivo físico.

É importante notar que qualquer aplicativo Wear OS é essencialmente apenas um aplicativo Android. Portanto, para executar o Flutter em um dispositivo Wear OS (ou emulador), precisamos ajustar alguns arquivos no diretório android. Além disso, do lado do Flutter, devemos adaptar a interface do usuário para as telas pequenas e obter algumas informações úteis do hardware. Agora que os objetivos estão claros, vamos construir algo!

Neste tutorial, construiremos um aplicativo contador (assim como very_good_core) que:

  • Possui uma interface de usuário escura básica (para economizar energia em dispositivos OLED)
  • Adapta suas cores para quando o relógio entra no modo ambiente
  • O usuário pode usar a entrada rotativa para interagir com a funcionalidade do aplicativo

💡 Criamos um aplicativo de exemplo com todos esses pontos abordados, para que você possa avançar para ver como funciona. Também planejamos criar um modelo a partir disso e adicioná-lo ao Very Good CLI, portanto, fique atento. 👀

Ok, então vamos começar criando o aplicativo usando very_good_cli:

very_good create flutter_app my_app
cd my_app

 

Ativando o suporte do relógio

Depois disso, a ordem do dia é remover os arquivos desnecessários. Como estamos criando um aplicativo autônomo somente para Wear OS, precisaremos apenas de executores para Android. Remova as pastas macos, ios, web, linux e windows.

Depois disso, devemos adicionar alguns plugins úteis que usaremos mais adiante neste tutorial. Esses são os pacotes wear e wearable_rotary:

flutter pub add wear wearable_rotary

Agora, para tornar o Android Runner capaz de rodar em dispositivos Android, adicione a seguinte linha ao arquivo AndroidManifest.xml:

<manifest xmlns:android="<http://schemas.android.com/apk/res/android>"
    package="com.example.veryGoodCore">
+  <uses-feature android:name="android.hardware.type.watch" />
   <application
...

Além disso, considere adicionar esses metadados na tag do application para marcar o aplicativo como autônomo (isso será importante ao implantar na loja):

<meta-data
   android:name="com.google.android.wearable.standalone"
   android:value="true" />

Outro arquivo que deve ser ajustado é o arquivo MainActivity.kt. Essa primeira alteração informa ao sistema operacional para renderizar o aplicativo sem um plano de fundo. Isso faz com que o aplicativo pareça redondo em dispositivos com telas arredondadas:

import android.os.Bundle
import androidx.annotation.NonNull
import android.view.MotionEvent

...
class MainActivity: FlutterActivity() {
...

    override fun onCreate(savedInstanceState: Bundle?) {
        intent.putExtra("background_mode", "transparent")
        super.onCreate(savedInstanceState)
    }
}

Mais tarde, usaremos o plug-in wearable_rotary. Isso significa que temos que adicionar o seguinte retorno de chamada à atividade principal:

import com.samsung.wearable_rotary.WearableRotaryPlugin
import android.view.MotionEvent

...
class MainActivity: FlutterActivity() {
...		
    override fun onGenericMotionEvent(event: MotionEvent?): Boolean {
        return when {
            WearableRotaryPlugin.onGenericMotionEvent(event) -> true
            else -> super.onGenericMotionEvent(event)
        }
    }
}

Por último, mas não menos importante, vamos atualizar as restrições de versão do Android SDK para corresponder aos plug-ins adicionados, que, no momento da redação deste artigo, estavam no nível mínimo de API 25. Independentemente disso, recomendo definir a versão mínima do SDK para 30 , que inclui apenas o Wear OS 3 e superior. Veja por que evitar o Wear OS 2 e inferior.

Para alterar as restrições do Android SDK, altere o arquivo build.gradle:

...
    defaultConfig {
        minSdkVersion 30
        targetSdkVersion 32
...

Depois disso, você pode executar o aplicativo em um emulador ou dispositivo.

Você notará uma coisa sobre isso: a interface do usuário parece compactada. Isso não é muito bom! Isso acontece porque a interface do usuário atual para o aplicativo contador foi feita para telas de smartphones, não para relógios. Então vamos adaptar isso.

Adaptando-se ao suporte do relógio

Podemos usar alguns recursos de API para fazer com que os aplicativos do Material se encaixem nessas telas minúsculas, mas tudo se resume a boas práticas e atenção ao que deve estar na tela de cada vez.

Na frente do Material, pode ser um bom começo definir a densidade visual para compactar:

...
@override
Widget build(BuildContext context) {
  return MaterialApp(
    theme: ThemeData(
            visualDensity: VisualDensity.compact,
...

Isso configura automaticamente widgets como botões e menus para ter menos pixels para preenchimento e espaçamento geral. Eu recomendo usar o Material 3, pois é mais compatível visualmente com a maior parte da interface do usuário do sistema Wear OS 3.

Além disso, aconselho usar fundos escuros. Como a maioria dos relógios tem molduras escuras nas telas OLED, isso ajudará a economizar bateria e combinará bem com dispositivos como o Pixel Watch.

...
@override
Widget build(BuildContext context) {
  return MaterialApp(
    theme: ThemeData(
            visualDensity: VisualDensity.compact,
            useMaterial3: true, // use material 3
            colorScheme: const ColorScheme.dark( // dark colorscheme
                    primary: Colors.white24,
                    onBackground: Colors.white10,
                    onSurface: Colors.white10,
                  ),
...

Em nosso exemplo, também precisamos fazer alguns ajustes no widget CounterPage, que podemos alterar a partir disso:

@override
Widget build(BuildContext context) {
  final l10n = context.l10n;
  return Scaffold(
    appBar: AppBar(title: Text(l10n.counterAppBarTitle)),
    body: const Center(child: CounterText()),
    floatingActionButton: Column(
      mainAxisAlignment: MainAxisAlignment.end,
      crossAxisAlignment: CrossAxisAlignment.end,
      children: [
        FloatingActionButton(
          onPressed: () => context.read<CounterCubit>().increment(),
          child: const Icon(Icons.add),
        ),
        const SizedBox(height: 8),
        FloatingActionButton(
          onPressed: () => context.read<CounterCubit>().decrement(),
          child: const Icon(Icons.remove),
        ),
      ],
    ),
  );
}

Para algo assim:

@override
Widget build(BuildContext context) {
  final l10n = context.l10n;
  return Scaffold(
    body: SizedBox.expand(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
            onPressed: () => context.read<CounterCubit>().increment(),
            child: const Icon(Icons.add),
          ),
          const SizedBox(height: 10),
          Text(l10n.counterAppBarTitle),
          const CounterText(),
          const SizedBox(height: 10),
          ElevatedButton(
            onPressed: () => context.read<CounterCubit>().decrement(),
            child: const Icon(Icons.remove),
          ),
        ],
      ),
    ),
  );
}

Trocamos os botões de ação flutuantes por botões elevados e centralizamos tudo em uma coluna.

Agora o aplicativo deve ficar assim:

 

Aproveitando o suporte do relógio

Parece bom até agora, mas alguns recursos interessantes de hardware podem enriquecer ainda mais a experiência do usuário. Apesar de todos os sensores que podem ser acessados por meio de alguns plugins, vamos nos concentrar hoje em dois plugins incríveis feitos pela comunidade.

Um deles é o plugin wear, mantido pela Comunidade Flutter. Isso nos dará acesso ao estado do modo ambiente para que possamos adaptar a aparência do aplicativo no modo de baixo consumo.

O outro é wearable_rotary, criado por Tizen, que inclui suporte para Wear OS. Isso permite que nosso código Flutter receba eventos das entradas rotativas, como o bisel giratório nos relógios Samsung e a coroa rotativa no relógio Pixel.

Adaptando-se ao modo ambiente

Quando a exibição sempre ativa é ativada nas configurações do relógio ou por meio da permissão do Android WAKE_LOCK, o sistema pode entrar no modo de “baixo consumo de energia” enquanto o aplicativo é executado. Isso é chamado de modo ambiente. Podemos usar o widget AmbientMode do wear para ouvir quando esse modo é ativado ou desativado e, em seguida, adaptar as cores do material de acordo.

O código a seguir torna o aplicativo monocromático no modo ambiente:

import 'package:wear/wear.dart';

class App extends StatelessWidget {
...
    @override
    Widget build(BuildContext context) {
      // Add ambient mode support
      return AmbientMode(
        child: const CounterPage(),
        builder: (context, mode, child) {
          return MaterialApp(
                    home: child,
                    theme: ThemeData(
                        useMaterial3: true,
                        visualDensity: VisualDensity.compact,
                        colorScheme: mode == WearMode.active
                        ? const ColorScheme.dark( // 
                            primary: Color(0xFF00B5FF),
                          )
                        : const ColorScheme.dark(
                            primary: Colors.white24,
                            onBackground: Colors.white10,
                            onSurface: Colors.white10,
                          ),
...

Exemplo do aplicativo entrando no modo ambiente:

Além disso, este plug-in nos permite obter metainformações sobre o modo ambiente por meio da classe AmbientDetails. Também é possível detectar a forma da tela.

Ouvindo a entrada rotativa

Um bom recurso para nosso pequeno aplicativo de contador seria permitir que o usuário aumentasse e diminuísse a contagem por meio da moldura/coroa giratória. Para isso, podemos ouvir os rotaryEvents fornecidos pelo plug-in e definir o estado do contador a partir deles:

...
class _CounterViewState extends State<CounterView> {
  late final StreamSubscription<RotaryEvent> rotarySubscription;

  @override
  void initState() {
    super.initState();
    rotarySubscription = widget.rotaryEvents.listen(handleRotaryEvent);
  }

  @override
  void dispose() {
    rotarySubscription.cancel();
    super.dispose();
  }

  void handleRotaryEvent(RotaryEvent event) {
    final cubit = context.read<CounterCubit>();
    if (event.direction == RotaryDirection.clockwise) {
      cubit.increment();
    } else {
      cubit.decrement();
    }
  }
...

Resultado:

 

Implantando na loja de aplicativos

Até agora, tudo bem, tão fácil. Temos um aplicativo Flutter que parece feito para smartwatches. Mas como liberamos isso para que o mundo possa baixá-lo diretamente em seus relógios?

Como esperado, os aplicativos Wear OS são distribuídos pela Google Play Store (dispositivos Samsung também podem usar a Galaxy Store).

Existem algumas partes específicas que precisam de atenção especial para evitar uma rejeição de versão. Esses são:

  • Os aplicativos autônomos devem mencionar o Wear OS em suas páginas, na descrição e no título.
  • Deve haver capturas de tela para vários tamanhos, resoluções e formas de tela. É encorajado a produzi-los em emuladores.
  • As capturas de tela do Wear OS são muito mais restritas do que os aplicativos para smartphones. As capturas de tela devem conter a interface do aplicativo e apenas a interface do aplicativo. Não inclua fotos de dispositivos.

A primeira versão publicada do aplicativo passará por duas fases de aprovação. O primeiro deve ser como qualquer aplicativo Android. Consulte os documentos oficiais sobre a implantação de um aplicativo Flutter na Play Store.

Após a aprovação dessa versão, o aplicativo deve estar visível na loja, mas as pessoas ainda não poderão instalá-lo em dispositivos Wear OS. Os aplicativos Wear OS requerem um formato especial para que possam ser instalados em dispositivos vestíveis. Por isso:

Isso criará um formulário passo a passo para que você possa fornecer informações adicionais específicas do Wear OS que aparecem na página da sua loja.

Depois de terminar esse formulário, outro processo de revisão será iniciado para ver se o aplicativo fornecido está apto para rodar nos relógios das pessoas. Certifique-se de que os requisitos acima mencionados sejam atendidos. Após a segunda etapa de aprovação, o aplicativo deve aparecer na loja.

Parabéns, agora você pode se gabar de ser um desenvolvedor de smartwatch 🥳

 

Mas espere! Hora das notícias não tão boas porque precisamos falar sobre o…

 

Suporte para Apple Watch

Ao contrário do Wear OS, o watchOS (sistema operacional de relógios da Apple; nomes confusos, eu sei) não é apenas um sistema operacional de smartphone com um logotipo diferente e algumas APIs personalizadas (ok, é quase isso). WatchKit muda o jogo mais do que sua contraparte Android.

Nesta edição do Flutter, Jenn Magder lista um conjunto de procedimentos que devem ser feitos no framework e motor de suporte de som para este tipo de dispositivo. Até onde sabemos, executar o Flutter e o Apple Watches não é tão simples quanto no Wear OS.

Decidimos não cobrir o Apple Watch neste tutorial, pois este ainda é um território desconhecido. Mas se há uma coisa sobre o Flutter que o tempo provou repetidamente, é que: se ele tiver uma tela, ele executará o Flutter, eventualmente.