Algunos dispositivos no reciben notifications de Apple Push

Utilizo el formatting de notificación mejorada de iOS de Apple para enviar notifications push de forma masiva y utilizando la solución PHP descrita en esta publicación: https://stackoverflow.com/a/10059000/300129

La experiencia en este punto es que cuando envío una notificación de inserción, algunos dispositivos reciben el post y algunos dispositivos no lo están. Los resultados son inconsistentes. A veces, el dispositivo X recibirá una notificación y, a veces, el dispositivo X no. Estoy anotando todo y no recibo ninguna respuesta de error.

Cualquier pensamiento sobre lo que está sucediendo sería muy útil.

La solución en la respuesta a la que está vinculado tiene un problema. Intenta leer la respuesta de error después de enviar cada post, pero la lectura regresa inmediatamente y no espera a que una respuesta esté disponible. Si bien esto es más eficiente que esperar una respuesta de error potencial para milisegundos de X después de cada post, es posible que se pierda la respuesta de error y la connection puede ser eliminada por Apple sin que se haya producido ningún error.

Si bien no puedo darte un código para resolver tu problema, te doy algunos consejos.

Aquí está la lógica que debe usar (de acuerdo con Apple), pero no he logrado que funcione de manera confiable (al less no en mi implementación de Java):

Empuje el performance de la notificación y la comprobación de errores

Si ve un performance inferior a 9,000 notifications por segundo, su server podría beneficiarse de una lógica mejorada de event handling errores.

A continuación, se explica cómo verificar si hay errores al usar la interfaz binaria mejorada. Sigue escribiendo hasta que falle una escritura. Si la transmisión está list para volver a escribir, vuelva a enviar la notificación y continúe. Si la transmisión no está list para escribir, vea si la transmisión está disponible para leer.

Si es así, lea todo lo disponible en la transmisión. Si devuelve cero bytes, la connection se cerró debido a un error como un byte de command no válido u otro error de análisis. Si recupera seis bytes, es una respuesta de error que puede verificar el código de respuesta y el ID de la notificación que provocó el error. Deberá enviar todas las notifications posteriores a esa.

Una vez que todo ha sido enviado, haga una última comprobación de una respuesta de error.

Puede demorar un time hasta que la connection perdida salga de APN a su server solo por la latencia normal. Es posible enviar más de 500 notifications antes de que se produzca un error en la escritura debido a que se ha eliminado la connection. Alnetworkingedor de 1,700 escrituras de notifications pueden fallar solo porque la tubería está llena, por lo que solo vuelva a intentarlo en ese caso una vez que la secuencia esté list para volver a escribirse.

Ahora, aquí es donde los intercambios se vuelven interesantes. Puedes comprobar si hay una respuesta de error después de cada escritura, y verás el error de inmediato. Pero esto provoca un gran aumento en el time que lleva enviar un lote de notifications.

Los tokens de dispositivo deberían ser válidos casi todos si los ha capturado correctamente y los envía al entorno correcto. Por lo tanto, tiene sentido optimizar los supuestos de fallas. Obtendrá mucho mejor performance si espera que falle la escritura o que se complete el lote antes de search una respuesta de error, incluso contando la hora de enviar nuevamente las notifications rechazadas.

Nada de esto es realmente específico para los APN, se aplica a la mayoría de los progtwigs de nivel de socket.

Si su herramienta de desarrollo de elección admite múltiples subprocesss o comunicación entre processs, puede tener un subprocess o process esperando una respuesta de error todo el time y dejar que el subprocess de envío principal o el process sepa cuándo debe abandonar y volver a intentarlo.

Esto se toma de la nota técnica de Apple: Solución de problemas de notifications automáticas .

No sé cómo se detecta en PHP que la escritura falló, pero cuando lo hace, debe intentar escribir la notificación fallida una vez más, y si vuelve a fallar, intente leer la respuesta de error y cierre la connection.

Si logra leer la respuesta de error, sabrá qué notificación falló y sabrá cuál es el tipo de error (el error más probable es 8: token de dispositivo no válido). El código en la respuesta a la que te referiste no hace nada después de identificar ese error. Si después de escribir 100 posts obtiene una respuesta de error para el post 80, debe volver a enviar los posts 81 a 100, ya que Apple nunca los recibió. En mi caso (server Java), no siempre consigo leer la respuesta de error (a veces me sale un error al intentar leer la respuesta del socket). En ese caso, solo puedo avanzar y enviar las siguientes notifications (y no tengo forma de saber qué notifications recibieron realmente Apple). Es por eso que es importante mantener su database limpia de tokens no válidos.

Si mantiene su database limpia (es decir, almacene en él solo tokens de dispositivo que Apple envió a su aplicación y todos pertenecen al mismo entorno de inserción, sandbox o producción), no debería encontrar ningún tokens de dispositivo no válido.

Encontré un problema similar al tuyo al implementar el lado del server de notifications push en Java. No pude get de manera confiable todas las respuestas de error devueltas por Apple.

Descubrí que en Java hay una manera de deshabilitar el algorithm de TCP Nagle, que provoca el almacenamiento en búfer de múltiples posts antes de enviarlos en un lote a Apple. Aunque Apple nos anima a utilizar el algorithm de Nagle (por razones de performance), descubrí que cuando lo deshabilito y luego bash leer la respuesta de Apple después de cada post que les envío, consigo recibir el 100% de las respuestas de error (I lo verifiqué escribiendo un process que simulaba el server APNS).

Deshabilitando el algorithm de Nagle y enviando las notifications una a una, lentamente y tratando de leer la respuesta de error después de cada post, puede ubicar todas las señales no válidas en su database y eliminarlas. Una vez que sepa que su DB está limpio, puede habilitar el algorithm de Nagle y reanudar el envío de notifications rápidamente sin molestarse en leer las respuestas de error de Apple. Entonces, cada vez que reciba un error al escribir un post en el zócalo, simplemente puede crear un zócalo nuevo e intentar nuevamente enviar solo el último post.

No hay garantía de que las notifications push se entregarán realmente, incluso si el server APNS las aceptó.

En lo que respecta a su server, las notifications push son fire-and-forget; no hay forma de saber cuál es el estado de una notificación después de que lo haya enviado a APNS . El time de entrega también puede variar, desde segundos hasta media hora.
Además, es probable que el iPhone del usuario no pueda recibir notifications push todo el time. Podrían estar en una networking Wi-Fi que no permite conexiones a APNS porque los puertos requeridos están bloqueados. O el teléfono podría estar apagado.

APNS intentará entregar la última notificación que recibió para ese dispositivo cuando vuelva a estar en línea , pero solo intentará por un time limitado. Una vez que se agote, la notificación de inserción se perderá para siempre.

También he experimentado este problema en mi aplicación varias. El motivo de algunos dispositivos que no reciben las notifications push puede ser:

  • Uso del server APNS de sandbox con certificate APNS de producción. -> Verifícalo
  • Perfiles provisionales de desarrollo y producción instalados en el dispositivo. -> Retire ambos provisionales y luego tiene que esperar por lo less 24 horas para que la manzana también quite el token del dispositivo de su server.

En mi caso, durante el desarrollo, algunos APN donde no se reciben en un dispositivo (estaba probando con PushMeBaby ).

Eliminé de mi dispositivo todos los perfiles de aprovisionamiento anteriores relacionados con mi proyecto, y desde ese momento todo salió bien. Para hacer eso, ve a Configuración> Perfiles.

Tal vez tuve algún tipo de conflicto con los perfiles ya que el proyecto en el que estoy trabajando ha cambiado el ID del package y los perfiles de aprovisionamiento desde el momento.