We have implemented GCM to show notifications in android application but only some messages not receiving in devices sent by server to google? Server is sending messages without collapse_key so every message should reach in device without collapsed. Please suggest me to proceed further.
Thanks
Receiver code is below:
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
service code is below:
public class GcmIntentService extends IntentService {
NotificationCompat.Builder builder;
public GcmIntentService() {
super("GcmIntentService");
}
public static final String TAG = "GCM Demo";
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
/*
* Filter messages based on message type. Since it is likely that GCM will be
* extended in the future with new message types, just ignore any message types you're
* not interested in, or that you don't recognize.
*/
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.i(TAG, "Working... " + (i + 1)
+ "/5 # " + SystemClock.elapsedRealtime());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
generateNotification(this, name, id, message);
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
}
Manifest file is below
<permission
android:name="MY_PACKAGE_NAME.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="MY_PACKAGE_NAME.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<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="MY_PACKAGE_NAME" />
</intent-filter>
</receiver>
<service android:name=".GcmIntentService" />
You need to create a Google account in that device (Settings -> Accounts -> Google). So please check whether it's logged with Google or not :)
Related
I am trying to receive the push notification message and send the notification message but i am getting the null value not receive any message.
Below code
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
Log.d("push","msg type: " + messageType);
if (!extras.isEmpty()) {
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
.equals(messageType)) {
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
} else if (!extras.isEmpty() && GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
Log.d("push notify msg: ", extras.toString());
sendNotification(extras.toString());
}
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
Create a receiver and declare it in manifest.
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(),XYZIntentService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
Manifest:
<receiver
android:name="com.companyname.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="PKG_NAME" />
</intent-filter>
</receiver>
Meta Data Tag:
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
Permissions:
<permission
android:name="com.vuliv.player.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.vuliv.player.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
Now you can add your code to XYZIntentService to get GCM notification.
For any query feel free to raise.
Follow this link it is a sample project of GCM provided by GOOGLE it will help you
I have created a GCM Intent service and the device is getting registered successfully and server successfully send the message. but device don't get any notifications.
Below the log i see,
10-29 18:26:09.599: V/GCMBroadcastReceiver(30775): onReceive: com.google.android.c2dm.intent.RECEIVE
10-29 18:26:09.599: V/GCMBroadcastReceiver(30775): GCM IntentService class: com.eye.hor.GCMIntentService
10-29 18:26:09.599: V/GCMBaseIntentService(30775): Acquiring wakelock
Below is the code for GCMBroadcastReceiver,
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(context.getPackageName(), intent.getExtras().toString());
Log.d("brdR", "askd");
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
Below is the code for GCMIntentService,
public class GcmIntentService extends IntentService {
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
public GcmIntentService() {
super("GcmIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
/*
* Filter messages based on message type. Since it is likely that
* GCM will be extended in the future with new message types, just
* ignore any message types you're not interested in, or that you
* don't recognize.
*/
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("", "Working... " + (i + 1) + "/5 # " +
// SystemClock.elapsedRealtime());
// try {
// Thread.sleep(5000);
// } catch (InterruptedException e) {
// }
// }
Log.d("true", "Completed work # " + SystemClock.elapsedRealtime());
// Post notification of received message.
sendNotification(extras.getString("msg"), extras.getString("title"), extras.getString("id"));
Log.d("true", "Received: " + extras.toString());
}
}
// 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, String title, String id) {
mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
int notification_id = Integer.parseInt(id);
// PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new
// Intent(this, CommonUtils.class), 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.icon).setContentTitle(title)
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg)).setContentText(msg);
// mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(notification_id, mBuilder.build());
}
}
This is manifest,
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
android:name="com.eye.hor.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.eye.hor.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />
Receiver Code in Manifest,
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.eye.hor.service" />
</intent-filter>
</receiver>
<service android:name="com.eye.hor.service.GCMIntentService" />
My main package name is com.eye.hor but i placed GCMIntentService and GCMBroadcastReceiver java files in the com.eye.hor.service package. i already put log in these two classes but they not reach.
please help
Looks like you already know you have a problem with the package names :
The following looks for your service class in the wrong package :
ComponentName comp =
new ComponentName(context.getPackageName(), // this is the main package of
// your app - com.eye.hor
GcmIntentService.class.getName());
Change it to :
ComponentName comp =
new ComponentName(GcmIntentService.class.getPackage().getName(),
GcmIntentService.class.getName());
You should also change the category in your manifest to the main package :
<category android:name="com.eye.hor.service" />
to
<category android:name="com.eye.hor" />
<category android:name="com.eye.hor.service" />
This is not supposed to be the package your broadcastreceiver is in, this is the package defined in the google developers console.
I'm willing to bet in your google developers console you defined the package has com.eye.hor, in which case you would have to change this line to:
<category android:name="com.eye.hor" />
What is device on which you developed your app? On different devices there are exotic settings influence on background working, check such setting in your device ("autostart", "push notification" and other, they can called different on some devices like Xiamo, Huawei and other).
Are you sure that your push server uses correct "sender id" and "api key" parameters, which you can check in developer console?
Check that Google Play services installed correct.
When implementing xmpp over the Cloud Connection Server of Google i receive messages that will start an WakefulBroadcastReceiver.
Manifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<permission
android:name="com.tag.xmppandroid.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.tag.xmppandroid.permission.C2D_MESSAGE"/>
<receiver
android:name=".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.tag.xmppandroid"/>
</intent-filter>
</receiver>
<service android:name=".GcmIntentService"></service>
WakefulBroadcastReceiver
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
Now this WakefulBroadcastReceiver will start an Intent service called GcmIntentService.class. The purpose of this intentService is receiving the message and directly send a message back as xmpp to the server that send the message. Actually this works, i send the message back with gcm.send(...) and the server receives the messages. But only when im debugging.
The server won't receive the message when the application is not in debugging mode. When the application is in debug mode it will send the message to the xmpp server. It looks like the thread shuts down to early and the message could not be send back to the server. But when im debugging i prevent the service from sleeping and it has time to send the message or anything. Does anyone know why this happens?
Code of my Intentservice:
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
final GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
String message_id = null;
String time_to_live = null;
if (!extras.isEmpty()) // has effect of unparcelling Bundle
{
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + extras.toString(), null);
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// Get values from intent send over xmpp
message_id = ((intent.getExtras() == null) ? "Empty Bundle" : intent.getExtras().getString("message_id"));
String message = ((intent.getExtras() == null) ? "Empty Bundle" : intent.getExtras().getString("message"));
time_to_live = ((intent.getExtras() == null) ? "Empty Bundle" : intent.getExtras().getString("time_to_live"));
Bundle data = new Bundle();
data.putString("hello", "world");
data.putString("delivered", "true");
try {
gcm.send(Constants.GCM_SENDER_ID + "#gcm.googleapis.com", message_id, Constants.GCM_TIME_TO_LIVE, data);
} catch (IOException e) {
e.printStackTrace();
}
// Send data to the view
sendToView(message_id, message, time_to_live);
// Show notification
sendNotification("Received: " + message, extras);
// Show toast on main thread
Handler mHandler = new Handler(getMainLooper());
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), Constants.GCM_SENDER_ID, Toast.LENGTH_SHORT).show();
}
});
}
} else {
sendToView("empty_bundle", null, null);
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
I hope someone can explain me why this happens, or what i do wrong since i really want to understand why this happens.
When I send a push notification to the emulator I get this message:
{"multicast_id":8595716062607030073,"success":1,"failure":0,"canonical_ids":1,"results": [{"message_id":"0:1403002114354553%44f16b55f9fd7ecd","registration_id":"XXXXXXX...
But after registering and sending the notification to my device with the new regId i get this :
{"multicast_id":8356469968000736599,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1403002260325568%44f16b55f9fd7ecd"}]}
I activated the notification in my phone and connected with Google account
Also i get the new registration ID in my database when registering but i cant figure out the problem
Here is my manifest.xml:
<!-- for gcm -->
<receiver
android:name="com.test.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.test.android.gcm" />
</intent-filter>
</receiver>
<service android:name="com.test.android.gcm.GCMNotificationIntentService" />
<!-- end for gcm -->
<!-- GCM activity -->
<activity
android:name="com.test.android.gcm.RegisterActivity"
android:label="#string/app_name" >
</activity>
<activity
android:name="com.test.android.gcm.MainActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name" >
</activity>
<!-- End GCM activity -->
Can anyone point me to the right direction please
This is how it works.
When registering a client to GCM you get a registration ID. Let's call it A. Your server will hold on to that for it to be able to send notifications.
Time goes by and for whatever reason, say expiration of the registration ID in the GCM server, GCM decides to give the same client a different, newer ID. We'll call it B. Your server holds on to that one, too.
Now you have to IDs for the same device, one is old and another is up to date. They will both be valid for sending notifications.
In a MulticastResult, receiving a Canonical ID means that the ID you're using isn't the most recent ID. When you do receive a canonical ID, it should replace the one you're using (since it's the most up to date ID).
For A you'll receive a MulticastResult with success=1, canonical id=B. For B you'll just receive success=1 because it is the most recent ID. The response for A indicates it is out of date and should be replace by B.
Since in your case you're using a newly registered ID (like you've said), there's no reason for it to be out of date, and there is no problem with your code.
As for why you are not getting the notification, your client has to have a receiver class that extends WakefulBroadcastReceiver, and handles the incoming notification:
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
and an IntentService to complete the picture
`public class GcmIntentService extends IntentService {
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
public GcmIntentService() {
super("GcmIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
/*
* Filter messages based on message type. Since it is likely that GCM
* will be extended in the future with new message types, just ignore
* any message types you're not interested in, or that you don't
* recognize.
*/
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.i(TAG, "Working... " + (i+1)
+ "/5 # " + SystemClock.elapsedRealtime());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
Log.i(TAG, "Completed work # " + SystemClock.elapsedRealtime());
// Post notification of received message.
sendNotification("Received: " + extras.toString());
Log.i(TAG, "Received: " + extras.toString());
}
}
// 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, DemoActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_gcm)
.setContentTitle("GCM Notification")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
See Implementing a GCM client.
UPDATE: I fixed the problems in the code below so this makes a nice basic working example of how to use GCM
So, I'm trying to implement Android GCM into my app. Here are the relevant parts I've added to the manifest:
<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" />
I've added the following code to the onCreate of my main activity:
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" );
}
I've also created the GCMIntenetService class like so:
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 );
}
}
When I run this I get this in 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
From what I've gleaned from other posts I should get a registration ID in LogCat but I"m not. Also onRegistered() in GCMIntentService never gets called. So what am I doing wrong?
this is incorrect
protected GCMIntentService( String senderId ) {
super(senderId);}
As it states in the documentation. you must declare a PUBLIC, NO ARGUMENT constructor for GCMIntentService. Otherwise the GCMIntentService can't be instantiated properly by background intent services.
public GCMIntentService(){
super(senderID);}
the senderID can be a hard coded constant string because it will no longer change with the new GCM.
It's also very important you use the correct senderID. 24 hours is long enough for yours to be active so if my above solution doesn't work you are using the incorrect senderID. Everything else looks great.
The senderID is in the URL of your web browser when you are browsing the Google API access page. Click on GCM and a 12 digit number will be present in the browser URL. That is the correct key to use. NOT your API key. That is used on the App server side.
I also had this ANNOYing bug, til now. The Problem was, that i declared the intentservice inside another package... even if i declared the name in the android manifest and no classnotfound exception had been place... no error at all could be found... so i made sure the intentservice is in the root package.
I think you have some issues in the code.
You should do the registration of your own broadcast receiver in the manifest file and that receiver will trigger the <service android:name=".GCMIntentService" />.
Therefore you must do something like I write below.
The receiver must be declared like:
<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>
Your broadcast receiver that will start the service.
public class YourBroadCastReceiver extends BroadcastReceiver {
#Override
public final void onReceive(Context context, Intent intent) {
GCMIntentService .runIntentInService(context, intent);
setResult(Activity.RESULT_OK, null, null);
}
}
I advice you to take a look at the official GCM documentation where you can find a good example.
And... don't forget to enable the Google Cloud Messaging service in the main Google APIs Console page.
Let me know if it helps!
See below tutorial for GCM:-
http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
Here I have written few steps for How to Get RegID and Notification starting from scratch
Create/Register App on Google Cloud
Setup Cloud SDK with Development
Configure project for GCM
Get Device Registration ID
Send Push Notifications
Receive Push Notifications
You can find complete tutorial in below URL link
Getting Started with Android Push Notification : Latest Google Cloud
Messaging (GCM) - step by step complete tutorial
Code snip to get Registration ID (Device Token for Push Notification).
Configure project for GCM
Update AndroidManifest file
For enable GCM in our project we need to add few permission in our manifest file
Go to AndroidManifest.xml and add below code
Add Permission
<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" />
Add GCM Broadcast Receiver declaration
add GCM Broadcast Receiver declaration in your application tag
<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/>
Add GCM Servie declaration
<application
<service android:name=".GcmIntentService" />
<application/>
Get Registration ID (Device Token for Push Notification)
Now Go to your Launch/Splash Activity
Add Constants and Class Variables
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;
Update OnCreate and OnResume methods
#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);
}
Note : please store REGISTRATION_KEY, it is important for sending PN Message to GCM
also keep in mine this will be unique for all device, by using this only GCM will send Push Notification.
Receive Push Notifications
Add GCM Broadcast Receiver Class
As we have already declared “GcmBroadcastReceiver.java” in our Manifest file, So lets create this class
update receiver class code this way
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();
}
}
Add GCM Service Class
As we have already declared “GcmBroadcastReceiver.java” in our Manifest file, So lets create this class
update receiver class code this way
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());
}
}
Not sure if this is related to your specific problem, however, I was experiencing the same issue. Everything was setup correctly, as far as I could tell, but the onRegistered() handler was never called.
I had the standard onCreate(), onStart() and onDestroy() service methods as part of my GCMIntentService class. Once I removed them, the handler was called, as expected.
My assumption is that by overriding these methods, I was by-passing needed code initialization.
After reading ClouDeveloper's post I removed onCreate(), onDestroy(), and the other onXXX() callback methods. Also, my GCMIntentService.onRegistered(Context, regId) is called with the regId.
Thank you ClouDeveloper!
You also need to register with your application server in the GCMBaseIntentService.onRegistered() callback. Otherwise you will not be able to send your app messages.
You should really checkout Google's GCM demo client as it provides a working sample with all of the correct code. We also have a working sample up on github: airbop-client. It provides a slightly more complete example given that it has working interactions with an application server, which is necessary for a GCM enabled app. It works with the AirBop servers (which I helped create) which are free up to 1000 devices.
If you are not getting response from the registration, one of the main reason is your manifest file is not configured correctly - especially give the "package_name" (your app package name like com.xxx.yyy) in the <permission> and <intent filter> correctly.