Push notifications
Registrar device tokens, manejar notificaciones y deeplinks.
Configuración con PushConfig
Configura los callbacks de push en SouthGamesSDK.init():
await SouthGamesSDK.init(
apiKey: 'sg_live_xxx',
orgId: 'mi-empresa',
pushConfig: PushConfig(
// Pedir permisos al inicializar (default: true)
requestPermissionOnInit: true,
// Mostrar notificaciones en foreground (default: true)
showForegroundNotifications: true,
// Callback cuando el usuario toca una notificación
onNotificationTap: (message) {
print('Tap: ${message.notification?.title}');
},
// Callback en foreground
onForegroundMessage: (message) {
print('Recibida: ${message.notification?.title}');
},
// Callback automático para deeplinks (ver abajo)
onDeeplinkReceived: (deeplink, message) {
navigatorKey.currentState?.pushNamed(deeplink);
},
),
);
El SDK obtiene el token FCM y lo registra automáticamente al llamar identify().
Deeplinks
Las notificaciones push pueden incluir un deeplink que se entrega al tocar la notificación. El deeplink se configura desde el dashboard al crear el push, y el SDK no lo abre ni lo interpreta: lo entrega parseado para que lo enrutes con tu propio router o sistema de configuración.
Handler unificado (recomendado, v0.8.0+)
onDeeplink es el punto único por el que pasan todos los deeplinks: los de pushes tocados y las acciones de CTAs/botones de notificaciones in-app. Recibe un SgDeeplink con la URI parseada y helpers de ruteo:
await SouthGamesSDK.init(
apiKey: '...',
orgId: '...',
onDeeplink: (link) {
// link.raw -> "myapp://promo/verano?code=ABC"
// link.pathSegments -> ["promo", "verano"]
// link.params -> {"code": "ABC"}
// link.source -> SgDeeplinkSource.push | SgDeeplinkSource.inApp
final promo = link.match('promo/:slug');
if (promo != null) {
context.go('/promos/${promo['slug']}'); // tu router, tus rutas
return;
}
if (link.match('config/:key') != null) {
applySetting(link.pathSegments[1], link.params); // acciones de config
}
},
);
match('patron/:param') compara contra los segmentos de ruta (para schemes propios como myapp://promo/verano el host cuenta como primer segmento) y devuelve los parámetros capturados, o null si no calza.
Cold start: deeplinks que llegan antes que tu router
Si el usuario toca el push con la app cerrada, el deeplink llega durante init() — antes de que exista tu navigator. El SDK lo maneja así:
- Con
init(onDeeplink: ...), la entrega ocurre después del primer frame, cuando tu navigator/router ya existe. No tienes que hacer nada. - Si registras el handler más tarde (setter), los deeplinks acumulados quedan pendientes y se entregan al registrarlo.
// Opción A (recomendada): pasar onDeeplink a init() — cold start cubierto
await SouthGamesSDK.init(apiKey: ..., orgId: ..., onDeeplink: handler);
// Opción B: registrar cuando tu router esté listo (entrega inmediata + pendientes)
SouthGamesSDK.instance.onDeeplink = (link) => router.go(link.raw);
// Opción C: consultar explícitamente al montar la app
final pending = SouthGamesSDK.instance.consumePendingDeeplink();
if (pending != null) router.go(pending.raw);
Push con notificación in-app vinculada
Si el envío se creó con la opción del dashboard "Mostrar también como notificación in-app", el push llega con data.inAppId. Al tocarlo, el SDK busca esa in-app y la muestra automáticamente con el overlay (aunque el usuario la hubiera descartado antes — es una apertura explícita). Para manejarla tú mismo:
PushConfig(autoOpenLinkedInApp: false)
// y luego, donde prefieras:
final inAppId = SouthGamesPush.getInAppId(message);
if (inAppId != null) {
await SouthGamesSDK.instance.getInAppNotificationById(inAppId);
}
Callback legacy
PushConfig.onDeeplinkReceived sigue funcionando igual que siempre (se ejecuta después de onNotificationTap, solo si hay deeplink). Ten en cuenta que este callback no tiene buffer de cold start — para eso usa onDeeplink:
PushConfig(
onDeeplinkReceived: (deeplink, message) {
navigatorKey.currentState?.pushNamed(deeplink);
},
)
Manejo manual
También puedes extraer el deeplink manualmente desde cualquier RemoteMessage:
import 'package:southgames_flutter/southgames_flutter.dart';
final deeplink = SouthGamesPush.getDeeplink(message);
if (deeplink != null) {
// Navegar a la pantalla correspondiente
}
Payload
El deeplink se envía como data.deeplink en el payload push (y data.inAppId cuando hay in-app vinculada):
{
"notification": {
"title": "¡Oferta especial!",
"body": "20% de descuento en tu próxima compra"
},
"data": {
"sendId": "abc123",
"deeplink": "myapp://promo/verano",
"inAppId": "notif456"
}
}
Background handler
Para rastrear notificaciones recibidas en background, registra el handler en main.dart:
@pragma('vm:entry-point')
Future<void> _firebaseBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
await SouthGamesSDK.handleBackgroundMessage(message);
}
void main() {
FirebaseMessaging.onBackgroundMessage(_firebaseBackgroundHandler);
// ...
}
Registro manual de token
Si no usas Firebase Messaging o quieres registrar tokens de otro proveedor:
await SouthGamesSDK.push.registerDeviceToken(
externalId: 'user_123',
token: 'fcm_or_apns_token',
);
Proveedores compatibles
El SDK es agnóstico al proveedor de push. Puedes usar cualquiera:
- Firebase Cloud Messaging (FCM)
- Apple Push Notification service (APNs)
- OneSignal
- Cualquier otro que te dé un device token
Logout
Al hacer logout, el SDK desregistra el token automáticamente:
await SouthGamesSDK.logout();
// El token se elimina del servidor y se borra localmente