Implementación básica de Android GCM

ACTUALIZACIÓN: arreglé los problemas en el código a continuación, por lo que esto hace un buen ejemplo básico de trabajo de cómo usar GCM


Por lo tanto, estoy tratando de implementar Android GCM en mi aplicación. Estas son las partes relevantes que he añadido al manifiesto:

 <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="20" /> <permission android:name=".permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name=".permission.C2D_MESSAGE" /> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.GET_ACCOUNTS"/> 

 <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="com.badbob.app.gmctestapp" /> </intent-filter> </receiver> <service android:name=".GCMIntentService" /> 

He añadido el siguiente código al onCreate de mi actividad principal:

  GCMRegistrar.checkDevice( this ); GCMRegistrar.checkManifest( this ); final String regId = GCMRegistrar.getRegistrationId( this ); if( regId.equals( "" ) ) { GCMRegistrar.register( this, GCM_SENDER_ID ); } else { Log.v( LOG_TAG, "Already registered" ); } 

También he creado la clase GCMIntenetService así:

 public class GCMIntentService extends GCMBaseIntentService { private static final String LOG_TAG = "GetAClue::GCMIntentService"; public GCMIntentService() { super( GCM_SENDER_ID ); // TODO Auto-generated constructor stub Log.i( LOG_TAG, "GCMIntentService constructor called" ); } @Override protected void onError( Context arg0, String errorId ) { // TODO Auto-generated method stub Log.i( LOG_TAG, "GCMIntentService onError called: " + errorId ); } @Override protected void onMessage( Context arg0, Intent intent ) { // TODO Auto-generated method stub Log.i( LOG_TAG, "GCMIntentService onMessage called" ); Log.i( LOG_TAG, "Message is: " + intent.getStringExtra( "message" ) ); } @Override protected void onRegistered( Context arg0, String registrationId ) { // TODO Auto-generated method stub Log.i( LOG_TAG, "GCMIntentService onRegistered called" ); Log.i( LOG_TAG, "Registration id is: " + registrationId ); } @Override protected void onUnregistered( Context arg0, String registrationId ) { // TODO Auto-generated method stub Log.i( LOG_TAG, "GCMIntentService onUnregistered called" ); Log.i( LOG_TAG, "Registration id is: " + registrationId ); } } 

Cuando corro esto obtengo esto en LogCat :

 07-11 11:28:46.340: V/GCMRegistrar(27435): Registering receiver 07-11 11:28:46.370: D/GCMRegistrar(27435): resetting backoff for com.badbob.app.getacluebeta 07-11 11:28:46.380: V/GCMRegistrar(27435): Registering app com.badbob.app.getacluebeta of senders 128205395388 

De lo que he recogido de otros puestos debo obtener una identificación de registro en LogCat pero no onRegistered() en GCMIntentService nunca se GCMIntentService lo que estoy haciendo mal?

Esto es incorrecto

 protected GCMIntentService( String senderId ) { super(senderId);} 

Como se indica en la documentación. Debe declarar un constructor PUBLIC, NO ARGUMENT para GCMIntentService. De lo contrario, el GCMIntentService no puede ser instanciado correctamente por servicios de intención de fondo.

 public GCMIntentService(){ super(senderID);} 

El senderID puede ser una cadena constante codificada dura ya que ya no cambiará con el nuevo GCM. También es muy importante que use el senderID correcto. 24 horas es lo suficientemente largo para el suyo para estar activo por lo que si mi solución anterior no funciona, está utilizando el incorrecto senderID. Todo lo demás se ve muy bien.

El senderID se encuentra en la URL de su navegador web cuando está navegando por la página de acceso a la API de Google. Haga clic en GCM y un número de 12 dígitos estará presente en la URL del navegador. Esa es la clave correcta para usar. NO es la clave del API. Que se utiliza en el lado del servidor de aplicaciones.

También tuve este insecto ANNOYing, hasta ahora. El problema era que declaré el intentservice dentro de otro paquete … incluso si declaré el nombre en el manifiesto android y ninguna excepción classnotfound había sido lugar … no se pudo encontrar ningún error … así que me aseguré de que el Intentservice está en el paquete raíz.

Creo que tienes algunos problemas en el código.

Debe hacer el registro de su propio receptor de difusión en el archivo de manifiesto y ese receptor activará el <service android:name=".GCMIntentService" /> .

Por lo tanto, debes hacer algo como lo que escribo a continuación.

  • El receptor debe ser declarado como:

     <receiver android:name="your.package.name.YourBroadCastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> </intent-filter> 

  • Su receptor de difusión que iniciará el servicio.

     public class YourBroadCastReceiver extends BroadcastReceiver { @Override public final void onReceive(Context context, Intent intent) { GCMIntentService .runIntentInService(context, intent); setResult(Activity.RESULT_OK, null, null); } } 

Le aconsejo que eche un vistazo a la documentación oficial de GCM donde puede encontrar un buen ejemplo.

Y … no olvides activar el servicio de mensajería de Google Cloud en la página principal de la Consola de API de Google.

¡Déjeme saber si ayuda!

Aquí he escrito algunos pasos para cómo obtener RegID y notificación a partir de cero

  1. Crear / registrar la aplicación en Google Cloud
  2. Configuración de Cloud SDK con desarrollo
  3. Configurar el proyecto para GCM
  4. Obtener el ID de registro del dispositivo
  5. Enviar notificaciones push
  6. Recibir Notificaciones Push

Puede encontrar el tutorial completo debajo del enlace URL

Introducción a la Notificación Push de Android: el último mensaje de Google Cloud Messaging (GCM) – tutorial completo paso a paso

Introduzca aquí la descripción de la imagen

Codificar código para obtener el ID de registro (Token de dispositivo para notificación de emisión).

Configurar el proyecto para GCM


Actualizar el archivo AndroidManifest

Para habilitar GCM en nuestro proyecto necesitamos agregar pocos permisos en nuestro archivo de manifiesto. Vaya a AndroidManifest.xml y agregue debajo de código. Agregar permiso

 <uses-permission android:name="android.permission.INTERNET”/> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name=“.permission.RECEIVE" /> <uses-permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE" /> <permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE" android:protectionLevel="signature" /> 

Añadir declaración de GCM Broadcast Receiver

Agregue declaración GCM Broadcast Receiver en su etiqueta de aplicación

 <application <receiver android:name=".GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" ]]> <intent-filter]]> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="" /> </intent-filter]]> </receiver]]> <application/> 

