Flutter: do Mobile para o Desktop

Criando aplicativos para smartphones e computadores de maneira rápida e fácil com o framework da Google.

Acesse aqui a versão em inglês / Check here the english version

Introdução

Se você desenvolve aplicativos para smartphones, é bem provável que você já tenha ouvido falar sobre um novo framework para desenvolvimento de aplicativos, o Flutter, da Google. É um framework que permite desenvolver aplicativos com uma única base de código na linguagem Dart, também da Google, e publicá-los tanto para a plataforma Android quanto para iOS.

O framework ainda não chegou na versão 1.0, mas já foi anunciado como pronto para utilização em ambiente de produção pela Google desde sua versão beta 3, lançada em maio deste ano. Além disso, há a possibilidade de criar aplicações desenvolvidas em Flutter para ambientes desktop (Windows, macOS e Linux), que é o assunto que este artigo irá abordar.

Atualização em 06/11/2018: inclusão de arquivos pré-compilados com guia, atualização do template e melhoria no guia para evitar problemas ocorridos em algumas instalações.

Atualização em 15/11/2018: atualização do template e inclusão de guia para distribuição do aplicativo em ambientes sem o Flutter instalado.

Atualização em 21/11/2018: melhoria nas instruções para obtenção do hash da engine do Flutter.

O suporte às plataformas desktop se dá atualmente por meio de dois projetos, ambos ainda em desenvolvimento. Um deles inclusive é desenvolvido pela Google, mas possui uma indicação de que a empresa não oferece suporte ao mesmo. Os projetos se encontram nos seguintes repositórios do Github:

Ambos os projetos são classificados como Custom Flutter Engine Embedders, ou seja, são implementações da API do Flutter para que projetos desenvolvidos nesse framework possam ser executados em sistemas operacionais que não sejam os suportados oficialmente pelo projeto Flutter (Android, Fuchsia e iOS).

Eles utilizam OpenGL através da biblioteca GLFW (exceto a versão para macOS do projeto do Google), a qual fornece uma API para criação de janelas e tratamento de entrada por teclado e mouse, dentre outras funcionalidades, em plataformas desktop. Portanto, a plataforma onde será executado o aplicativo que está sendo desenvolvido deve possuir drivers instalados para o OpenGL.


Instalação do Flutter

Para instalar o Flutter, siga os passos listados na página de instalação oficial de acordo com o seu sistema operacional. Clique aqui para acessar a página de instalação. Ele será necessário para execução dos projetos mais adiante neste artigo. Não esqueça de incluir o Flutter na sua variável de ambiente PATH.


Projeto 1: Desktop Embedding for Flutter (Google)

Este projeto possui atualmente algumas limitações, as quais estão indicadas na seção Caveats da documentação do próprio repositório.

Diferente do segundo projeto, que será apresentado em seguida neste artigo, este projeto não possui arquivos binários que possibilitem a rápida execução do projeto de exemplo ou a configuração do seu próprio projeto Flutter para executá-lo em plataformas desktop. É necessário compilar o código fonte desse projeto no seu sistema operacional e depois incluir as bibliotecas geradas em um arquivo executável que irá fazer parte do aplicativo. Futuramente esse processo será simplificado, conforme dito na documentação atual no próprio repositório.

Para compilar o código fonte do projeto e criar seus aplicativos desktop com Flutter através desse projeto, siga as instruções presentes aqui e aqui.


Projeto 2: Go Flutter desktop embedder (Drakirus)

O segundo projeto é desenvolvido por meio da linguagem de programação Go (Golang) da Google.

No repositório do projeto existem versões para download (releases) em que é possível testar os exemplos de aplicações desktop por meio de arquivos executáveis já compilados. Além disso, a criação de novos projetos Flutter para desktop é bem simples.

Nos itens seguintes é apresentado como executar o projeto de exemplo existente no repositório do projeto e também como executar o seu próprio projeto desenvolvido em Flutter agora como uma aplicação desktop.

Execução do projeto de exemplo:

  1. Acesse as versões para download (releases) do projeto aqui.
  2. Baixe o arquivo de exemplo de acordo com a sua plataforma na seção com o nome Prebuilt Binaries example for Linux, Windows and MacOS, referente à versão v0.2.1-alpha.
  3. Descompacte o arquivo baixado no local de sua preferência.
  4. Execute o arquivo stocks (macOS e Linux) ou socks.exe (Windows) presente no diretório inicial do conjunto de arquivos descompactados. Ele será executado como qualquer outro aplicativo do sistema operacional que você utiliza (exemplo na imagem abaixo).
