Plugin para incluir en proyectos mobile de Siltium que permite el uso de notificaciones push, tanto en Foreground App como en Background y Terminate App.
Flutter: 3.10.6
Dart: 3.0.6
1.0.0 - Notificaciones Push para Android y iOS
Consultar archivo CHANGELOG.md para mas info de versiones.
- Agregar la librería en
pubspec.yaml
:
dependencies:
s_push_notifications:
git:
url: https://github.com/siltium-labs/flutter-push-notifications.git
# ref a branch
ref: development
# or ref a version tag
# ref: 1.0.0
Nota: Si se referencia directamente a una rama de dicho repositorio (como development) y se realizan cambios en la misma, es necesario quitar la librería (comentarla), correr el comando flutter pub get
, volver a agregar la librería (descomentarla) y finalmente volver a correr el comando flutter pub get
.
- Modificar el minSdkVersion a 19 en
project_name\android\app\build.gradle
:
android {
defaultConfig {
minSdkVersion 19
...
}
}
- Para pruebas en iOS hay que tener una cuenta registrada en la appStore, para asi obtener y agregar los certificados que necesita Firebase para conectarse con los servicios de iOS:
FirebaseConsole > Configuración de proyecto > Cloud Messaging > Configuración de la app de Apple
- Luego, en el editor Xcode, abrir la carpeta
ios
del proyecto y entrar en el directorioRunner
y archivo del mismo nombre. Habilitar las opciones deBackground fetch
yRemote notifications
.
Nota: En caso de no encontrarse las opciones mencionadas, agregar primero desde Signing & Capabilities
la opcion Push Notifications
.
- En Firebase, Ir a la Consola Firebase y crear un nuevo proyecto:
Colocarle nombre al nuevo proyecto y continuar:
También puedes habilitar o deshabilitar Google Analytics. Si lo deshabilitas, seguidamente puedes crear el proyecto. Si no, continúa a la configuración del mismo:
Al habilitar Google Analytics es necesario configurarlo y aceptar las condiciones de uso. Y finalmente, puedes crear el proyecto:
- Luego, añadir Firebase a tu aplicación: NuevoProyectoFirebase -> Agregar app -> Flutter
A continuación, seguir los pasos 1 y 2 de la documentación oficial que se muestran en pantalla.
Nota: Si es la primera vez que usas Firebase con Flutter, realiza los pasos 1 y 2 completos. Si ya lo usaste anteriormente, realiza a partir del paso 2.
También puedes seguir la guía de la Documentación oficial para Agregar Firebase en una app de Flutter
(Una vez terminada esta guía, también es necesario ir a NuevoProyectoFirebase -> Agregar app -> Flutter)
Para agregar y utilizar en tu proyecto el plugin de notificaciones push, primero debes seguir estos pasos:
- Importar la librería
s_push_notifications
y el archivofirebase_options.dart
(generado anteriormente con la intalación/configuración de Firebase) en el archivomain.dart
de tu proyecto:
// Package and Firebase options file import
import 'package:s_push_notifications/s_push_notifications.dart';
import 'firebase_options.dart';
- Inicializar la librería en
main.dart
conSPushNotify().init()
, pasando al parámetrooptions
un FirebaseOptions, que se encuentra en el archivofirebase_options.dart
, como se muestra a continuación:
void main() async {
await SPushNotify().init(options: DefaultFirebaseOptions.currentPlatform);
runApp(const MyApp());
}
Nota: No olvidar agregar el async al main().
Ahora ya puedes usar el plugin y las diferentes funcionalidades que contiene.
- Primero, para lograr hacer pruebas de envío de notificaciones push con Firebase, vamos a llamar a la función
SPushNotify().getToken()
para obtener el token del dispositivo y enviar dichas notificaciones al mismo:
void main() async {
await SPushNotify().init(options: DefaultFirebaseOptions.currentPlatform);
// Obtenemos el token del dispositivo
final fcmToken = await SPushNotify().getToken();
debugPrint("TOKEN: $fcmToken");
//
runApp(const MyApp());
}
Nota: Cada vez que se realice un build
de la aplicación, devolverá un token diferente.
- Seguidamente en tu proyecto, en la pantalla que quieras agregar el manejo de notificaciones, llamar a las siguientes funciones según tu preferencia:
SPushNotify().requestPermission()
-> Para pedir los permisos correspondientes para mostrar las notificaciones push (Obligatorio para iOS y Android 13 o superior).SPushNotify().onForegroundNoify()
-> Para manejar las notificaciones push cuando se reciben, mientras la app esta abierta o en primer plano (Foreground App).SPushNotify().onBackgroundNotify()
-> Para manejar las notificaciones push cuando se reciben, mientras la app esta cerrada o en segundo plano (Terminated y Background App).SPushNotify().onTapBackgroundNotify()
-> Para manejar las notificaciones push al ser presionadas o seleccionadas desde la barra de notificaciones, mientras la app esta cerrada o en segundo plano (Terminated y Background App).
IMPORTANTE:
La función que se utilice en SPushNotify().onBackgroundNotify()
para manejar las notificaciones, debe tener la siguiente estructura:
@override
void initState() {
super.initState();
_onReceiveBackgroundNotify();
}
_onReceiveBackgroundNotify() async {
await SPushNotify().onBackgroundNotify(_onBackgroundMessage);
}
// Esta función debe seguir la siguiente estructura:
// 1) Si usas Flutter 3.3.0 o una versión posterior, debe tener la siguiente anotación justo encima de la declaración de la función:
@pragma('vm:entry-point')
// 2) La función no debe ser anónima.
// 3) Y la función no debe ser de nivel superior (por ejemplo, no un método de clase que requiera inicialización)
// o bien, debe ser una funcion "static".
static Future<void> _onBackgroundMessage(message) async {
// Tú código para manejo de Background Notifications;
}
Otros métodos:
onSubscribeTopic
-> Para que la app cliente se pueda suscribir a cualquier tema existente o pueda crear un tema nuevo. Debe pasarse el nombre del tema (o topic) como un String.onUnsubscribeTopic
-> Para que la app cliente pueda anular la suscripción. Debe pasarse el nombre del tema (o topic) como un String.deleteToken
-> Para que la app cliente no reciba notificaciones push (por ejemplo, si el usuario cierra sesión).
subscribeToTopic() async {
String topic = "weather";
// Suscribirse a un tema
await SPushNotify().onSubscribeTopic(topic);
}
unsubscribeFromTopic() async {
// Anular suscripción a un tema
await SPushNotify().onUnsubscribeTopic("weather");
}
deleteAppToken() async {
// Eliminar token para dejar de recibir push notifications
await SPushNotify().deleteToken();
}
- Entrar en la Consola de Firebase, en la pestaña "Participación" del menú lateral y allí elegir "Messaging". En esta parte vamos a poder mandar mensajes de prueba y campañas:
- Ir a "Campaña nueva":
- En esta pantalla completar los datos que quieras enviar en la notificación push de prueba, y luego en "Enviar mensaje de prueba" agregar el token de tu dispositivo (obtenido anteriormente, en el paso 1). Entonces, al presionar "Probar" se enviará la notificación de prueba solamente al dispositivo cuyo token agregamos:
- Una vez realizada la prueba y recibida la notificación push, ahora si podemos realizar una nueva campaña. Del mismo modo que el paso anterior, completamos los datos en la pantalla de "Campaña nueva" y al final de la misma hacemos click en "Revisar" y "Publicar":
Ejemplo de home_page.dart, que se encuentra en la carpeta example de este plugin.
import 'package:flutter/material.dart';
import 'package:s_push_notifications/s_push_notifications.dart';
import 'package:s_push_notifications_example/notification_page.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('S-Push Notify - Siltium'),
centerTitle: true,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Center(
child: Text(
'Home Page',
style: TextStyle(
fontSize: 25,
),
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => _navigate(),
child: const Text("Navegar a Notify"),
),
const SizedBox(height: 20),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 30),
child: Divider(
color: Colors.white,
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => _subscribeToTopic("Clima"),
child: const Text("Suscribir a \"Clima\""),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => _unsubscribeFromTopic("Clima"),
child: const Text("Desuscribir de \"Clima\""),
),
],
),
);
}
// FUNCIONES --------------------------------------------------
@override
void initState() {
super.initState();
_requestPermission();
_onReceiveForegroundNotify();
_onReceiveBackgroundNotify();
_onTapBackgroundNotify();
}
_navigate() {
return Navigator.push(
context,
MaterialPageRoute(
builder: ((context) => const NotificationPage()),
),
);
}
_requestPermission() async {
// Por buenas practicas, no llamar a este método al inicio de la app.
// Llamarlo recién cuando se necesite mostrar las notificaciones push
await SPushNotify().requestPermission();
}
_onReceiveForegroundNotify() async {
await SPushNotify().onForegroundNoify(
onData: (message) {
debugPrint("-----RECEIVE FOREGROUND NOTIFY-----");
debugPrint("Title: ${message.notification?.title}");
debugPrint("Body: ${message.notification?.body}");
debugPrint("Payload: ${message.data}");
debugPrint("----------------------------------------------");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Notify: ${message.notification?.title}")));
},
onError: (error) {
// on error code
},
onDone: () {
// on done code
},
);
}
_onReceiveBackgroundNotify() async {
await SPushNotify().onBackgroundNotify(onData: _onBackgroundMessage);
// ó también
// await SPushNotify().onBackgroundNotify(onData: (message) => _onBackgroundMessage(message));
}
_onTapBackgroundNotify() async {
await SPushNotify().onTapBackgroundNotify(
onData: (message) {
debugPrint("-----ONTAP BACKGROUND/TERMINATED NOTIFY-----");
debugPrint("Title: ${message.notification?.title}");
debugPrint("Body: ${message.notification?.body}");
debugPrint("Payload: ${message.data}");
debugPrint("----------------------------------------------");
_navigate();
},
onError: (error) {
// on error code
},
onDone: () {
// on done code
},
);
}
@pragma('vm:entry-point')
static Future<void> _onBackgroundMessage(message) async {
debugPrint("-----RECEIVE BACKGROUND/TERMINATED NOTIFY-----");
debugPrint("Title: ${message.notification?.title}");
debugPrint("Body: ${message.notification?.body}");
debugPrint("Payload: ${message.data}");
debugPrint("----------------------------------------------");
}
_subscribeToTopic(String topic) async {
await SPushNotify().onSubscribeTopic(topic);
_showSnackBar("Suscripto a \"$topic\".");
}
_unsubscribeFromTopic(String topic) async {
await SPushNotify().onUnsubscribeTopic(topic);
_showSnackBar("Suscripción a \"$topic\" anulada.");
}
_showSnackBar(String text) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(text)));
}
}