Reglas de conexión de socket persistente de Android
He estado haciendo algunas pruebas para una solución de notificación push personalizada para dispositivos Android con sockets persistentes. Me gustaría compartir mis descubrimientos y validar los resultados.
Descripción Simple
Las aplicaciones ejecutan un servicio de primer plano y establecen una conexión con el servidor y mantienen esa conexión a través de ping agresivo (intervalo de @ 10 segundos). Si la conexión se detecta como muerta, la aplicación sigue intentando volver a conectarse indefinidamente. El servidor envía notificaciones vía canal dúplex.
- Enviar varios mensajes desde el servidor TCP a cliente (C fuerte a Android)
- Android LocalServerSocket
- ¿Por qué estoy enviando un RST si mi socket está conectado y no cerrado?
- Redes Android
- Cómo configurar el tiempo de espera keepalive en Android?
Ensayo 1:
Pinging is done using a timer at 10 second intervals. Server sends notification every minute. Applications acquires wifi and wake locks. Duration : 8 hours Battery loss : ~14%
Ensayo 2:
Pinging is done using AlarmManager at 10 second intervals. Server sends notification every minute. Application acquires only a wifilock Duration : 8 hours Battery loss : ~7%
Suposiciones: Un paquete de red entrante automáticamente despierta la CPU, por lo tanto, no es necesario un bloqueo de la sesión. El uso de AlarmManager para hacer ping (en lugar de temporizadores) significa que no necesitamos un wakelock.
Quitar ese wakelock realmente parecía ayudar a la batería. Sorprendentemente, el agresivo ping en cualquiera de las soluciones no afectó la vida de la batería tanto como yo hubiera esperado. (Tuvimos muchas otras pruebas, incluyendo una donde la aplicación acaba de celebrar un wifilock y no hizo nada que causó alrededor de 4% a 5% de pérdida de batería en el mismo período)
Puesto que la aplicación pudo enviar con éxito todas las peticiones de ping y recibir todos los mensajes entrantes, creo que mis suposiciones son correctas. Pero me encantaría obtener alguna confirmación de cualquier experto.
Una pregunta más: Si la aplicación estaba en lugar de escuchar las conexiones entrantes. Tendría que tener un wakelock en este caso, ¿correcto? ¿Una conexión entrante no despierta la CPU? No vamos por esta ruta, pero sólo quería confirmar.
También, por favor no recomiende GCM, se ha descartado por la política de la compañía.
Gracias.
- Servidor Android Http y tuberías rotas
- Socket IPv6 en Android
- Cómo escribir un Android SocketServer para escuchar en wifi
- ¿Se pueden realizar llamadas TCP o WebSockets a través de Javascript en dispositivos Android e iOS?
- Android enviar archivos grandes vía socket
- No se pueden obtener los elementos en la herramienta uiautomator cuando la aplicación se ejecuta en el dispositivo
- Escritura de audio en el servidor a través de un socket TCP
- El zócalo se atasca al hacer readLine ()
Dado que ha habido algún interés en esta pregunta y no hay confirmaciones, sólo voy a responder ahora. Ha pasado un tiempo desde que se hicieron las pruebas, y se ha creado una solución de nivel de producción y rigurosamente probada. Eliminar el bloqueo de la vigilia todavía ayudó a la batería y no se encontraron otros problemas como las solicitudes de ping que faltaban o las notificaciones entrantes, por lo que es la única validación que recibí sobre los supuestos mencionados.
Cosas adicionales a tener en cuenta:
-
En el método OnReceive de BroadcastReceiver para la alarma de ping, si no está llamando directamente al socket (desovando un nuevo hilo o intención), tendrá que mantener un bloqueo de la sesión hasta que finalice la petición de ping. Android sostiene un bloqueo de activación hasta que se devuelve OnReceive, después de lo cual es posible (pero raro) que la CPU pueda dormir antes de que finalice el ping.
-
Utilice un bloqueo Wifi de alto rendimiento si las notificaciones son sensibles.
-
Hubo otro problema específico del dispositivo que afectó la solución, se trata aquí .
Actualizar
Se presentó en el siguiente número con Android 5.1: Android Issue
Actualización 2
Necesita codificar alrededor del modo Doze para Android 6.0: Doze Mode