Aplicativo de exemplo desenvolvido em Flutter sendo executado no ambiente desktop do Windows 10.
Aplicativo de exemplo desenvolvido em Flutter sendo executado no ambiente desktop do macOS Mojave.
Aplicativo de exemplo desenvolvido em Flutter sendo executado no ambiente desktop do Ubuntu Budgie 18.04.

Observação: nos guias a seguir, a versão para macOS do aplicativo desktop está iniciando com uma tela preta, mas o aplicativo é carregado normalmente após maximizar a tela. Assim que descobrir a solução para este problema, atualizo este artigo.

Execução do seu próprio projeto (utilizando arquivos pré-compilados):

  1. Baixe o arquivo pré-compilado referente ao seu sistema operacional aqui.
  2. Descompacte em um diretório de sua preferência.
  3. Edite o arquivo config.json do diretório do template alterando o valor dos parâmetros conforme as informações do seu ambiente e aplicativo. FlutterPath: diretório da sua instalação do Flutter. FlutterProjectPath: diretório do seu projeto desenvolvido em Flutter. IconPath: caminho para o arquivo de ícone do aplicativo desktop (pode ser mantido o valor default). ScreenHeight: altura inicial da tela do aplicativo desktop. ScreenWidth: largura inicial da tela do aplicativo desktop. Use barras invertidas duplas (\\) ao invés de simples (\) nos caminhos dos diretórios caso esteja utilizando Windows.
  4. Execute o arquivo flutter-desktop-template, no macOS ou Linux, ou o arquivo flutter-desktop-template.exe no Windows e o aplicativo será iniciado. Ele será executado como qualquer outro aplicativo do sistema operacional que você utiliza

