Cómo gestionar los cambios de la ID de registro en Google Cloud Messaging en Android

En los documentos de Google Cloud Messaging, se indica:

La aplicación de Android debe almacenar este ID para su uso posterior (por ejemplo, para comprobar en onCreate () si ya está registrado). Tenga en cuenta que Google puede actualizar periódicamente el ID de registro, por lo que debe diseñar su aplicación de Android con el entendimiento de que la intención de com.google.android.c2dm.intent.REGISTRATION se puede llamar varias veces. Su aplicación de Android debe ser capaz de responder en consecuencia.

Registro mi dispositivo con el siguiente código:

GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); String regID = gcm.register(senderID); 

La clase GoogleCloudMessaging encapsula el proceso de registro. Entonces, ¿cómo supongo que para manejar com.google.android.c2dm.intent.REGISTRATION desde la manipulación que se realiza internamente por la clase GoogleCloudMessaging?

Esa es una pregunta interesante.

Google te alienta a cambiar al nuevo proceso de registro:

Una aplicación de Android que se ejecuta en un dispositivo móvil se registra para recibir mensajes llamando al registro del método GoogleCloudMessaging (senderID …). Este método registra la aplicación para GCM y devuelve el ID de registro. Este enfoque simplificado reemplaza al anterior proceso de registro de GCM.

La nota que dice que Google may periodically refresh the registration ID sólo aparece en la página que todavía muestra el proceso de registro antiguo, por lo que es posible que esta nota ya no sea relevante.

Si quieres estar a salvo, todavía puedes usar el proceso de registro antiguo. O puede usar el nuevo proceso, pero además tiene el código que maneja la intención de com.google.android.c2dm.intent.REGISTRATION , para asegurarse de que está cubierto si Google decide actualizar el ID de registro.

Dicho esto, nunca experimenté una actualización así, e incluso cuando experimenté un cambio en el ID de registro (normalmente como resultado del envío de una notificación después de desinstalar la aplicación y volver a instalarla), el ID de registro antiguo Trabajado (resultando en una identificación canónica de registro enviada en la respuesta de Google), por lo que no se hizo daño.

EDIT (06.06.2013):

Google cambió su aplicación de demostración para usar la nueva interfaz. Actualizan el ID de registro estableciendo una fecha de caducidad en el valor que la aplicación mantiene localmente. Cuando se inicia la aplicación, cargan su ID de registro almacenado localmente. Si está "caducado" (lo que en la demo significa que fue recibido de GCM hace más de 7 días), llaman gcm.register(senderID) nuevo.

