Push notifications com Firebase Cloud Messaging
Hey, psiu! Opa, tudo bem? Já parou para pensar que às vezes precisamos enviar um psiu para nossos usuários de aplicativos para chamar a atenção deles, igual fiz com você agora? Os usuários perdem o interesse muito rápido em um aplicativo se não enviarmos mensagens que os lembrem de abri-lo por alguma razão. Pensando nisso, a Google criou o Firebase Cloud Messaging, que é uma solução para realizar o envio de mensagens do tipo push para dispositivos móveis Android e iOS e também para aplicações web.
Notificação push
As notificações push são as famosas “cenourinhas” para atrair o “coelho”. No caso, o coelho são os usuários e a cenoura são notificações de promoção, uma nova curtida em uma foto, um novo comentário em uma rede social ou similares. É através das notificações que fazemos os usuários abrirem o aplicativo. Não é regra, pois um usuário pode simplesmente ignorar a notificação enviada, mas normalmente as pessoas abrem. Em uma tradução livre, push notification é uma “notificação empurrada”, ou seja, é uma notificação que o usuário não necessariamente solicitou, mas que concordou em receber ao instalar o aplicativo. Vamos ver um exemplo menos abstrato? Imagine que a Casa do Código tenha um aplicativo para seus leitores e leitoras receberem notificações todas as vezes que um livro novo for lançado. Para isso, o fluxo que seria criado para a notificação é o seguinte:
Uma das grandes vantagens de implementar esse tipo de notificação em seu aplicativo é poder monitorar a porcentagem de usuários que recebem, abrem, ignoram etc. as suas notificações. Desta maneira é possível mapear quais campanhas publicitárias fazem mais sentido de acordo com um determinado público. Essa abordagem de fazer com que o aplicativo seja receptor, isto é, fique esperando requisições, chamamos de Push Notification. Atualmente, existem algumas plataformas que oferecem esses serviços mensageiros, como o FCM (Firebase Cloud Messaging).
Configurando o Firebase
Primeiro, antes de mais nada, você precisa ter uma conta Google (Gmail), que será utilizada para acessar o console de desenvolvedor do Firebase. Para isso, acesse: https://firebase.google.com/ e clique em “Ir para o console”.
Feito isso, precisamos criar um projeto no Firebase para que possamos comunicar a nossa aplicação Flutter com ele posteriormente. Para isso, já na tela do console Firebase, crie um projeto.
Na próxima tela que se abrirá, digite um nome para o projeto. No nosso caso, optamos por utilizar o nome alura-notifications
, mas você pode utilizar qualquer nome que faça sentido para o seu projeto. Após apertar em continuar, aparecerá uma nova tela com detalhes sobre o Google Analytics. Deixe esta opção habilitada! É ela que nos fornecerá os dados do Cloud Messaging futuramente.
Em seguida, ajuste a sua conta no Google Analytics utilizando as configurações padrão oferecidas. Agora, é só apertar no botão de “Criar projeto” e observar a mágica acontecer! Vai aparecer uma tela com a mensagem “Criando o projeto” (normalmente esta etapa leva alguns segundos para terminar de executar).
Após a criação do projeto ser realizada, aperte o botão que aparecerá escrito “Continuar” e você cairá na tela principal do seu projeto Firebase. Após estar na tela principal, selecione o sistema operacional em que a sua aplicação está executando. No nosso caso, ensinaremos a integração do Firebase com o sistema operacional Android. Então, selecione esta opção para obter o guia de instalação e configuração do Firebase para esta plataforma.
A tela que abrirá tem três opções, mas agora precisamos preencher apenas uma, que é o nome do pacote do Android. Caso já tenha criado o seu projeto Flutter, para acessar o nome do pacote, abra a pasta android
e navegue até o arquivo AndroidManifest.xml
, que está localizado em: seu_projeto > android > app > src > profile > AndroidManifest.xml
. Nesse arquivo, você consegue obter o package. Caso não tenha criado, pode especificar o nome e a empresa que deseja e seu projeto terá como resultado o pacote que quiser. No nosso caso, ficou com.example.alura_notification
.
Após preencher o campo com o package do projeto, clique em próximo. Agora, você está em uma das telas mais importantes de toda a configuração do Firebase. Baixe para o seu computador o arquivo google-services.json
, que será a nossa credencial de acesso ao Firebase no lado do aplicativo. Coloque este arquivo dentro do seu projeto Flutter no seguinte diretório: seu_projeto > android > app > google-services.json
. Se este arquivo não estiver localizado na pasta app, que fica dentro da pasta android
do projeto Flutter, pode esquecer! Vai dar treta! Ele é o nosso passaporte para conversar com o Firebase.
O plug-in dos serviços do Google para Gradle carrega o arquivo google-services.json
, cujo download você acabou de fazer. Modifique seus arquivos build.gradle
para usar o plug-in. O arquivo build.gradle
fica na raiz da pasta android
. Verifique se o seu arquivo build.gradle
está similar ao código abaixo:
buildscript {
repositories {
// Verifique se o seu arquivo tem esta linha, caso não tenha, adicione-a:
google()
}
dependencies {
...
// Adicione esta linha para a leitura do arquivo .json do Firebase
classpath 'com.google.gms:google-services:4.3.5'
}
}
allprojects {
...
repositories {
// Verifique se o seu arquivo tem esta linha, caso não tenha, adicione-a:
google()
...
}
}
Agora, vá no arquivo build.gradle
, que está dentro da pasta app, e adicione as dependências do Firebase e do Google Services seguindo o exemplo do código abaixo:
apply plugin: 'com.android.application'
// Adicione esta linha
apply plugin: 'com.google.gms.google-services'
dependencies {
// Dependências necessárias, adicione-as!
implementation platform('com.google.firebase:firebase-bom:26.2.0')
implementation 'com.google.firebase:firebase-messaging'
implementation 'com.google.firebase:firebase-analytics'
}
Feito isso, volte ao console do Firebase, aperte o botão de “Próximo” e pronto! Temos o Firebase configurado. Novamente, na tela principal do projeto alura-notification
, role a página até chegar na opção “Cloud Messaging”. Guarde ela! Já já voltaremos para disparar a nossa primeira notificação a partir de lá!
Integração do Flutter com o Firebase Cloud Messaging
Configurado o Firebase com a parte nativa Android, agora é com o Flutter! Utilizaremos a extensão firebase_messaging criada especialmente para conectar o Flutter com o FCM. Adicione a declaração desta extensão na área das dependências do seu projeto no arquivo pubspec.yaml
.
A versão atual da extensão firebase_messaging é a 7.0.3.
O seu arquivo pubspec.yaml
deverá ficar similar ao nosso:
name: alura_notification
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.1
dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutter
flutter:
uses-material-design: true
Adicionada a dependência, agora precisamos importá-la no arquivo main.dart
! Para isso, insira a seguinte linha no topo do arquivo:
import 'package:firebase_messaging/firebase_messaging.dart';
Agora, adicione o código que captura os eventos enviados pelo Firebase Cloud Messaging dentro do widget principal. O código é:
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
},
);
_firebaseMessaging.getToken().then((String token) {
assert(token != null);
print('Push token gerado: $token');
});
Insira este código dentro de um método sobrescrito chamado initState()
. O Firebase gera um token único para o seu dispositivo que é recebido através do método getToken()
. Este token pode ser enviado para alguma API ou banco de dados e com ele é possível enviar uma notificação de push para o seu dispositivo em específico. Caso não queira enviar direcionadamente, sem problemas! Não precisa salvar este código, pois é possível enviar uma mensagem direcionada a todos os usuários de uma única vez através do painel do FCM. Feitas essas configurações no código Flutter, o seu arquivo main.dart
deve ficar similar a:
import 'package:flutter/material.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
@override
void initState() {
super.initState();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
},
);
_firebaseMessaging.getToken().then((String token) {
assert(token != null);
print('Push token gerado: $token');
});
}
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Na real, o que temos com este código é um aplicativo padrão de contador criado em Flutter, mas que por baixo dos panos suporta o recebimento de Push Notifications. A tela do aplicativo ficará da seguinte maneira:
Disparando uma notificação
Para realizar o disparo das notificações existem dois caminhos. O primeiro é integrando uma aplicação servidora que você disponha junto ao Firebase Cloud Messaging através da API que ele contém ou através do próprio painel de desenvolvedores. Neste caso, optamos pelo painel de desenvolvedores por ser uma proposta bastante clara e objetiva para um artigo. :)
Bora lá então? No painel do projeto alura-notifications
que criamos, acesse o Firebase Cloud Messaging. Caso ainda não tenha criado nenhuma notificação anteriormente, será exibida para você a tela de “Enviar a sua primeira mensagem”, como na imagem abaixo:
Após entrar na tela de envio de mensagens, preencha o título e o texto que aparecerá na notificação. Ao fazer isso, você pode apertar o botão de “Enviar uma notificação de teste”, como a imagem abaixo mostra:
Repare que ao apertar no botão “Enviar mensagem de teste”, será solicitado um token de registro do FCM. Este token é o que a nossa aplicação Flutter recebe quando se conecta com o FCM. No nosso caso, o código que está responsável por esta captura é:
_firebaseMessaging.getToken().then((String token) {
assert(token != null);
print('Push token gerado: $token');
});
Este código exibe para nós no terminal de execução do IntelliJ qual foi o token gerado para o nosso dispositivo. Todas as vezes que abrimos o aplicativo, ele exibe este token no terminal.
Atenção: certifique-se de que o seu emulador ou dispositivo físico estão conectados à internet para a obtenção do token via Firebase Cloud Messaging.
Copie apenas o Push Token e cole na janela do FCM, aperte o botão de adicionar, que é representado por um sinal de +, e deverá ficar da seguinte maneira:
Agora, é só enviar o Push de teste apertando o botão “Testar”.
Atenção: o envio da notificação pode ser instantâneo ou não. Houve testes no meu código que demoraram em torno de 5 minutos para a notificação chegar. Outros instrutores aqui da Alura também reportaram atrasos significativos na chegada das notificações. Então, sem treta! Às vezes demora mesmo e não é culpa sua.
Oba! Recebemos o nosso push notification com sucesso! Mas lembra que temos mais códigos que tratam push no aplicativo? Eles recebem os dados provenientes da notificação. Conseguimos capturar os dados e exibir no terminal ou ainda exibir na própria tela!
O onMessage
é disparado quando o push chega com o aplicativo aberto. O onResume
é executado quando o aplicativo está minimizado, recebe uma notificação e é aberto. E o onLaunch
é executado quando o aplicativo é aberto através da notificação recebida.
Para recapitular, vamos rever o código?
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
},
);
Repare que na mensagem capturada pelo aplicativo e exibida pelo console do Intellij, existe um acesso ao objeto chamado data
. E que está vazio. Podemos passar instruções ao aplicativo através do data partindo do console do Firebase até o dispositivo móvel.
onMessage: {notification: {title: Hello World, body: Olá, alura aqui!}, **data: {}**}
Também é possível, por exemplo, enviar um ícone para personalizar a exibição da notificação.
Conclusão
Ufa, que maneiro que você chegou até aqui! Aprendemos um montão de coisas! Neste artigo vimos como configurar o Firebase Console, como configurar a parte do Firebase Cloud Messaging (FCM), aprendemos a configurar as dependências dentro do projeto nativo Android, instalamos e configuramos o plugin do FCM para Flutter e enviamos uma notificação, partindo do console FCM para um dispositivo específico (no caso, o nosso app), através do Push Token que foi gerado.
Os códigos deste artigo estão disponíveis neste repositório do GitHub.
Vale lembrar que para o código funcionar, você precisa gerar o seu arquivo
google-services.json
e colocá-lo na pastaandroid/app
.
Muito obrigado por chegar até aqui e espero, de verdade, que tenha sido um conhecimento útil e que agregue positivamente para a sua carreira!