Skip to content

siltium-labs/flutter-push-notifications

Repository files navigation


S-PushNotify: Siltium Component for Push Notifications


Descripción

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.

Versión Actual de Flutter (para el Plugin)

Flutter: 3.10.6
Dart: 3.0.6

Versión Actual del Plugin

1.0.0 - Notificaciones Push para Android y iOS

Consultar archivo CHANGELOG.md para mas info de versiones.

Instalación de la Librería

EN FLUTTER:

  1. 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.

PARA ANDROID:

  1. Modificar el minSdkVersion a 19 en project_name\android\app\build.gradle:
android {
    defaultConfig {
        minSdkVersion 19
        ...
    }
}

PARA iOS:

  1. 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

Configurar proyecto firebase con claves apple

  1. Luego, en el editor Xcode, abrir la carpeta ios del proyecto y entrar en el directorio Runner y archivo del mismo nombre. Habilitar las opciones de Background fetch y Remote notifications.

Nota: En caso de no encontrarse las opciones mencionadas, agregar primero desde Signing & Capabilities la opcion Push Notifications.

Configuración en xcode

EN FIREBASE:

  1. En Firebase, Ir a la Consola Firebase y crear un nuevo proyecto:

Crear nuevo proyecto firebase

Colocarle nombre al nuevo proyecto y continuar:

Nombrar el nuevo proyecto firebase

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:

Habilitar/Deshabilitar google analytics

Al habilitar Google Analytics es necesario configurarlo y aceptar las condiciones de uso. Y finalmente, puedes crear el proyecto:

Finalizar y crear el proyecto

  1. Luego, añadir Firebase a tu aplicación: NuevoProyectoFirebase -> Agregar app -> Flutter

Crear App de Flutter en Firebase

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.

Paso 1

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)

Inicialización de la Librería

Para agregar y utilizar en tu proyecto el plugin de notificaciones push, primero debes seguir estos pasos:

  1. Importar la librería s_push_notifications y el archivo firebase_options.dart (generado anteriormente con la intalación/configuración de Firebase) en el archivo main.dart de tu proyecto:
// Package and Firebase options file import
import 'package:s_push_notifications/s_push_notifications.dart';
import 'firebase_options.dart';
  1. Inicializar la librería en main.dart con SPushNotify().init(), pasando al parámetro options un FirebaseOptions, que se encuentra en el archivo firebase_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.

Uso de la Librería

EN FLUTTER:

  1. 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.

  1. 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();
}

EN FIREBASE:

  1. 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:

Prueba push notifications firebase 1

  1. Ir a "Campaña nueva":

Prueba push notifications firebase 2

  1. 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:

Prueba push notifications firebase 3

Prueba push notifications firebase 4

  1. 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":

Prueba push notifications firebase 5

Prueba push notifications firebase 6

Prueba push notifications firebase 7

EJEMPLO

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)));
  }
}