Añadir declaración de GCM Servie

 <application <service android:name=".GcmIntentService" /> <application/> 

Obtener ID de registro (Token de dispositivo para notificación de empuje)

Ahora vaya a su Actividad de Lanzamiento / Splash

Agregar constantes y variables de clase

 private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000; public static final String EXTRA_MESSAGE = "message"; public static final String PROPERTY_REG_ID = "registration_id"; private static final String PROPERTY_APP_VERSION = "appVersion"; private final static String TAG = "LaunchActivity"; protected String SENDER_ID = "Your_sender_id"; private GoogleCloudMessaging gcm =null; private String regid = null; private Context context= null; 

Actualización de métodos OnCreate y OnResume

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_launch); context = getApplicationContext(); if (checkPlayServices()) { gcm = GoogleCloudMessaging.getInstance(this); regid = getRegistrationId(context); if (regid.isEmpty()) { registerInBackground(); } else { Log.d(TAG, "No valid Google Play Services APK found."); } } } @Override protected void onResume() { super.onResume(); checkPlayServices(); } # Implement GCM Required methods (Add below methods in LaunchActivity) private boolean checkPlayServices() { int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); if (resultCode != ConnectionResult.SUCCESS) { if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) { GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show(); } else { Log.d(TAG, "This device is not supported - Google Play Services."); finish(); } return false; } return true; } private String getRegistrationId(Context context) { final SharedPreferences prefs = getGCMPreferences(context); String registrationId = prefs.getString(PROPERTY_REG_ID, ""); if (registrationId.isEmpty()) { Log.d(TAG, "Registration ID not found."); return ""; } int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE); int currentVersion = getAppVersion(context); if (registeredVersion != currentVersion) { Log.d(TAG, "App version changed."); return ""; } return registrationId; } private SharedPreferences getGCMPreferences(Context context) { return getSharedPreferences(LaunchActivity.class.getSimpleName(), Context.MODE_PRIVATE); } private static int getAppVersion(Context context) { try { PackageInfo packageInfo = context.getPackageManager() .getPackageInfo(context.getPackageName(), 0); return packageInfo.versionCode; } catch (NameNotFoundException e) { throw new RuntimeException("Could not get package name: " + e); } } private void registerInBackground() { new AsyncTask() { Override protected Object doInBackground(Object... params) { String msg = ""; try { if (gcm == null) { gcm = GoogleCloudMessaging.getInstance(context); } regid = gcm.register(SENDER_ID); Log.d(TAG, "########################################"); Log.d(TAG, "Current Device's Registration ID is: "+msg); } catch (IOException ex) { msg = "Error :" + ex.getMessage(); } return null; } protected void onPostExecute(Object result) { //to do here }; }.execute(null, null, null); } 

Nota : por favor, guarde REGISTRATION_KEY, es importante para el envío de mensaje PN a GCM también mantener en la mía esto será único para todos los dispositivos, utilizando este sólo GCM enviará Notificación Push.

Recibir Notificaciones Push

Añadir clase de receptor de difusión GCM

