react - Empujes silenciosos no entregados a la aplicación en iOS 11
push notifications ios swift 4 (13)
Noté que en iOS 11 beta 2, las notificaciones silenciosas no se entregan a la
application:didReceiveRemoteNotification:fetchCompletionHandler
independientemente del estado de la aplicación (fondo / primer plano).
Implementé la
application:didReceiveRemoteNotification:fetchCompletionHandler
método
UIApplicationDelegete
application:didReceiveRemoteNotification:fetchCompletionHandler
y envié el siguiente envío silencioso
{
"aps": {
"content-available": 1
},
"mydata": {
"foo": "bar"
}
}
pero el método delegado no se llama en iOS 11.
Funciona bien en otras versiones de iOS y la sección de documentación Configuración de una notificación silenciosa no menciona que se deba hacer nada más.
¿Es esto un error en iOS 11 o me perdí algo nuevo en iOS 11?
Tenga en cuenta que no estoy hablando o usando el marco de
UserNotification
que no debería ser necesario para enviar
UserNotification
silenciosas.
Aquí hay un proyecto de muestra que ilustra el problema (deberá configurar su propia identificación de paquete)
Cuando almuerza el proyecto de muestra y envía una carga útil anterior a la aplicación, puede usar la consola macOS para ver que el envío se envía correctamente al dispositivo pero no a la aplicación.
ACTUALIZACIÓN 10.08
Parece que el comportamiento es aleatorio. A veces, después de reiniciar el dispositivo, la carga útil se entrega correctamente pero deja de funcionar después de un tiempo.
Como puede ver en la siguiente captura de pantalla, la inserción marcada como 1 se entrega solo al dispositivo y la inserción 2 (después del reinicio del dispositivo) también se entrega a la aplicación.
ACTUALIZACIÓN 14.08 - iOS 11 Beta 6
Sigue siendo el mismo comportamiento. Otra cosa que se supone que funciona pero no funciona es la siguiente. Cuando el esquema de la aplicación se establece en "Esperar a que se ejecute el ejecutable", se supone que un impulso silencioso activa la aplicación y la inicia en segundo plano.
ACTUALIZACIÓN 21.08 - iOS 11 Beta 7
Sigue siendo el mismo comportamiento y no actualizaciones de Apple en el informe de error.
ACTUALIZACIÓN 29.08 - iOS 11 Beta 8
Sigue siendo el mismo problema. Los pasos para reproducir que uso ahora son los siguientes:
- En el esquema del proyecto Xcode, seleccione "Esperar a que se ejecute el ejecutable"
-
Agregue un punto de interrupción en
didReceiveRemoteNotification: fetchCompletionHandler
- Inicie la aplicación en el dispositivo
- Enviar el empuje silencioso anterior
Esperado
: la aplicación pasa del estado suspendido al fondo y se llama
didReceiveRemoteNotification: fetchCompletionHandler
Actual : no pasa nada
ACTUALIZACIÓN 06.09 - iOS 11 Beta 10
Todavía tengo el mismo comportamiento con errores. El boleto de Apple se actualizó con la siguiente respuesta:
Relaciones con los desarrolladores de Apple 6 de septiembre de 2017, 10:42 p.m. Ingeniería ha proporcionado los siguientes comentarios sobre este problema:
Pudimos ejecutar la aplicación de muestra y probar el comportamiento. No vimos ningún problema cuando probamos esto como se describe.
No se garantiza que las aplicaciones lleguen a la aplicación cuando se está ejecutando en segundo plano, y los registros aquí indican que no creemos que la aplicación se esté utilizando lo suficiente como para iniciarla.
Nos vemos entregando empujones de vez en cuando cuando las condiciones son buenas.
Creemos que esto se está comportando correctamente.
Actualización 11.09
Mi informe de error de Apple se cerró y se marcó como duplicado de
33278611
que permanece abierto
ACTUALIZACIÓN 13.09 - iOS 11 GM
Gracias a los comentarios de kam800 (ver abajo) hice más pruebas y obtuve esas observaciones:
Parece que hay un nuevo demonio en iOS 11
dasd DuetActivitySchedulerDaemon
que descarta completamente el envío de datos o retrasa la entrega del envío de datos:
Entrega aplazada
Registros de consola
default 13:11:47.177547 +0200 dasd DuetActivitySchedulerDaemon CANCELED: com.apple.pushLaunch.net.tequilaapps.daylight:C03A65 <private>! lifecycle com.apple.duetactivityscheduler
default 13:11:47.178186 +0200 dasd DuetActivitySchedulerDaemon Removing a launch request for application <private> by activity <private> default com.apple.duetactivityscheduler
default 12:49:04.426256 +0200 dasd DuetActivitySchedulerDaemon Advancing start date for <private> by 6.5 minutes to Wed Sep 13 12:55:31 2017 default com.apple.duetactivityscheduler
default 13:21:40.593012 +0200 dasd DuetActivitySchedulerDaemon Activity <private>: Optimal Score 0.6144 at <private> (Valid Until: <private>) scoring com.apple.duetactivityscheduler
default 13:21:40.594528 +0200 dasd DuetActivitySchedulerDaemon Setting timer (isWaking=1, activityRequiresWaking=0) between <private> and <private> for <private> default com.apple.duetactivityscheduler
Problemas de entrega pospuestos
- Cuando la entrega de envío de datos se pospone y se inicia la aplicación, el envío de datos se entrega solo cuando se alcanza la fecha de entrega, que puede ser de varios minutos en el futuro. Esto anula por completo el propósito de usar datos para mantener el contenido de la nueva aplicación listo para el próximo lanzamiento. Cito aquí una vez más la documentación de Apple:
"Las notificaciones silenciosas mejoran la experiencia del usuario al ayudarlo a mantener su aplicación actualizada, incluso cuando no se está ejecutando".
- Cuando se envían dos datos a una aplicación suspendida, iOS 11 los pospone en lugar de activar la aplicación directamente. Cuando se alcanza el tiempo de entrega, ¡ solo se entrega el último envío de datos! Los empujes anteriores se pierden y no se entregan a través del método delegado, lo que resulta en una pérdida de datos.
Entrega cancelada
Registros de consola
default 13:35:05.347078 +0200 dasd DuetActivitySchedulerDaemon com.apple.pushLaunch.net.tequilaapps.daylight:C03A65:[
{name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Must Not Proceed, Score: 0.00}}
], FinalDecision: Must Not Proceed} scoring com.apple.duetactivityscheduler
Problemas de entrega cancelados
Bueno, en este caso, el envío de datos se pierde por completo y nunca se entregó en iOS 11 mientras se entregó correctamente en iOS 10.
ACTUALIZACIÓN 19.09 - iOS 11 GM
También noté que cuando la aplicación está en primer plano y la notificación no se entrega a la aplicación, veo los siguientes registros en la consola:
default 08:28:49.354824 +0200 apsd apsd <private>: Received message for enabled topic ''<private>'' onInterface: NonCellular with payload ''<private>'' with priority 10 for device token: NO courier-oversized com.apple.apsd
fault 08:33:18.128209 +0200 dasd Foundation <NSXPCConnection: 0x151eee460> connection from pid 55: Exception caught during decoding of received message, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
Exception: value for key ''NS.objects'' was of unexpected class ''NSNull''. Allowed classes are ''{(
NSArray,
NSData,
NSString,
NSNumber,
NSDictionary,
NSUUID,
_DASActivity,
NSSet,
_DASFileProtection,
NSDate,
NWParameters,
NWEndpoint
)}''. general com.apple.foundation.xpc
Al escribir esta respuesta, me enfrento exactamente al mismo problema que la respuesta de Bill Dunay .
Mi requisito era recibir notificaciones silenciosas cuando la aplicación está en primer plano y nada cuando la aplicación está en segundo plano / no se está ejecutando. Y mi solución fue esta. No uso insignias, por lo tanto, establecerlo en cero no es un problema para mí.
{
"aps" : {
"badge" : 0,
"sound" : ""
},
"mydata": {
"foo": "bar"
}
}
Tenga en cuenta que deliberadamente no estoy usando "contenido disponible". Configuración que hace que la lógica de optimización de iOS se demore / cancele la entrega de la notificación.
Apple Developer Relations acaba de agregar un comentario a mi radar:
Creemos que este problema se resuelve en la última versión beta de iOS 11.2.
Por favor, pruebe con la última versión beta de iOS. Si aún tiene problemas, actualice su informe de errores con cualquier registro relevante o información que pueda ayudarnos a investigar.
actualmente instalando iOS 11.2 beta: probará el comportamiento de inserción silenciosa
Como solución alternativa, estamos agregando una clave de "notificación" y dentro de un "título" con una cadena vacía como valor. Esto es despertar la devolución de llamada didReceive en el appDelegate.
En mi caso, se usaron notificaciones silenciosas para actualizar la interfaz de usuario después de que se realizó el trabajo en el sitio del servidor, por lo que fue muy difícil tener contenido no relevante en la aplicación. Debido a que nuestra carga útil para notificaciones silenciosas contiene incluso el título y el cuerpo, implemento estos métodos para obtener notificaciones de trabajo en la aplicación activa / inactiva, sin cobrar y con la actualización de la aplicación en segundo plano desactivada e incluso en estado de bajo consumo.
Para que esto funcione, agrego delegado y creo una extensión con el protocolo
UNUserNotificationCenterDelegate
y el
willPresent notification
(iOS 10+), que se activa cada vez con la carga correcta.
Para no mostrar la notificación cuando la aplicación está activa, simplemente complete la llamada con una insignia o sonido.
Terminé con algo como esto
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
// MARK: - Lifecycle
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
}
//this was only method to handle notifications before
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
//process silent notification
completionHandler(UIBackgroundFetchResult.newData)
}
}
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
//proces notification when app is active with `notification.request.content.userInfo`
if UIApplication.shared.applicationState == .active {
completionHandler(.badge)
}else {
completionHandler(.alert)
}
}
}
Y para que funcione estos estados cuando la aplicación está en segundo plano y la notificación silenciosa no llame a mis métodos, recibo notificaciones del centro de notificaciones directamente en
applicationDidBecomeActive
por:
UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in
debugLog(message: "unprocessed notification count: /(notifications.count)")
if notifications.count > 0 {
notifications.forEach({ (notification) in
DispatchQueue.main.async {
//handle `notification.request.content.userInfo`
}
})
}
}
Entonces, las notas de la versión de iOS 11.1 beta 1 dicen
iOS 11.1 beta 1 se acaba de lanzar y mencionan: "Notificaciones Problemas resueltos • Las notificaciones automáticas silenciosas se procesan con más frecuencia. (33278611)
Hice algunas pruebas y parece estar solucionado:
Estado suspendido
Cuando inicio la aplicación en modo suspendido y envío un envío silencioso, la aplicación vuelve a segundo plano y se llama al delegado
didReceiveRemoteNotification:fetchCompletionHandler
.
Estado de primer plano
Del mismo modo, cuando la aplicación está en primer plano y se envía un envío silencioso, el delegado parece ser llamado como se esperaba. Esto no funcionaba al azar en versiones anteriores de iOS 11, así que lo confirmaré después de más pruebas.
He recibido el mismo problema para algunas notificaciones (no necesariamente en silencio).
Después de revisar todas las actualizaciones y respuestas, puedo agregar dos actualizaciones que pueden ayudar:
-
Descubrí que acceder
UIApplication.shared.isRegisteredForRemoteNotifications
métodoUIApplication.shared.isRegisteredForRemoteNotifications
mientras recibo una notificación hace que la aplicación se bloquee sin informar nada a Xcode. Compruebe si está ejecutando algún código después de recibir la notificación que accede al método. ( isRegisteredForRemoteNotifications bloqueando la interfaz de usuario con semaphore_wait_trap ).-
Descubrí que tenía un error de análisis de notificaciones push en la consola debido a que
"title-loc-args" : [3333]
no aceptaba 3333 literalmente pero lo aceptaba como una cadena"title-loc-args" : ["3333"]
. Esto hizo que toda mi interfaz se bloqueara después de acceder al método anterior, solo en iOS 11, funciona en iOS 12.
-
Descubrí que tenía un error de análisis de notificaciones push en la consola debido a que
-
También descubrí que, con exactamente el mismo código, funciona sin ningún problema en iOS 12.0 (16A5366a) . Pero en iOS 11 está sucediendo.
Las notas de la versión beta de iOS 11.1 incluyen: Notificaciones Problemas resueltos Las notificaciones automáticas silenciosas se procesan con mayor frecuencia. (33278611)
Parece un nuevo comportamiento de iOS 11. iOS 11 beta 10 proporciona algunos registros descriptivos sobre este problema:
default 23:18:51.806011 +0200 dasd com.apple.pushLaunch.com.acme.Acme:F7E7D0:[
{name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Can Proceed, Score: 0.50}}
{name: BatteryLevelPolicy, policyWeight: 1.000, response: {Decision: Can Proceed, Score: 0.87, Rationale: [{batteryLevel == 62}]}}
{name: DeviceActivityPolicy, policyWeight: 5.000, response: {Decision: Can Proceed, Score: 0.20}}
] sumScores:52.279483, denominator:81.410000, FinalDecision: Can Proceed FinalScore: 0.642175}
default 23:18:51.806386 +0200 dasd ''com.apple.pushLaunch.com.acme.Acme:F7E7D0'' has compatibility score of 1.000000 with ''com.apple.CFNetwork-cc-111-79:E7272D''. Relaxing scores.
default 23:18:51.806855 +0200 dasd ''com.apple.pushLaunch.com.acme.Acme:F7E7D0'' CurrentScore: 0.642175, ThresholdScore: 0.738454 DecisionToRun:0
Parece que cada envío silencioso se entrega al iOS, pero dasd daemon usa un par de políticas para decidir si el envío silencioso debe enviarse a la aplicación (por ejemplo, nivel de batería). Logré recibir un impulso silencioso ayer por la noche, pero mi iPhone estaba conectado al cargador en ese momento, probablemente el puntaje de BatteryLevelPolicy fue lo suficientemente alto como para recibir ese impulso silencioso.
Apple no proporciona información oficial sobre este comportamiento del lado de iOS, solo hay información sobre la limitación del lado del servidor:
Las notificaciones silenciosas no están destinadas a mantener su aplicación activa en segundo plano, ni a actualizaciones de alta prioridad. Los APN tratan las notificaciones silenciosas como de baja prioridad y pueden limitar su entrega por completo si el número total se vuelve excesivo. Los límites reales son dinámicos y pueden cambiar según las condiciones, pero trate de no enviar más de unas pocas notificaciones por hora.
Mantengo mis dedos cruzados, cambiaron ese comportamiento, porque eso arreglaría mi aplicación :) Por otro lado, este cambio es bueno, una de las muchas cosas que hace que la batería del iPhone dure más que los teléfonos Android.
Por lo tanto, esto es realmente un error en iOS 11 y ahora está solucionado en iOS 11 beta 3. La
application:didReceiveRemoteNotification:fetchCompletionHandler
ahora se llama correctamente cuando se recibe un impulso silencioso tanto en primer plano como en segundo plano.
ACTUALIZAR
No, no está solucionado y todavía está sucediendo en iOS beta 3 y 4
Solo quería agregar mis 2 centavos aquí ya que este problema también me ha afectado y he notado que Apple ha cerrado varios radares sobre este problema diciendo que no podían reproducirse. Una cosa interesante que encontré es que los empujes se entregarán si la aplicación está en segundo plano mientras está conectada al depurador.
Si elimino el depurador, desenchufe mi teléfono, inicie la aplicación y envíe la carga útil silenciosa, veo que la aplicación NO se despierta. Veo en el registro de la consola que el sistema cancela la entrega de la carga útil a mi aplicación.
He enviado un radar con una pequeña aplicación de muestra que reproduce el problema. También he señalado explícitamente en el radar que la persona que trabaja en mi ticket no debe ejecutar la aplicación adjunta al depurador para reproducir el problema. Aquí está el enlace: https://bugreport.apple.com/web/?problemID=34461063
Esperemos que esto cause algún progreso en este tema.
Tuve un problema similar con mi aplicación, hasta iOS 10 recibía notificaciones push y la
application:didReceiveRemoteNotification:fetchCompletionHandler
se llamaba correctamente, pero cuando se actualizaban a iOS 11, las notificaciones push dejaban de funcionar.
El problema con mi código era, a pesar de que estaba usando content-available: 1 y mutable-content: 1 en la carga de notificaciones push, la opción Background Fetch no estaba activada. Pero funcionaba perfectamente hasta iOS 10.
Después de activar la capacidad de recuperación de fondo, está funcionando ahora
iOS 11.1 Beta 2 también contiene
Notifications
Resolved Issues
• Silent push notifications are processed more frequently. (33278611)
en las Notas de la versión: lo probaré ahora.
ACTUALIZACIÓN - 11.10.2017 - iOS 11.1 Beta 2
Después de usar nuestra aplicación durante 2 días en "escenarios del mundo real", parece que hay una mejora real en esta versión de iOS. Con cautela empiezo a creer que esto está arreglado.
iOS 11.4.1, Swift 4
Estaba teniendo problemas con los impulsos silenciosos que no llegaban (de CloudKit) e intenté todo lo que todos han mencionado aquí.
Luego decidí intentar configurar un
alertBody
blanco para mis objetos
CKNotificationInfo()
como este:
let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
info.alertBody = ""
Esto hizo que los empujes se enviaran con una prioridad más alta (pero aún eran empujes silenciosos) y ya no recibí el error en los registros de mi dispositivo de que se ignoraba el empuje.
Espero que ayude a alguien. :)