Execução do seu próprio projeto (compilando o projeto desktop Go):

  1. Baixe e instale a linguagem de programação Go através da sua página de downloads aqui (as instruções para instalação e configuração das ferramentas na variável de ambiente PATH são fornecidas na página do download).
  2. Caso você não possua um gcc instalado em sua máquina, será necessário instalar para compilação de alguns arquivos de código do projeto desktop em Go. Para Windows, sugiro o tdm64-gcc. Para macOS é utilizado o fornecido pelo Xcode Command Line Tools. Para Linux, geralmente já existe um gcc instalado.
  3. Baixe e instale o Git aqui, caso você não possua ele instalado na sua máquina.
  4. Crie seu projeto Flutter normalmente através do comando flutter create ou de uma IDE.
  5. Inclua o seguinte import no arquivo main.dart do seu projeto Flutter: import 'package:flutter/foundation.dart' show debugDefaultTargetPlatformOverride;
  6. Inclua o seguinte código no início do método main (antes da chamado ao método runApp) do arquivo main.dart do seu projeto Flutter (esse código é necessário porque plataformas desktop não são oficialmente suportadas pelo projeto Flutter): debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
  7. Em um terminal, execute o comando flutter build bundle no diretório do seu projeto Flutter (será criado um diretório com os arquivos necessários para a execução do aplicativo em Flutter pelo template que será baixado e configurado nos passos seguintes).
  8. Também em um terminal, execute o comando go get -u github.com/go-gl/glfw/v3.2/glfw para baixar a biblioteca GLFW para a linguagem Go (caso ocorra algum problema, verifique o item Solução de problemas no final deste artigo). É necessário verificar se você possui todas as dependências citadas neste link antes de instalar.
  9. Baixe o projeto desktop em Go aqui (versão que atualmente está funcionando e oferendo suporte a Windows, macOS e Linux).
  10. Descompacte o conteúdo do arquivo baixado em um diretório qualquer no seu sistema operacional.
  11. Renomeie o diretório extraído de go-flutter-desktop-embedder-0.2.1-alpha para go-flutter-desktop-embedder.
  12. Copie o diretório extraído (agora renomeado) para dentro do diretório src\github.com\Drakirus (ou src/github.com/Drakirus no Windows), que deve ser criado no seu GOPATH (o GOPATH é uma variável de ambiente que indica onde estão instaladas as bibliotecas baixadas para a linguagem Go; no Windows e no macOS geralmente é o diretório go dentro da pasta pessoal do usuário).
  13. Baixe ou clone o repositório do template necessário para esse passo a passo aqui (ele será utilizado para facilitar a execução do aplicativo sem precisar programar na linguagem Go). Descompacte o arquivo baixado em um diretório de sua preferência caso tenha optado por baixar ao invés de clonar o repositório.
  14. Baixe a biblioteca do Flutter (necessária para o funcionamento do template) utilizando o link https://storage.googleapis.com/flutter_infra/flutter/74625aed323d04f2add0410e84038d250f51b616/linux-x64/linux-x64-embedder no Linux, https://storage.googleapis.com/flutter_infra/flutter/74625aed323d04f2add0410e84038d250f51b616/darwin-x64/FlutterEmbedder.framework.zip no macOS ou https://storage.googleapis.com/flutter_infra/flutter/74625aed323d04f2add0410e84038d250f51b616/windows-x64/windows-x64-embedder.zip no Windows (substituindo o texto em negrito, que é o hash da versão beta 0.9.4, pelo hash correspondente à versão do Flutter que você está utilizando no seu projeto, que você pode obter consultando o arquivo bin\internal\engine.version presente dentro do seu diretório de instalação do Flutter).
  15. Descompacte o arquivo baixado e copie o arquivo libflutter_engine.so no Linux, FlutterEmbedder.framework (o conteúdo do arquivo FlutterEmbedder.framework.zip como um diretório com o nome FlutterEmbedder.framework) no macOS ou flutter_engine.dll no Windows para dentro do diretório do template, onde se encontra o arquivo main.go, e também para dentro do diretório go-flutter-desktop-embedder, que foi copiado para o seu GOPATH anteriormente.
  16. Em um terminal, vá para o diretório go-flutter-desktop-embedder e execute o comando export CGO_LDFLAGS="-L${PWD}" no Linux, o comando set CGO_LDFLAGS=-L%cd% no Windows ou o comando export CGO_LDFLAGS="-F${PWD} -Wl,-rpath,@executable_path" no macOS. Mantenha o terminal aberto.
  17. No mesmo terminal, execute o comando go install dentro do diretório go-flutter-desktop-embedder. Ainda mantenha o terminal aberto.
  18. Edite o arquivo config.json do diretório do template alterando o valor dos parâmetros conforme as informações do seu ambiente e aplicativo. FlutterPath: diretório da sua instalação do Flutter. FlutterProjectPath: diretório do seu projeto desenvolvido em Flutter. IconPath: caminho para o arquivo de ícone do aplicativo desktop (pode ser mantido o valor default). ScreenHeight: altura inicial da tela do aplicativo desktop. ScreenWidth: largura inicial da tela do aplicativo desktop. Use barras invertidas duplas (\\) ao invés de simples (\) nos caminhos dos diretórios caso esteja utilizando Windows.
  19. Ainda no mesmo terminal, repita o passo 16 e execute o comandogo build, mas agora no diretório em que você descompactou o template, onde se encontra o arquivo main.go. No Windows, utilize o comando go build -ldflags -H=windowsgui ao invés de go build para que não seja exibido um terminal juntamente com o aplicativo ao executá-lo. No macOS, pode ser necessário empacotar o diretório conforme os padrões da plataforma para que um terminal não seja aberto junto com a aplicação.
  20. Será criado o arquivo executável (ele terá o mesmo nome do diretório do projeto, ou seja, flutter-desktop-template no Linux e no macOS e flutter-desktop-template.exe no Windows, caso o diretório do template seja flutter-desktop-template).
  21. Execute o arquivo criado e o aplicativo será iniciado. Ele será executado como qualquer outro aplicativo do sistema operacional que você utiliza (exemplo na imagem abaixo).
Aplicativo desenvolvido em Flutter sendo executado no ambiente desktop do Windows 10.
Aplicativo desenvolvido em Flutter sendo executado no ambiente desktop do macOS Mojave.
Aplicativo desenvolvido em Flutter sendo executado no ambiente desktop do Ubuntu Budgie 18.04.
  • Sempre que for feita alguma alteração no projeto Flutter, repita o passo 7 (execução do comando flutter build bundle no diretório do projeto) novamente.
  • A versão do Flutter utilizada no projeto deve ser a mesma que foi baixada no passo 14.
  • Sempre que for feita alguma alteração no arquivo config.json do template, repita os passos 16 e 19.

Empacotando sua aplicação para distribuição

