Criando Federated Plugins

Maria Clara Almeida Souza
suamusicatech
Published in
4 min readAug 8, 2022

Atualmente o formato padrão indicado para criar um novo plugin é o Federated Plugin, (em português Plugins federados), é uma maneira de dividir o suporte para diferentes plataformas em pacotes separados.

Um Plugin Federado requer a seguinte estrutura:

1- app-facing package(interface da plataforma e especificidades da mesma):

O pacote do qual os usuários do plugin dependem para usar o plugin.

2- platform package(s) — especificações da plataforma

Um ou mais pacotes que contêm o código de implementação específico da plataforma.

3- platform interface package

Este pacote declara uma interface que qualquer pacote de plataforma deve implementar para dar suporte ao pacote, e não é visível fora da implementação do plugin. Ter um pacote que define a interface garante que os platform packages implementem a mesma funcionalidade.

O diagrama abaixo, contribui para a visualização da estrutura de um plugin Federado.

Estrutura Federated Plugin. Fonte: Flutter lessons for federated plugin development.

Mas qual a importância acerca do Federated Plugin?! Quando queremos estar presente em ’n’ dispositivos, sejam eles, mobile, desktop, telas de TV e todos os lugares em que nossos usuários possam vir a instalar nossa aplicação, desejamos que essa aplicação mantenha seu funcionamento independente da plataforma, com a necessidade de evitar distorções, fica evidente a importância do Federated Plugin, além disso, essa abordagem permite que um especialista estenda um plug-in existente para funcionar na plataforma que ele conhece melhor.

Exemplo

Para o nosso exemplo, um simples plugin que para a leitura do nível da bateria que irá funcionar tanto para o sistema operacional Android como para o iOS, para isso, no local em que o plugin será desenvolvido é necessário:

1- Crie e implemente o pacote:

flutter create — template=package battery

2- Platform Interface

flutter create -t package battery_platform_interface

3- Android:

flutter create --template=plugin --platforms=android -a kotlin battery_android

4- iOS

flutter create --template=plugin --platforms=ios -i swift battery_ios

Obtendo a seguinte estrutura:

📦battery
┣ 📂battery
┣ 📂battery_android
┣ 📂battery_ios
┣ 📂battery_platform_interface

De forma mais detalhada como ficará a interface para as plataformas:

📦battery_platform_interface
┣ 📂lib
┃ ┣ 📂src
┃ ┃ ┣ 📂chanel_methods
┃ ┃ ┃ ┗ 📜battery_method_channel.dart
┃ ┃ ┗ 📜battery_platform_interface.dart
┃ ┗ 📜battery_platform_interface.dart

battery_platform_interface:

Neste packge é adicionado o plugin_platform_interface seu papel é fornecer uma classe base para interfaces de plataforma de plugins de flutter federados.

Então a classe BatteryPlatform herda os recursos da PlatformInterface, como podemos ver abaixo.

Esta classe abstrata (BatteryPlatform) servirá de base para as implementações de cada plataforma, sendo suas funções as ações que o plugin deverá executar em cada uma.

battery_method_channel:

MethodChannelBattery herda BatteryPlatform e implementa suas funções através do MethodChanel invocado. Resumindo, é onde é colocado o nome do channel que será utilizado para a troca de mensagens com o nativo e o resultado esperado, como podemos ver abaixo.

Toda a plataforma criada precisa adicionar como dependência a interface criada acima, para que seus comportamentos sejam similares idependente da plataforma, como podemos ver abaixo para android (demais plataformas são feitas de forma análoga):

battery_android:

Aqui a plataforma é implementada, neste caso, o Android. O MethodChanel precisa ser igual para todas as plataformas.

Esta classe irá se registrar através da função registerWith e implentar os métodos da interface.

Agora é preciso implementar esse método dentro da plataforma, nesse caso como a plataforma detalhada é Android, será detalhado o arquivo BatteryAndroidPlugin.

Pode-se notar novamente o chanel com o mesmo valor do que foi mostrado anteriormente.

Na função onMethodCall é onde iremos implementar cada método necessário, no nosso caso o método chamado getBatteryLevel, que chamará a funcão também chamada getBatteryLevel que nos retorna o valor desejado, que é retornado para o código dart através do result.

Esse padrão é seguido para todas as plataformas (iOS, windows…etc).

battery:

o battery representa o plugin como um todo. Podemos ver que nesse caso temos as plataformas Android e iOS implementadas. Caso for necessário implementar para outras plataformas, como o windows, seria necessário criar o plugin battery_windows e adicionar no pubspec abaixo.

Ou seja, esse é o arquivo que será lido por uma aplicação como será mostrado mais abaixo.

Essa é, nesse caso, a única classe que fica visível para o uso das aplicações, então basicamente, o app vai através de suas funções para retornar o recurso desejado e disponível.

example:

Em nosso projeto exemplo do plugin, pode-se observar que apenas foi adicionado a dependência battery, que é o que o código Flutter precisa ter acesso.

main:

Olhando para a função initBattery é possível ver como a aplicação utiliza o recurso do plugin de forma simples.

Resultado:

Conclusão

Esta estrutura permite que a partir da necessidade sejam adicionadas suporte a novas plataformas ao plugin, de uma forma menos acoplada, possibilitando um melhor trabalho compartilhado, e claro, obedecendo as regras da interface.

Segue o github do código mostrado acima: https://github.com/Claraalmeida09/battery

Encontrou algum erro no artigo ou tem alguma dúvida? Comenta aí!

@suamusicatech

--

--