Esto no maneja el hipotético escenario en el que un ID de registro es actualizado por Google para una aplicación que no se ha iniciado durante mucho tiempo. En ese caso, la aplicación no será consciente del cambio, y tampoco el servidor de terceros.

 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mDisplay = (TextView) findViewById(R.id.display); context = getApplicationContext(); regid = getRegistrationId(context); if (regid.length() == 0) { registerBackground(); } gcm = GoogleCloudMessaging.getInstance(this); } /** * Gets the current registration id for application on GCM service. * <p> * If result is empty, the registration has failed. * * @return registration id, or empty string if the registration is not * complete. */ private String getRegistrationId(Context context) { final SharedPreferences prefs = getGCMPreferences(context); String registrationId = prefs.getString(PROPERTY_REG_ID, ""); if (registrationId.length() == 0) { Log.v(TAG, "Registration not found."); return ""; } // check if app was updated; if so, it must clear registration id to // avoid a race condition if GCM sends a message int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE); int currentVersion = getAppVersion(context); if (registeredVersion != currentVersion || isRegistrationExpired()) { Log.v(TAG, "App version changed or registration expired."); return ""; } return registrationId; } /** * Checks if the registration has expired. * * <p>To avoid the scenario where the device sends the registration to the * server but the server loses it, the app developer may choose to re-register * after REGISTRATION_EXPIRY_TIME_MS. * * @return true if the registration has expired. */ private boolean isRegistrationExpired() { final SharedPreferences prefs = getGCMPreferences(context); // checks if the information is not stale long expirationTime = prefs.getLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, -1); return System.currentTimeMillis() > expirationTime; } 

EDIT (08.14.2013):

Google cambió su Demo App de nuevo (hace dos días). Esta vez, eliminaron la lógica que considera que el ID de registro expiró después de 7 días. Ahora solo actualizan el ID de registro cuando se instala una nueva versión de la aplicación.

EDIT (04.24.2014):

En aras de la integridad, aquí están las palabras de Costin Manolache (tomado de aquí ), un desarrollador de Google involucrado en el desarrollo de GCM, sobre el tema:

La actualización periódica nunca ocurrió y la actualización de registro no se incluye en la nueva biblioteca de GCM.

La única causa conocida para el cambio de ID de registro es el antiguo error de las aplicaciones que no se registran automáticamente si reciben un mensaje mientras se actualizan. Hasta que este error sea fijo, las aplicaciones todavía necesitan llamar a register () después de la actualización, y hasta ahora el ID de registro puede cambiar en este caso. Llamar unregister () explícitamente normalmente también cambia el ID de registro.

La sugerencia / solución es generar su propio identificador aleatorio, guardado como una preferencia compartida por ejemplo. En cada actualización de la aplicación, puede cargar el identificador y el ID de registro potencialmente nuevo. Esto también puede ayudar a rastrear y depurar los cambios de actualización y registro en el servidor.

Esto explica la implementación actual de la aplicación oficial de demostración GCM. com.google.android.c2dm.intent.REGISTRATION nunca debe ser manejado cuando se utiliza la clase GoogleCloudMessaging para registrarse.

Al leer la nueva API de InstanceID, encontré más información sobre cuándo podría cambiar el token:

Su aplicación puede solicitar tokens del servicio de ID de instancia según sea necesario mediante el método getToken () y, como InstanceID, su aplicación también puede almacenar tokens en su propio servidor. Todos los tokens emitidos en tu aplicación pertenecen al InstanceID de la aplicación.

Los tokens son únicos y seguros, pero es posible que su aplicación o el servicio de ID de instancia tengan que actualizar tokens en caso de un problema de seguridad o cuando un usuario desinstale y reinstale su aplicación durante la restauración del dispositivo . Su aplicación debe implementar un listener para responder a solicitudes de actualización de token del servicio de ID de instancia.

Más detalles:

El servicio ID de instancia inicia devoluciones de llamada periódicamente (por ejemplo, cada 6 meses), solicitando que la aplicación actualice sus tokens. También puede iniciar devoluciones de llamada cuando:

  • Hay problemas de seguridad; Por ejemplo, problemas de SSL o de plataforma.
  • La información del dispositivo ya no es válida; Por ejemplo, copia de seguridad y restauración.
  • El servicio de ID de instancia se ve afectado de otro modo.

Fuentes:

https://developers.google.com/instance-id/

https://developers.google.com/instance-id/guides/android-implementation

Después de fregar a través de toneladas de respuestas engañosas a través de la red, incluyendo SO, el único lugar que encontré una respuesta completa fue como señaló la respuesta de Eran y aquí :

Mientras que la actualización automática de registro podría o no podría haber ocurrido, google describe un algoritmo simiple para manejar los canocical_ids analizando una respuesta exitosa:

 If the value of failure and canonical_ids is 0, it's not necessary to parse the remainder of the response. Otherwise, we recommend that you iterate through the results field and do the following for each object in that list: If message_id is set, check for registration_id: If registration_id is set, replace the original ID with the new value (canonical ID) in your server database. Note that the original ID is not part of the result, so you need to obtain it from the list of code>registration_ids passed in the request (using the same index). Otherwise, get the value of error: If it is Unavailable, you could retry to send it in another request. If it is NotRegistered, you should remove the registration ID from your server database because the application was uninstalled from the device or it does not have a broadcast receiver configured to receive com.google.android.c2dm.intent.RECEIVE intents. Otherwise, there is something wrong in the registration ID passed in the request; it is probably a non-recoverable error that will also require removing the registration from the server database. See Interpreting an error response for all possible error values. 

Desde el enlace mencionado anteriormente.

  • Lados negativos de C2dM
  • ¿Es posible utilizar GCM sin la cuenta de Google y Google Play Services en el dispositivo?
  • Mensajes de Android - Desarrollo vs distribución
  • ¿Está lista la producción de GCM? ¿Deberíamos empezar a usarlo ahora?
  • Notificaciones Push utilizando el servidor Rails
  • Android: Notificación de prueba en línea (Google Cloud Messaging)
  • Push notificación de UrbanAirship no funciona con servidor en vivo (es decir, con la clave de producción) en android
  • Notificación Push de Android C2DM
  • Cómo anular onPushReceive () de ParsePushBroadcastReceiver?
  • PHP del servidor GCM - Error 401 no autorizado
  • Enviar notificación de carga con nodo-gcm al dispositivo android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.