Push Notifications - Flutter com OneSignal.
O mais usado recentemente para push é o firebase, devido a sua alta integração com o Flutter, mas nesse artigo irei apresentar uma forma mais descomplicada ainda de enviar push notifications. A plataforma se chama OneSignal.
O OneSignal é uma plataforma que se comunica com o firebase para fazer o push, nele é possível ainda utilizar o crashlytics. Então, neste artigo iremos fazer a comunicação com o OneSignal e o App em flutter.
Primeiro passo
Acessar o site do OneSignal e criar uma conta.
Segundo passo
Criar uma conta no Firebase ou usar a sua existente.
Terceiro passo
Agora com as duas contas criadas, vamos criar um app no Firebase e outro no OneSignal.
Firebase
Acesse o console e adicione um projeto com o seu nome de preferência.
Projeto criado, vamos acessar a parte de configurações e navegar para Cloud Messaging.
Nesta parte, iremos necessitar da Chave do servidor e do código do remetente, deixe isso aberto e vamos para o passo seguinte, a criação de um app no OneSignal.
OneSignal
Logue no sistema e clique em ADD APP, coloque um nome de sua preferência.
Escolha em seguida a plataforma Android.
Agora iremos colocar as duas keys do Firebase mencionadas anteriormente.
Pressione save e escolha Native Android.
Finalizando tudo certo, irá ficar nesta página.
Your App ID será a key usada no seu app flutter para identificar seu aplicativo. Então deixe isso aberto no navegador pois iremos utilizar.
Concluímos as configurações básicas, agora iremos colocar a mão na massa, com o aplicativo.
Daqui em diante fica a sua escolha, de criar um app novo ou usar em um projeto existente.
Android Studio
Agora com nosso projeto criado no Android Studio, iremos então adicionar o plugin onesignal_flutter no pubspect.yaml
name: flutteronesignal
description: Desenvolvido por Gabriel Savio, CEO da Grape DEV
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
onesignal_flutter: any
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
Agora precisamos configurar os arquivos do android.
Primeiro arquivo: android/build.gradle
Vamos adicionar a seguinte linha:
buildscript {
repositories {
// ...
maven { url 'https://plugins.gradle.org/m2/' } // Gradle Plugin Portal
}
dependencies {
// ...
// OneSignal-Gradle-Plugin
classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.1, 0.99.99]'
}
}
Ficando da seguinte forma:
buildscript {
repositories {
google()
jcenter()
maven { url 'https://plugins.gradle.org/m2/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.1, 0.99.99]'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Agora vamos em outro arquivo, no seguinte : android/app/build.gradle e no final dele iremos colar a seguinte linha:
apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin'
Ficando da seguinte forma:
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "grapedev.com.flutteronesignal"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin'
Pronto! Temos tudo configurado para receber o código no flutter para inicializar o OneSignal.
Flutter
Agora vamos para o código no flutter. Iremos criar a estrutura de pastas e arquivos seguintes na imagem:
Obs: ignore.dart é para ser ignorado mesmo, não precisa criar ele.
Nossa arquivo main.dart ficou da seguinte forma:
import 'package:flutter/material.dart';
import 'package:flutteronesignal/pages/home_page.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 One Signal',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
e nossa pages/home/home_page.dart
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("FlutterOneSignal"),
centerTitle: true,
),
body: Column(children: <Widget>[
Text("Notificações")
],),
);
}
}
Com nosso app da seguinte forma.
Agora iremos criar o nosso BlocHome (pages/home/bloc/home_bloc.dart) para iniciar o OneSignal.
import 'package:onesignal/onesignal.dart';
class BlocHome{
void initOneSignal(){
OneSignal.shared.init("your_onesignal_app_id_here");
}
}
Agora volte no site do OneSignal e copie o APPID e cole ai.
Ficando assim:
import 'package:onesignal/onesignal.dart';
class BlocHome{
void initOneSignal(){
OneSignal.shared.init("bc2472d1-fac8-433f-be56-48ea9ecbc1ef");
}
}
obs: Lembre-se de trocar para o seu appID, para conseguir visualizar pelo painel do OneSignal.
Agora precisamos importar esse BlocHome na nossa HomePage e chamar o método initOneSignal no void init, ficando da seguinte forma:
import 'package:flutter/material.dart';
import 'package:flutteronesignal/pages/home/bloc/bloc_home.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
var bloc = BlocHome();
@override
void initState() {
bloc.initOneSignal();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("FlutterOneSignal"),
centerTitle: true,
),
body: Column(children: <Widget>[
Text("Notificações")
],),
);
}
}
Feito isso, agora vamos testar! Dê stop no seu projeto, e compile ele novamente.
Feito isso, vamos ao site do OneSignal, se tudo estiver corrido certo, vai aparecer que seu app tem 1 usuário.
Agora, vamos enviar um push, clique em MESSAGES, procure por NEW PUSH.
Escreva um título e uma message só para teste.
Role até o final e clique em CONFIRM.
Agora é só enviar!
Pronto funcionou! Agora vem a pergunta. Porque apareceu esse popUp feio na minha tela? O onesignal tem um disparador de notificação interno caso o app esteja em primeiro plano, você pode desativar isso com o seguinte código.
OneSignal.shared.setInFocusDisplayType(OSNotificationDisplayType.none);
Adicione ele no initOneSignal.
import 'package:onesignal/onesignal.dart';
class BlocHome{
void initOneSignal(){
OneSignal.shared.init("bc2472d1-fac8-433f-be56-48ea9ecbc1ef");
OneSignal.shared.setInFocusDisplayType(OSNotificationDisplayType.none);
}
}
E se o app estiver em segundo plano? Funciona, faça o teste.
E se o app estiver fechado? Também funciona.
O onesignal tem algumas funções interessantes, podendo identificar cada usuário no seu app por email, e ainda pode enviar TAGS para facilitar na segmentação de usuários para enviar um push específico para um somente ou para um grupo.
As funções sao as seguintes:
//Identifica o user por email
OneSignal.shared.setEmail();//Identifica po um idExterno, id de sua API
OneSignal.shared.setExternalUserId(externalId);//Envia somente uma tag
OneSignal.shared.sendTag(key, value);//Enviar várias tags
OneSignal.shared.sendTags(tags);//Pegar as tags do usuário
OneSignal.shared.getTags();
E também pode utilizar o método abaixo, para pegar a chegada de notificações e tomar decisões dentro do seu app.
OneSignal.shared.setNotificationReceivedHandler((OSNotification notification) {
});
No próximo artigo eu irei implementar a função citada acima, para criar um sistema de notificações interno no aplicativo, um histórico de notificações que já recebeu.
Vou deixar abaixo o link da documentação oficial do OneSignal .
Documentação Oficial do OneSignal sobre Flutter
Segue link do projeto no GitHub