GcmListenerService no se llama Cuando la aplicación está en segundo plano

GcmListenerService no se llama cuando la aplicación está en segundo plano o cuando el teléfono está bloqueado o en modo de suspensión pero se dispara la notificación. Cómo se llamará esto cuando App está en primer plano su funcionamiento ideal. El código para GcmListenerService está siguiendo

public class MyGcmListenerService extends GcmListenerService { private static final String TAG = "MyGcmListenerService"; LocalDataBaseManager mDbManager; String message; Random randomNumber; long ID; /** * Called when message is received. * * @param from SenderID of the sender. * @param data Data bundle containing message data as key/value pairs. * For Set of keys use data.keySet(). */ // [START receive_message] @Override public void onMessageReceived(String from, Bundle data) { String message ; String title; // ID = Utils.getIDForPush("pushId",this); // if(ID == 0){ // ID = 1; // }else { // ID += 1; // } // Utils.saveIDForPush("pushId",ID,this); Bundle bundle = data.getBundle("notification"); if(bundle!= null){ message = bundle.getString("body"); title = bundle.getString("title"); Log.d(TAG, "From: " + from); Log.d(TAG, "Message: " + message);} else { message =""; title = "NCMS"; } mDbManager = LocalDataBaseManager.getInstance(this); if (from.startsWith("/topics/")) { Calendar c = Calendar.getInstance(); SimpleDateFormat s = new SimpleDateFormat("ddMMyyyyhhmmss"); String format = s.format(new Date()); ID = Long.parseLong(format); String date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ENGLISH).format(new Date()); Warnings warnings = new Warnings(); warnings.setWARNING_ID(ID); warnings.setWARNING_EN(message); warnings.setWARNING_AR(message); warnings.setSTART_DATE_TIME(date); warnings.setNotification_type(String.valueOf(Constant.NotificationType.PUSH)); warnings.setSEVERITY(""); warnings.setEND_DATE_TIME(""); warnings.setUPDATE_NO(""); mDbManager.insertNotificationInfo(warnings); // message received from some topic. } else { // normal downstream message. } // [START_EXCLUDE] /** * Production applications would usually process the message here. * Eg: - Syncing with server. * - Store message in local database. * - Update UI. */ /** * In some cases it may be useful to show a notification indicating to the user * that a message was received. */ // KeyguardManager km = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE); // boolean locked = km.inKeyguardRestrictedInputMode(); // // String release = android.os.Build.VERSION.RELEASE; // // // if (Integer.parseInt(String.valueOf(release.charAt(0))) < 5 && locked) { // // this.stopService(new Intent(this, NotificationService.class)); // Intent serviceIntent = new Intent(this, NotificationService.class); // this.startService(serviceIntent); // // } sendNotification(title,message); // [END_EXCLUDE] } // [END receive_message] /** * Create and show a simple notification containing the received GCM message. * * @param message GCM message received. */ private void sendNotification(String title,String message) { Intent intent = new Intent(this, MainActivity.class); intent.putExtra("message",message); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT); Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ncms_launcher) .setContentTitle(title) .setContentText(message) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()); } } 

La información del manifiesto para este servicio es la siguiente

  <service android:name=".gcm.MyGcmListenerService" android:exported="false" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> </intent-filter> </service> 

Lo que me falta aquí.

Parece que el corazón de este problema es en realidad un problema del lado del servidor. Si el servidor está enviando mensajes de notificación , onMessageReceived no se llamará si la aplicación está en segundo plano. El servidor debería estar enviando mensajes de datos .

GCM Docs discutir la diferencia.

Básicamente, la carga útil del mensaje debe tener una clave de data como

 { "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...", "data" : { "Nick" : "Mario", "body" : "great match!", "Room" : "PortugalVSDenmark" }, } 

Y NO una clave de notificación como

 { "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...", "notification" : { "body" : "great match!", "title" : "Portugal vs. Denmark", "icon" : "myicon" } } 

Más específicamente, los documentos de GCM indican que los mensajes enviados, incluidos los datos y las cargas útiles de notificación , se tratarán de forma diferente dependiendo de si la aplicación está en primer plano o en segundo plano:

El comportamiento de la aplicación cuando se reciben mensajes que incluyen tanto la notificación como la carga de datos depende de si la aplicación está en segundo plano o en primer plano, si está activa o no en el momento de la recepción.

  • Cuando en segundo plano, las aplicaciones reciben la carga útil de notificación en la bandeja de notificación y sólo manejan la carga útil de datos cuando el usuario hace tapping en la notificación.
  • Cuando en primer plano, su aplicación recibe un paquete con las dos cargas disponibles.

Este hilo de github también tiene una buena explicación:

Así que hay dos tipos de mensajes GCM:

  • Mensajes de notificación: están destinados a generar una notificación sin procesamiento intermedio por la aplicación. Ellos solo golpean enMessageReceived si la aplicación se está ejecutando.

  • Mensajes de datos: están destinados a pasar silenciosamente datos al servicio de mensajería de la aplicación. Ellos golpean enMessageReceived incluso si la aplicación está en segundo plano. El servicio puede entonces elegir generar una notificación utilizando las API de notificación del sistema normales, o puede optar por manejar el mensaje silenciosamente.

El problema que estaba enfrentando fue cuando la aplicación está en segundo plano o la fuerza cerrada, entonces la notificación se disparó, pero no a través de GcmListenService, sino a través de GCMReceiver Así que ampliado GCMReceiver y lo hizo algo así con esto cuando la aplicación está en primer plano o en el fondo o la fuerza muerta. Se llamará GCMListenerService después de la modificación como sigue

