ios - notification - push firebase android
Las notificaciones de fondo de FCM no funcionan en iOS (7)
-Para FCM cuando la aplicación está en segundo plano o en primer plano y se activará la aplicación OS <10 (_: didReceiveRemoteNotification :).
-Cuando la aplicación está en primer plano y OS => 10 userNotificationCenter: willPresentNotification: withCompletionHandler: el método se activará.
-Cuando se envía un mensaje de datos sin componente de notificación: la aplicación (_: didReceiveRemoteNotification :) se activará.
-Cuando se envía un mensaje de datos con el componente de notificación: userNotificationCenter: willPresentNotification: withCompletionHandler: el método se activará.
Tengo un problema con la notificación FCM en iOS.
Recibo notificaciones con éxito cuando mi aplicación está en primer plano (la devolución de llamada
didReceiveRemoteNotification
en
appdelegate
está
appdelegate
), pero no recibo notificaciones cuando la aplicación está en segundo plano (no veo nada en la bandeja de notificaciones de iOS).
Entonces, creo que el problema está en el formato del mensaje enviado por FCM. El json enviado por mi servidor a FCM tiene el siguiente formato:
{
"data":{
"title":"mytitle",
"body":"mybody",
"url":"myurl"
},
"notification":{
"title":"mytitle",
"body":"mybody"
},
"to":"/topics/topic"
}
Como puede ver, hay dos bloques en mi json: un bloque de notificaciones (para recibir notificaciones en segundo plano) y un bloque de datos (para recibir notificaciones en primer plano).
No puedo entender por qué no se reciben notificaciones en segundo plano. Mis dudas son sobre el orden de los bloques (¿es un problema si pongo el bloque de "datos" antes del bloque de "notificación"?).
EDITAR: más información sobre el problema.
Este es mi appdelegate.swift:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
{
var window: UIWindow?
// Application started
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
{
let pushNotificationSettings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(pushNotificationSettings)
application.registerForRemoteNotifications()
FIRApp.configure()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "tokenRefreshNotification:", name: kFIRInstanceIDTokenRefreshNotification, object: nil)
return true
}
// Handle refresh notification token
func tokenRefreshNotification(notification: NSNotification) {
let refreshedToken = FIRInstanceID.instanceID().token()
print("InstanceID token: /(refreshedToken)")
// Connect to FCM since connection may have failed when attempted before having a token.
if (refreshedToken != nil)
{
connectToFcm()
FIRMessaging.messaging().subscribeToTopic("/topics/topic")
}
}
// Connect to FCM
func connectToFcm() {
FIRMessaging.messaging().connectWithCompletion { (error) in
if (error != nil) {
print("Unable to connect with FCM. /(error)")
} else {
print("Connected to FCM.")
}
}
}
// Handle notification when the application is in foreground
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// Print message ID.
print("Message ID: /(userInfo["gcm.message_id"])")
// Print full message.
print("%@", userInfo)
}
// Application will enter in background
func applicationWillResignActive(application: UIApplication)
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
// Application entered in background
func applicationDidEnterBackground(application: UIApplication)
{
FIRMessaging.messaging().disconnect()
print("Disconnected from FCM.")
}
// Application will enter in foreground
func applicationWillEnterForeground(application: UIApplication)
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
// Application entered in foreground
func applicationDidBecomeActive(application: UIApplication)
{
connectToFcm()
application.applicationIconBadgeNumber = 0;
}
// Application will terminate
func applicationWillTerminate(application: UIApplication)
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
La única forma en que puedo recibir mensajes en primer plano es deshabilitando el método swizzling, configurando FirebaseAppDelegateProxyEnabled en NO en mi info.plist.
En este caso, la documentación de FCM dice que tengo que implementar en mi appdelegate.swift dos métodos:
- FIRMessaging.messaging().appDidReceiveMessage(userInfo) in didReceiveRemoteNotification callback
- FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Sandbox) in didRegisterForRemoteNotificationsWithDeviceToken callback
Pero si implemento esas funciones, los mensajes dejan de llegar incluso cuando la aplicación está en primer plano.
Sé que esto es muy extraño.
EDITAR 2:
Cuando la aplicación está en segundo plano, no se recibe la notificación, pero cuando abro mi aplicación, se recibe la misma notificación de inmediato (se activa el método didReceiveRemoteNotification).
Prioridad y contenido_disponible (como se menciona en otras respuestas) son los elementos clave para asegurarse de recibir las notificaciones. Las pruebas mostraron resultados interesantes, así que pensé en compartirlas aquí.
Resultados de la prueba: Swift 3, Xcode 8, iOS 10
Prioridad = "alta" => "inmediata" (dentro de demoras obvias de la red) recepción del mensaje.
Prioridad = "normal" => varios resultados (generalmente rápido, aunque obviamente más lento que "alto")
content_available = true en las notificaciones (sin mensaje de carga útil)
- Primer plano = datos recibidos como se esperaba
- Fondo = datos recibidos como se esperaba (al abrir la aplicación)
content_available = true en el nivel superior (sin mensaje de carga útil)
- Primer plano = datos recibidos como se esperaba
- Fondo = datos recibidos como se esperaba (al abrir la aplicación)
content_available = true en las notificaciones (con mensaje {title / body})
- Primer plano = datos recibidos DOS VECES
- Fondo = datos recibidos DOS VECES (al abrir la aplicación)
content_available = true en el nivel superior (con mensaje de carga útil)
- Primer plano = datos recibidos DOS VECES
- Fondo = datos recibidos DOS VECES (al abrir la aplicación)
CONCLUSIONES
- Si bien la prioridad es una posible causa de no recibir mensajes, el factor MÁS IMPORTANTE es que debe tener ''content_available'' o un mensaje de carga útil.
- content_available DEBE usarse en cargas útiles solo de datos (sin él, nunca se envía ningún mensaje).
- content_available NO DEBE usarse en cargas útiles que contienen mensajes, ya que hace que se envíen mensajes dobles desde FCM.
- No se encontraron diferencias en el uso de content_available en el nivel superior o en las notificaciones.
EDITAR: Resultados de pruebas adicionales: - si tiene un título de mensaje, DEBE tener un cuerpo de mensaje o no recibe una alerta.
La parte extraña de esto es que obtendrás la vibración, la insignia y el sonido, pero el cuadro de alerta no aparecerá a menos que tengas un cuerpo y el título.
Suponiendo que ha configurado todo correctamente, luego establecer la
priority
del mensaje de
normal
a
high
debería hacer que aparezca de inmediato.
Esto se debe a la forma en que iOS agrupa las notificaciones y las maneja.
Puede leer sobre la
Prioridad de las notificaciones de FCM aquí
.
Tenga en cuenta que realmente no debe usar
high
producción
high
a menos que haya un buen caso, ya que tiene una penalización de batería.
Aquí está la referencia de los documentos de Apple
La prioridad de la notificación. Especifique uno de los siguientes valores:
10 – Enviar el mensaje push de inmediato. Las notificaciones con esta prioridad deben activar una alerta, sonido o insignia en el dispositivo de destino. Es un error utilizar esta prioridad para una notificación push que contiene solo la clave de contenido disponible.
5: envíe el mensaje de inserción en un momento que tenga en cuenta las consideraciones de energía para el dispositivo. Las notificaciones con esta prioridad se pueden agrupar y entregar en ráfagas. Están estrangulados y, en algunos casos, no se entregan. Si omite este encabezado, el servidor APN establece la prioridad en 10.
Tuve este problema con el conjunto de propiedades
content_available
.
La solución fue eliminar y reinstalar la aplicación desde el dispositivo iOS.
cuando usas mensajes directos del canal FCM no puedes recibir notificaciones en segundo plano
Este es un párrafo del documento de Firebase :
Con el canal directo habilitado, el backend de FCM utiliza una cola de mensajes confiable para realizar un seguimiento de los mensajes pendientes cuando la aplicación está en segundo plano o cerrada. Cuando la aplicación pasa a primer plano y se restablece la conexión, el canal enviará automáticamente mensajes pendientes al cliente hasta que reciba un reconocimiento del cliente.
puede usar la interfaz FCM APN para recibir notificaciones tanto en primer plano como en segundo plano
content_available
establecer la propiedad
content_available
en true de la siguiente manera:
{
"data":{
"title":"mytitle",
"body":"mybody",
"url":"myurl"
},
"notification":{
"title":"mytitle",
"body":"mybody",
"content_available": true
},
"to":"/topics/topic"
}
Hay un cuadro de nota azul en esta sección que dice esto: https://firebase.google.com/docs/cloud-messaging/concept-options#notifications