Seguimiento de desinstalaciones
Realiza un seguimiento de las desinstalaciones de apps para medir la retención de usuarios y optimizar las campañas de reenganche integrando servicios de notificaciones push con Singular SDK.
Importante: Google dejó obsoletas las API de GCM en abril de 2018. Utilice Firebase Cloud Messaging (FCM) para todas las implementaciones de seguimiento de desinstalación de Android.
Seguimiento de desinstalación de Android
Requisitos previos
Antes de implementar el seguimiento de desinstalación en tu app Flutter, configura tu app en la plataforma Singular siguiendo la guía Configuración del seguimiento de desinstalación de Android.
Requisitos del sistema
El seguimiento de desinstalación requiere Firebase Cloud Messaging y configuraciones específicas del dispositivo.
Requisitos de FCM(fuente):
- Versión de Android: Los dispositivos deben ejecutar Android 4.1 (API 16) o superior
- Servicios de Google Play: Los dispositivos deben tener instalada la aplicación Google Play Store
- Compatibilidad con emuladores: Se admiten emuladores de Android 4.1+ con API de Google
- Distribución: Las aplicaciones se pueden distribuir fuera de Google Play Store sin dejar de admitir el seguimiento de desinstalaciones.
Nota: no se realizará el seguimiento de las desinstalaciones de los usuarios que utilicen versiones de Android no compatibles o dispositivos sin Google Play Services.
Pasos de implementación
Paso 1: Instalar paquetes Firebase
Añade las dependencias de Firebase a tu archivo pubspec.yaml para la funcionalidad básica y el soporte de mensajería.
dependencies:
flutter:
sdk: flutter
firebase_core: ^2.24.2
firebase_messaging: ^14.7.10
singular_flutter_sdk: ^1.8.0
Después de añadir las dependencias, ejecute flutter pub get para instalar los paquetes.
Paso 2: Configurar Firebase
Añade los archivos de configuración de Firebase a tu proyecto Flutter para Android.
- Registra tu aplicación Android en tu proyecto Firebase Console
- Descarga
google-services.jsony colócalo enandroid/app/ - Verifica que las dependencias de mensajería de Firebase están añadidas a tu proyecto
Para obtener instrucciones de configuración detalladas, consulta Añadir Firebase a tu app Flutter.
Paso 3: Inicializar Firebase
Inicialice Firebase antes de ejecutar su app Flutter para habilitar los servicios de mensajería.
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase
await Firebase.initializeApp();
runApp(MyApp());
}
Paso 4: Solicitar permisos de notificación
Solicite permisos de notificación al usuario (necesario para Android 13+) antes de recuperar el token FCM.
import 'package:firebase_messaging/firebase_messaging.dart';
import 'dart:io';
Future<bool> requestNotificationPermission() async {
if (Platform.isAndroid) {
// Android 13+ requires explicit permission request
// Note: firebase_messaging handles this automatically via requestPermission
final FirebaseMessaging messaging = FirebaseMessaging.instance;
final NotificationSettings settings = await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
return settings.authorizationStatus == AuthorizationStatus.authorized ||
settings.authorizationStatus == AuthorizationStatus.provisional;
}
// iOS permission handled separately
return true;
}
Paso 5: Recuperar y registrar el token FCM
Obtenga el token de dispositivo FCM y regístrelo en Singular utilizando registerDeviceTokenForUninstall() después de solicitar los permisos.
import 'package:flutter/material.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'dart:io';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
if (Platform.isAndroid) {
initializeAndroidUninstallTracking();
}
}
Future<void> initializeAndroidUninstallTracking() async {
try {
// Request notification permission
final hasPermission = await requestNotificationPermission();
if (!hasPermission) {
print('Notification permission denied - uninstall tracking unavailable');
return;
}
// Get FCM token
final token = await FirebaseMessaging.instance.getToken();
if (token != null) {
// Register token with Singular for uninstall tracking
Singular.registerDeviceTokenForUninstall(token);
print('FCM token registered with Singular: $token');
} else {
print('No FCM token available');
}
} catch (error) {
print('Error setting up uninstall tracking: $error');
}
}
Future<bool> requestNotificationPermission() async {
final messaging = FirebaseMessaging.instance;
final settings = await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
return settings.authorizationStatus == AuthorizationStatus.authorized ||
settings.authorizationStatus == AuthorizationStatus.provisional;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
Firma del método:
static void registerDeviceTokenForUninstall(String token)
Para obtener la documentación completa del método, consulte la referencia registerDeviceTokenForUninstall.
Paso 6: Gestionar la actualización del token
Actualice el token FCM con Singular cada vez que se actualice para mantener un seguimiento preciso de la desinstalación.
import 'package:flutter/material.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'dart:io';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
if (Platform.isAndroid) {
setupTokenRefreshListener();
}
}
void setupTokenRefreshListener() {
// Listen for token refresh events
FirebaseMessaging.instance.onTokenRefresh.listen((String token) {
print('FCM token refreshed: $token');
// Update Singular with new token
Singular.registerDeviceTokenForUninstall(token);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
Práctica recomendada: Los tokens FCM pueden actualizarse en cualquier momento (actualizaciones de aplicaciones, restauración de dispositivos, etc.). Suscríbase siempre al flujo onTokenRefresh para mantener Singular actualizado con el token más reciente.
Seguimiento de la desinstalación de iOS
Requisitos previos
Configure su aplicación iOS en la plataforma Singular siguiendo la guía Configuración del seguimiento de desinstalación de iOS.
El seguimiento de desinstalaciones en iOS se basa en la tecnología del servicio de notificaciones push de Apple (APNs). Si su aplicación no es compatible con las notificaciones push, consulte la guía de Apple para Registrar su aplicación con APNs.
Pasos de implementación
Paso 1: Configurar el proyecto iOS
Añade la configuración de Firebase y habilita las capacidades de notificaciones push en tu proyecto iOS.
- Registra tu app iOS en tu proyecto Firebase Console
- Descarga
GoogleService-Info.plisty añádelo a la carpeta Xcode Runner - En la configuración del proyecto Xcode, habilita la capacidad de Notificaciones Push
- Habilita Background Modes y marca Remote notifications
Paso 2: Solicitar autorización de notificaciones iOS
Solicite permisos de notificación al usuario y recupere el token del dispositivo APNS.
import 'package:firebase_messaging/firebase_messaging.dart';
import 'dart:io';
Future<bool> requestIOSNotificationPermission() async {
if (!Platform.isIOS) {
return false;
}
try {
final FirebaseMessaging messaging = FirebaseMessaging.instance;
final NotificationSettings settings = await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
provisional: false,
);
final authorized =
settings.authorizationStatus == AuthorizationStatus.authorized ||
settings.authorizationStatus == AuthorizationStatus.provisional;
if (authorized) {
print('iOS notification authorization status: ${settings.authorizationStatus}');
return true;
}
return false;
} catch (error) {
print('Error requesting iOS notification permission: $error');
return false;
}
}
Paso 3: Recuperar y registrar el token APNS
Obtenga el token de dispositivo APNS y regístrelo en Singular utilizando registerDeviceTokenForUninstall() una vez concedida la autorización.
import 'package:flutter/material.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'dart:io';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
if (Platform.isIOS) {
initializeIOSUninstallTracking();
}
}
Future<void> initializeIOSUninstallTracking() async {
try {
// Request notification authorization
final hasPermission = await requestIOSNotificationPermission();
if (!hasPermission) {
print('Notification permission denied - uninstall tracking unavailable');
return;
}
// Get APNS token
final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
if (apnsToken != null) {
// Register token with Singular for uninstall tracking
Singular.registerDeviceTokenForUninstall(apnsToken);
print('APNS token registered with Singular: $apnsToken');
} else {
print('No APNS token available');
}
} catch (error) {
print('Error setting up iOS uninstall tracking: $error');
}
}
Future<bool> requestIOSNotificationPermission() async {
final messaging = FirebaseMessaging.instance;
final settings = await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
return settings.authorizationStatus == AuthorizationStatus.authorized ||
settings.authorizationStatus == AuthorizationStatus.provisional;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
Formato del token: El token APNS recuperado de getAPNSToken() ya está formateado como cadena hexadecimal, que es el formato correcto para Singular.
Paso 4: Actualización del token (iOS)
Actualice el token APNS con Singular si cambia durante el ciclo de vida de la aplicación.
import 'package:flutter/material.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'dart:io';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
if (Platform.isIOS) {
setupIOSTokenRefreshListener();
}
}
void setupIOSTokenRefreshListener() {
// Listen for token refresh events
FirebaseMessaging.instance.onTokenRefresh.listen((String token) {
print('APNS token refreshed: $token');
// Update Singular with new token
Singular.registerDeviceTokenForUninstall(token);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
Implementación completa multiplataforma
Configuración unificada de seguimiento de desinstalación
Implemente el seguimiento de desinstalación para las plataformas Android e iOS con la lógica adecuada de gestión de errores y actualización de tokens.
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_config.dart';
import 'dart:io';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
// Initialize Singular SDK
initializeSingularSDK();
// Setup uninstall tracking
initializeUninstallTracking();
// Setup token refresh listener
setupTokenRefreshListener();
}
void initializeSingularSDK() {
final config = SingularConfig(
'YOUR_SDK_KEY',
'YOUR_SDK_SECRET'
);
Singular.start(config);
}
Future<void> initializeUninstallTracking() async {
try {
if (Platform.isAndroid) {
await setupAndroidUninstallTracking();
} else if (Platform.isIOS) {
await setupIOSUninstallTracking();
}
} catch (error) {
print('Error initializing uninstall tracking: $error');
}
}
Future<void> setupAndroidUninstallTracking() async {
print('Setting up Android uninstall tracking');
// Request notification permission
final messaging = FirebaseMessaging.instance;
final settings = await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
if (settings.authorizationStatus != AuthorizationStatus.authorized &&
settings.authorizationStatus != AuthorizationStatus.provisional) {
print('Android notification permission denied');
return;
}
// Get and register FCM token
final token = await messaging.getToken();
if (token != null) {
Singular.registerDeviceTokenForUninstall(token);
print('Android FCM token registered: $token');
} else {
print('Failed to retrieve Android FCM token');
}
}
Future<void> setupIOSUninstallTracking() async {
print('Setting up iOS uninstall tracking');
// Request iOS notification authorization
final messaging = FirebaseMessaging.instance;
final settings = await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
final authorized =
settings.authorizationStatus == AuthorizationStatus.authorized ||
settings.authorizationStatus == AuthorizationStatus.provisional;
if (!authorized) {
print('iOS notification permission denied');
return;
}
// Get and register APNS token
final apnsToken = await messaging.getAPNSToken();
if (apnsToken != null) {
Singular.registerDeviceTokenForUninstall(apnsToken);
print('iOS APNS token registered: $apnsToken');
} else {
print('Failed to retrieve iOS APNS token');
}
}
void setupTokenRefreshListener() {
// Listen for token refresh events (works for both platforms)
FirebaseMessaging.instance.onTokenRefresh.listen((String token) {
print('${Platform.operatingSystem.toUpperCase()} token refreshed: $token');
Singular.registerDeviceTokenForUninstall(token);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(
title: Text('Uninstall Tracking Demo'),
),
body: Center(
child: Text('Uninstall tracking initialized'),
),
),
);
}
}
Notas específicas para cada plataforma
- iOS: Asegúrese de que su aplicación tiene los derechos de notificación push necesarios y de que los APN están correctamente configurados en su cuenta de desarrollador de Apple.
-
Android: Verifica que FCM está configurado en tu consola Firebase y que el archivo
google-services.jsonestá incluido en tu proyecto enandroid/app/
Verificación y resolución de problemas
Verificar la implementación
Confirme que el seguimiento de desinstalación funciona correctamente antes de desplegar a producción.
- Compruebe los registros: Compruebe que el registro de tokens aparece en los registros de la consola con el formato correcto.
- Pruebe la generación de tokens: Asegúrese de que los tokens se generan en el primer lanzamiento de la aplicación después de conceder los permisos.
- Supervise el panel de control: Compruebe los datos de seguimiento de desinstalación del panel de Singular transcurridas 24-48 horas.
- Prueba de actualización de tokens: Borre los datos de la aplicación y compruebe que los tokens se actualizan correctamente al reiniciar la aplicación.
Problemas comunes
-
Token no generado: Comprueba que las dependencias de Firebase están correctamente instaladas y que Firebase está configurado en tu proyecto Flutter. Ejecute
flutter pub getdespués de añadir las dependencias - Permiso denegado: Comprueba que los usuarios han concedido permisos de notificación. Para Android 13+, se requiere una solicitud de permiso explícita. Para iOS, los usuarios deben autorizar las notificaciones
-
Token no actualizado: Asegúrate de que te has suscrito al flujo
onTokenRefreshpara ambas plataformas. La escucha debe configurarse en la inicialización de la aplicación. - Faltan datos: Confirma que los dispositivos cumplen los requisitos de la plataforma (Android 4.1+ con Google Play Services, iOS con soporte APNs). Los dispositivos sin estos servicios no pueden ser rastreados
- Error de configuración: Compruebe que el seguimiento de desinstalación está activado en la configuración de la plataforma Singular para su aplicación. Siga las guías de configuración específicas de la plataforma enlazadas en Requisitos previos
-
Configuración de Firebase: Para Android, asegúrese de que
google-services.jsonestá enandroid/app/. Para iOS, asegúrese de queGoogleService-Info.plistse añade a la carpeta Runner del proyecto Xcode. -
Inicialización del SDK: Confirme que Singular SDK está inicializado antes de llamar a
registerDeviceTokenForUninstall(). El registro del token debe realizarse después de iniciar el SDK. -
Detección de plataforma: Utilice
Platform.isAndroidyPlatform.isIOSdesdedart:iopara garantizar que el código específico de la plataforma se ejecuta en la plataforma correcta.
Recursos adicionales: Para obtener información detallada sobre la solución de problemas, consulte la Guía de configuración de seguimiento de des instalación de Android, la Guía de configuración de seguimiento de desinstalación de iOS y la Documentación de configuración de Firebase de Flutter.
Mejores prácticas
Gestión de tokens
- Registro temprano: Solicite permisos y registre tokens lo antes posible en el ciclo de vida de la aplicación, idealmente durante el primer lanzamiento de la aplicación.
- Gestión de errores: Implemente una sólida gestión de errores en torno a la recuperación y el registro de tokens para gestionar los fallos con elegancia.
- Actualización de tokens: Implementa siempre escuchas de actualización de tokens para mantener Singular actualizado cuando cambien los tokens.
- Experiencia de usuario: Solicitar permisos de notificación en contexto, explicando por qué la aplicación los necesita para mejorar las tasas de concesión de permisos.
Estrategia de pruebas
- Pruebas de desarrollo: Probar tanto en dispositivos físicos Android como iOS, ya que los emuladores pueden tener un soporte limitado de notificaciones push
- Flujos de permisos: Probar escenarios en los que los usuarios denieguen permisos y verificar que la aplicación los gestiona correctamente.
- Persistencia de tokens: Verificar que los tokens persisten durante los reinicios de la aplicación y se actualizan correctamente al actualizarla.
- Registro: Habilite un registro detallado durante el desarrollo para realizar un seguimiento de la generación y el registro de tokens.