Google Cloud Messaging: los mensajes se reciben al instante o con un gran retraso

Estoy usando la mensajería en la nube de Google en mi proyecto de último año para la universidad. Todo funciona bien, pero he tenido algunos problemas con GCM. Con bastante regularidad, los mensajes se entregan casi instantáneamente o con un gran retraso.

Lo he leído y realmente no creo que se aplique en este caso:

GCM por lo general entrega mensajes inmediatamente después de que se envían. Sin embargo, esto no siempre es posible. Por ejemplo, el dispositivo podría apagarse, desconectarse o no estar disponible. En otros casos, el remitente puede solicitar que los mensajes no se entreguen hasta que el dispositivo se active utilizando el indicador de retraso_mientras_idle. Finalmente, GCM podría retrasar intencionalmente los mensajes para evitar que una aplicación consum recursos excesivos e impacte negativamente la duración de la batería.

En mi proyecto hablamos de un máximo de 5 o 6 mensajes del servidor por minuto. Si GCM se puede utilizar para una aplicación de chat, seguramente no podrían bloquear los mensajes que se envían / ​​reciben a este ritmo. Se ha vuelto bastante molesto y será bastante malo si mi proyecto solo funciona el 50% del tiempo …

Aquí está mi código para el mensaje que envía el servidor:

@Override public void run() { Message.Builder messageBuilder = new Message.Builder().delayWhileIdle(false); Gson gson = new Gson(); messageBuilder.addData("profile", gson.toJson(profile)); databaseConnection.notifyDevices(messageBuilder.build()); } public void notifyDevices(Message message) { Sender sender = new Sender(xxx); List nameValuePairs = new ArrayList(); nameValuePairs.add(new BasicNameValuePair("message", message.toString())); //LOG System.out.println("Notifying devices with the following message \n \"" +message+ "\""); List deviceIDsList = new ArrayList(); String [] deviceIDArray; //Get devices to notify List deviceList = getDevicesToNotify(); for(JSONDeviceProfile device : deviceList) { deviceIDsList.add(device.getDeviceId()); try { sender.send(message, device.getDeviceId(), 5); } catch (IOException e) { System.out.println("Error sending GCM message!"); e.printStackTrace(); } } } 

Y mi método de onMessage de Android:

 @Override protected void onMessage(Context arg0, Intent intent) { String message = intent.getStringExtra("profile"); Log.d(TAG + "Received Message: ", "Received Message: " + message.toString()); //CALL NEW INTENT WITH PROFILE DETAILS Intent displayProfileIntent = new Intent(arg0, DisplayProfile.class); displayProfileIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); displayProfileIntent.putExtra("message", message); startActivity(displayProfileIntent); /* //generateNotification(arg0, username); handler.post(new Runnable() { @Override public void run() { //Toast.makeText(getApplicationContext(), username, Toast.LENGTH_SHORT).show(); } }); */ } 

Espero que alguien haya tenido un problema similar, solo quiero confirmar que el problema es algo que estoy haciendo o que está fuera de mis manos.

tl; dr Los mensajes GCM llegan de forma instantánea o unos 10 minutos más tarde (la demora suele ser constante).

La parte del marco de GCM en el teléfono del cliente usa una conexión TCP en el puerto 5228. Esta conexión se usa para notificaciones push, pero como cada conexión tcp puede tener tiempo de espera con algunos enrutadores / operadores que aplican políticas estrictas para matar conexiones inactivas de tcp ( tcp tiempo de espera inactivo ).

La mayoría de los enrutadores wifi matan las conexiones inactivas después de 5 minutos, por ejemplo, como el mío.

El marco GCM utiliza un mecanismo de mantener vivo para enviar un paquete de red de latido cada 15 minutos en wifi y cada 28 minutos en 3G. Este keep-alive no siempre es confiable para todos los usuarios.

Abrí el problema en google aquí: https://productforums.google.com/forum/#!category-topic/nexus/connecting-to-networks-and-devices/fslYqYrULto Están de acuerdo en que actualmente hay un problema.

EDITAR (01/01/2014) : actualmente, Google actualizó los intervalos de latido cardíaco a 8 minutos para conexiones wifi y móviles. Es un cambio remoto que afecta a todos los dispositivos Android 2.2+. Esta es una buena mejora para evitar el tiempo de espera de la conexión de inserción tcp. Aún así, si un enrutador wifi mata las conexiones inactivas después de 5 minutos, tendrá un retraso de 3 (8-5) minutos en las notificaciones push (si no tenía otras notificaciones que mantienen viva la conexión)

EDITAR (2016/03/06) : ahora google parece estar probando mis comentarios de hace 2 años, para tener un mecanismo dynamic para determinar el intervalo correcto de latido dependiendo de la red. Actualmente parece un lanzamiento progresivo y solo para wifi como para lo que sé. Así que, basado en el SSID wifi, el algoritmo determina el intervalo de latido correcto para el wifi específico con una especie de refinamiento gradual. ¡Esto suena muy bien! Este es un cambio remoto que afecta a todos los teléfonos Android que tienen Google Play Services.