Para distribuir sua aplicação desktop desenvolvida em Flutter, de maneira que ela possa ser executada em computadores que não possuam o Flutter instalado, siga os passos abaixo após ter executado um dos guias acima para execução do seu próprio projeto.

  1. Confira se você está utilizando a versão mais atual do template, que é a versão 1.1.0.
  2. Crie um diretório para armazenar todos os arquivos necessários para a execução da sua aplicação. Nos passos seguintes, esse diretório será mencionado como diretório da aplicação.
  3. Inclua no diretório da aplicação o executável flutter-desktop-template (no Linux e no macOS) ou flutter-desktop-template.exe (no Windows). Renomeie o executável conforme o nome da sua aplicação.
  4. Inclua também a biblioteca do Flutter no diretório da aplicação. Essa biblioteca é o arquivo libflutter_engine.so no Linux, o diretório FlutterEmbedder.framework no macOS ou o arquivo flutter_engine.dll no Windows.
  5. Copie o arquivo config.json para o diretório da aplicação. Edite esse arquivo, alterando o valor de FlutterPath e FlutterProjectPath para em branco (deixe os valores vazios).
  6. Inclua o diretório assets com a imagem de ícone no diretório da aplicação. Caso você tenha escolhido uma outra imagem, copie essa imagem para o diretório da aplicação e corrija o caminho da mesma no valor de IconPath, no arquivo config.json.
  7. Copie para o diretório da aplicação o diretório flutter_assets, presente dentro do diretório build do seu projeto Flutter.
  8. Por último, copie o arquivo icudtl.dat presente no caminho bin\cache\artifacts\engine\windows-x64 (no Windows) bin/cache/artifacts/engine/linux-x64 (no Linux) ou bin/cache/artifacts/engine/darwin-x64 (no macOS) da sua instalação do Flutter para o diretório da aplicação.
  9. No macOS, pode ser necessário empacotar o diretório conforme os padrões da plataforma para que um terminal não seja aberto junto com a aplicação.

Agora você pode distribuir a sua aplicação e instalá-la em ambientes sem a necessidade de instalar o Flutter junto com ela.


Soluções de problemas

Caso ocorra alguma problema ao executar o passo 8 da execução do seu próprio projeto (biblioteca Go GLFW) em um ambiente Linux, resultando em uma mensagem parecida com a apresentada abaixo, você pode desconsiderá-la. São somente avisos que não interferem na execução do aplicativo desktop.

# github.com/go-gl/glfw/v3.2/glfw
In file included from ../../go-gl/glfw/v3.2/glfw/c_glfw_linbsd.go:24:0:
../../go-gl/glfw/v3.2/glfw/glfw/src/linux_joystick.c: In function ‘_glfwInitJoysticksLinux’:
../../go-gl/glfw/v3.2/glfw/glfw/src/linux_joystick.c:224:42: warning: ‘%s’ directive output may be truncated writing up to 255 bytes into a region of size 9 [-Wformat-truncation=]
 snprintf(path, sizeof(path), “%s/%s”, dirname, entry->d_name);
 ^~~~~~~
In file included from /usr/include/stdio.h:862:0,
 from /usr/include/X11/Xcursor/Xcursor.h:26,
 from ../../go-gl/glfw/v3.2/glfw/glfw/src/x11_platform.h:39,
 from ../../go-gl/glfw/v3.2/glfw/glfw/src/internal.h:169,
 from ../../go-gl/glfw/v3.2/glfw/glfw/src/x11_init.c:28,
 from ../../go-gl/glfw/v3.2/glfw/c_glfw_linbsd.go:19:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:64:10: note: ‘__builtin___snprintf_chk’ output between 12 and 267 bytes into a destination of size 20
 return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL — 1,
 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 __bos (__s), __fmt, __va_arg_pack ());
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Conclusão

Os dois projetos apresentados neste artigo permitem que aplicações desenvolvidas com o framework Flutter possam ser executadas em ambientes desktop. O primeiro é desenvolvido pela própria Google, mas não oferece um suporte por parte da mesma. O segundo permite tanto uma maior facilidade para execução de aplicativos desenvolvidos em Flutter como aplicações desktop como uma maior familiaridade para desenvolvedores que trabalham com a linguagem de programação Go (Golang), também da Google.

Para casos em que uma aplicação deve ser desenvolvida para ambiente desktop e mobile, de maneira que o código possa ser reaproveitado, os dois projetos apresentados neste artigo são uma ótima solução.

Para dúvidas, deixe seu comentário. Responderei o mais breve possível. Obrigado pela leitura. Um abraço!