Como ya hemos declarado "GcmBroadcastReceiver.java" en nuestro archivo de manifiesto, así que permite crear esta clase actualizar código de la clase del receptor de esta manera

 public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName()); startWakefulService(context, (intent.setComponent(comp))); setResultCode(Activity.RESULT_OK); Toast.makeText(context, “wow!! received new push notification", Toast.LENGTH_LONG).show(); } } 

Agregar clase de servicio GCM

Como ya hemos declarado "GcmBroadcastReceiver.java" en nuestro archivo de manifiesto, así que permite crear esta clase actualizar código de la clase del receptor de esta manera

 public class GcmIntentService extends IntentService { public static final int NOTIFICATION_ID = 1; private NotificationManager mNotificationManager; private final static String TAG = "GcmIntentService"; public GcmIntentService() { super("GcmIntentService"); } @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); Log.d(TAG, "Notification Data Json :" + extras.getString("message")); GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); String messageType = gcm.getMessageType(intent); if (!extras.isEmpty()) { if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR .equals(messageType)) { sendNotification("Send error: " + extras.toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED .equals(messageType)) { sendNotification("Deleted messages on server: " + extras.toString()); // If it's a regular GCM message, do some work. } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE .equals(messageType)) { // This loop represents the service doing some work. for (int i = 0; i < 5; i++) { Log.d(TAG," Working... " + (i + 1) + "/5 @ " + SystemClock.elapsedRealtime()); try { Thread.sleep(5000); } catch (InterruptedException e) { } } Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime()); sendNotification(extras.getString("message")); } } // Release the wake lock provided by the WakefulBroadcastReceiver. GcmBroadcastReceiver.completeWakefulIntent(intent); } // Put the message into a notification and post it. // This is just one simple example of what you might choose to do with // a GCM message. private void sendNotification(String msg) { mNotificationManager = (NotificationManager) this .getSystemService(Context.NOTIFICATION_SERVICE); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, LaunchActivity.class), 0); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder( this) .setSmallIcon(R.drawable.icon) .setContentTitle("Ocutag Snap") .setStyle(new NotificationCompat.BigTextStyle().bigText(msg)) .setContentText(msg) .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE); mBuilder.setContentIntent(contentIntent); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } } 

No estoy seguro de si esto está relacionado con su problema específico, sin embargo, estaba experimentando el mismo problema. Todo estaba configurado correctamente, por lo que yo podía decir, pero el manejador onRegistered() nunca fue llamado.

Tenía los métodos de servicio estándar onCreate() , onStart() y onDestroy() como parte de mi clase GCMIntentService. Una vez que los eliminé, el manejador fue llamado, como era de esperar.

Mi suposición es que al anular estos métodos, estaba pasando por alto la inicialización de código necesaria.

Después de leer el post de onCreate() , onDestroy() onCreate() , onDestroy() y los otros métodos de devolución de llamada onXXX () . También, mi GCMIntentService.onRegistered(Context, regId) se llama con el regId .

Gracias ClouDeveloper!

También debe registrarse con su servidor de aplicaciones en la devolución de llamada GCMBaseIntentService.onRegistered () . De lo contrario, no podrá enviar los mensajes de la aplicación.

Realmente debe salir del cliente de demostración GCM de Google, ya que proporciona una muestra de trabajo con todo el código correcto. También tenemos una muestra de trabajo en github: airbop-cliente . Proporciona un ejemplo un poco más completo dado que tiene interacciones de trabajo con un servidor de aplicaciones, que es necesario para una aplicación habilitada para GCM. Funciona con los servidores AirBop (que he ayudado a crear), que son libres hasta 1000 dispositivos.

Si no obtiene respuesta del registro, uno de los motivos principales es que su archivo de manifiesto no está configurado correctamente; en especial, dé el "nombre_paquete" (el nombre del paquete de su aplicación como com.xxx.yyy) en el archivo <permission> y <intent filter> correctamente.

  • En algún momento no recibe notificación push GCM en Mobile
  • Id de registro es nulo de gcm en android 2.3.3, 2.3.5 pero no es nulo y funciona en android 2.3.4, 4.0.4
  • Java.io.IOException: SERVICE_NOT_AVAILABLE en el cliente de GCM
  • Lint se queja de que no se ha traducido la cadena gcm_defaultSenderId
  • GCM Cloud Connection Server - cómo empezar a usarlo?
  • Varios mensajes push: El contenido del adaptador ha cambiado pero ListView no ha recibido ninguna notificación
  • GcmBroadcastReceiver no se dispara en Android 4.0.3
  • Enviar notificación múltiple a GCM usando JSON
  • Google Cloud Messaging envía notificaciones a todos los dispositivos
  • Integración de GCM para Android
  • Azure Notification Hub ya no acepta la Clave API de GCM
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.