  public class MyGcmListenerService extends GcmListenerService { private static final String TAG = "MyGcmListenerService"; LocalDataBaseManager mDbManager; String message; Random randomNumber; long ID; /** * Called when message is received. * * @param from SenderID of the sender. * @param data Data bundle containing message data as key/value pairs. * For Set of keys use data.keySet(). */ // [START receive_message] @Override public void onMessageReceived(String from, Bundle data) { String message ; String title; // ID = Utils.getIDForPush("pushId",this); // if(ID == 0){ // ID = 1; // }else { // ID += 1; // } // Utils.saveIDForPush("pushId",ID,this); Bundle bundle = data.getBundle("notification"); if(bundle!= null){ message = bundle.getString("body"); title = bundle.getString("title"); Log.d(TAG, "From: " + from); Log.d(TAG, "Message: " + message);} else { message =""; title = "NCMS"; } mDbManager = LocalDataBaseManager.getInstance(this); if (from.startsWith("/topics/")) { Calendar c = Calendar.getInstance(); SimpleDateFormat s = new SimpleDateFormat("ddMMyyyyhhmmss"); String format = s.format(new Date()); ID = Long.parseLong(format); String date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ENGLISH).format(new Date()); Warnings warnings = new Warnings(); warnings.setWARNING_ID(ID); warnings.setWARNING_EN(message); warnings.setWARNING_AR(message); warnings.setSTART_DATE_TIME(date); warnings.setNotification_type(String.valueOf(Constant.NotificationType.PUSH)); warnings.setSEVERITY(""); warnings.setEND_DATE_TIME(""); warnings.setUPDATE_NO(""); mDbManager.insertNotificationInfo(warnings); // message received from some topic. } else { // normal downstream message. } // [START_EXCLUDE] /** * Production applications would usually process the message here. * Eg: - Syncing with server. * - Store message in local database. * - Update UI. */ /** * In some cases it may be useful to show a notification indicating to the user * that a message was received. */ // KeyguardManager km = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE); // boolean locked = km.inKeyguardRestrictedInputMode(); // // String release = android.os.Build.VERSION.RELEASE; // // // if (Integer.parseInt(String.valueOf(release.charAt(0))) < 5 && locked) { // // this.stopService(new Intent(this, NotificationService.class)); // Intent serviceIntent = new Intent(this, NotificationService.class); // this.startService(serviceIntent); // // } sendNotification(title,message); // [END_EXCLUDE] } // [END receive_message] /** * Create and show a simple notification containing the received GCM message. * * @param message GCM message received. */ private void sendNotification(String title,String message) { Intent intent = new Intent(this, MainActivity.class); intent.putExtra("message",message); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT); Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ncms_launcher) .setContentTitle(title) .setContentText(message) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()); } } 

Y el receptor GCM es como sigue

  public class GcmBroadcastReceiver extends GcmReceiver { LocalDataBaseManager mDbManager; @Override public void onReceive(Context context, Intent intent) { mDbManager = LocalDataBaseManager.getInstance(context); Bundle bundle = intent.getExtras(); bundle.keySet(); Set<String> keySet = bundle.keySet(); if(keySet != null && keySet.isEmpty() == false) { Iterator<String> it = keySet.iterator(); int i = 0; while(it.hasNext()){ String key = it.next(); String desc = bundle.getString(key); Log.d("BroadCast Values",key +" "+desc); } } Log.d("", "In Receive Method of Broadcast Receiver"); if (bundle != null && bundle.containsKey("gcm.notification.body")) { String message = bundle.getString("gcm.notification.body",""); Long ID = new Date().getTime(); String date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ENGLISH).format(new Date()); Warnings warnings = new Warnings(); warnings.setWARNING_ID(ID); warnings.setWARNING_EN(message); warnings.setWARNING_AR(message); warnings.setSTART_DATE_TIME(date); warnings.setNotification_type(String.valueOf(Constant.NotificationType.PUSH)); warnings.setSEVERITY(""); warnings.setEND_DATE_TIME(""); warnings.setUPDATE_NO(""); mDbManager.insertNotificationInfo(warnings); // message received from some topic. } super.onReceive(context, intent); // ComponentName cn = new ComponentName(context.getPackageName(), RegistrationIntentService.class.getName()); // startWakefulService(context, intent.setComponent(cn)); // setResultCode(Activity.RESULT_OK); } } 

Manifest cambios para GCMReceiver sigue

  <receiver android:name=".gcm.GcmBroadcastReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="com.uae.ncms" /> </intent-filter> </receiver> <service android:name=".gcm.MyGcmListenerService" android:exported="false" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> </intent-filter> </service> 
  • Confusión de registro Android GCM
  • Registro de Google Cloud Messaging AUTHENTICATION_FAILED
  • Notificación push de Android GCM para aplicaciones de localización
  • Mensaje de error de PHP GCM MismatchSenderId
  • No se pudo resolver: com.google.android.gms: play-services-measurement: 9.0.2
  • Enviar notificaciones en Android mediante Google App Engine
  • Hacer dispositivo Android como servidor para enviar mensajes a GCM directamente
  • Anulación de registro de GCM causando que la aplicación se bloquee
  • Cómo mantener la escucha de notificaciones push en Android en segundo plano
  • Java.io.IOException: SERVICE_NOT_AVAILABLE en el cliente de GCM
  • ¿Cambia el Id de registro cuando el usuario actualiza o reinstala la aplicación
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.