Below is the how to from google to register for GCM. Where in the second line of code do I put my appid? Comme to think about it is the appid the name of my project on the Google App Engine?
sender is the ID of the account authorized to send messages to the application, typically the email address of an account set up by the application's developer.
app is the application's ID, set with a PendingIntent to allow the registration service to extract application information.
For example:
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); // boilerplate
registrationIntent.putExtra("sender", "someemail#oo.com");
startService(registrationIntent);
The code in your quote is partly wrong. The value of sender used to be an email address (in the now deprecated C2DM), but in GCM the sender should contain the Google API Project ID.
sender is the project number of the account authorized to send messages to the Android application.
app is the Android application's ID, set with a PendingIntent to allow the registration service to extract Android application information.
According to http://developer.android.com/google/gcm/gcm.html
app is the Android application's ID, set with a PendingIntent to allow
the registration service to extract Android application information.
GCM extracts your app ID from the pending intent you are passing. So your second line is as it should be.
But I recommend you to use the gcm.jar library instead. It makes handling GCM much easier:
Add gcm.jar in Eclipse IDE (Google Cloud Messaging)
Related
I'm trying to understand how an app is registered with Google Cloud messaging. I'm looking at the code in the Google Play app for this which looks like this:
paramVarArgs = a(paramVarArgs);
Log.v("GCMRegistrar", "Registering app " + paramContext.getPackageName() + " of senders " + paramVarArgs);
Intent localIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
localIntent.setPackage("com.google.android.gsf");
localIntent.putExtra("app", PendingIntent.getBroadcast(paramContext, 0, new Intent(), 0));
localIntent.putExtra("sender", paramVarArgs);
paramContext.startService(localIntent);
I don't quite understand how the app that is being registered finally receives an intent as this seems to be sending the intent to the app with the package name com.google.android.gsf (Google services framework). I looked at the service that is invoked with the REGISTER action in gsf app, but it doesn't seem to be sending a broadcast either. I am quite confused about how this all works. Could someone please explain? Thanks a lot in advance!!
If you will check the Registering Client Apps document :
In the Instance ID API
Instance ID provides a unique ID per instance of your apps. You can implement Instance ID for Android and iOS apps.
Instance ID lifecycle
The Instance ID service issues an InstanceID when your app comes online. The InstanceID is backed by a public/private key pair with the private key stored on the local device and the public key registered with the Instance ID service.
Your app can request a fresh InstanceID whenever needed using the getID() method. Your app can store it on your server if you have one that supports your app.
Your app can request tokens from the Instance ID service as needed using the getToken() method, and like InstanceID, your app can also store tokens on your own server. All tokens issued to your app belong to the app's InstanceID.
Tokens are unique and secure, but your app or the Instance ID service may need to refresh tokens in the event of a security issue or when a user uninstalls and reinstalls your app during device restoration. Your app must implement a listener to respond to token refresh requests from the Instance ID service.
Here is a code sample for generating an ID:
String iid = InstanceID.getInstance(context).getId();
Hope this helps.
I am seeing this issue on my push notifications server - different Android devices (identified by their IMEI) receive the SAME registration id from Google's GCM service.
Isn't the registration id supposed to be unique? at east for the same application or GCM API Key?
I saw this thread but there doesn't seem to be an answer there:
Can two different devices have same GCM Registration ID?
Any help would be much appreciated
EDIT
here is the relevant code for registration:
Intent intent = new Intent(
"com.google.android.c2dm.intent.REGISTER");
intent.setPackage("com.google.android.gsf");
intent.putExtra("app",
PendingIntent.getBroadcast(context, 0, new Intent(), 0));
intent.putExtra("sender", flatSenderIds);
context.startService(intent);
The only idea that comes to my mind is that this deprecated method will assign the same ID on different devices if the extra value for sender is the same on all of them. That differs from the current version where you don't say who you are, you don't even send an Intent, you just call register() and Google determines who you are and what ID you should be given.
If you finally use this new library, there's an example snippet of how to register (inside an AsyncTask or a Thread):
GoogleCloudMessaging gcm = null;
try {
// Will be for the first time
if (gcm == null)
gcm = GoogleCloudMessaging.getInstance(your_context);
// Registration against the GCM service
String regid = gcm.register(YOUR_SENDER_ID_OBTAINED_FROM_YOUR_PROJECT);
// You'll need to send the registration info to your remote server
registerRemoteServer(regid);
Log.d("MyGCM", "Registered on GCM as " + regid);
}
catch (final IOException ex) { ex.printStackTrace(); }
Sometimes Google changes the registration ID and you'll have multiple IDs associated. The server that sends the notification (your server) has to update the database with the new ID.
For more info check this document:
http://developer.android.com/google/gcm/adv.html
they says:
It's an Canonical IDs
On the server side, as long as the application is behaving well,
everything should work normally. However, if a bug in the application
triggers multiple registrations for the same device, it can be hard to
reconcile state and you might end up with duplicate messages.
GCM provides a facility called "canonical registration IDs" to easily
recover from these situations. A canonical registration ID is defined
to be the ID of the last registration requested by your application.
This is the ID that the server should use when sending messages to the
device.
If later on you try to send a message using a different registration
ID, GCM will process the request as usual, but it will include the
canonical registration ID in the registration_id field of the
response. Make sure to replace the registration ID stored in your
server with this canonical ID, as eventually the ID you're using will
stop working.
Well, after adding your registration code, I can see you are using the old method of registration. That method has been depecated since the middle of last year. It is likely to be less reliable than the new registration method.
You should try registering via the GoogleCloudMessaging.register method of the Google Play Services library. That's the recommended way by Google. See the official demo here.
I have configured GCM in my application. I want to unregister device from GCM whenever user will uninstall application.
I got the code as
Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER");
unregIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
startService(unregIntent);
but where we have to put this code..?
Thank You.
You cannot call unregister from GCM while uninstalling, because there is no method called while user uninstalls the application.
when you send a push notification, GCM will check if the user has your application, if the user has uninstalled the application GCM will note the same and inform you as part of reply for the push.
You have to check this on your server. You cannot do it from the application code since there is no way of knowing when the user is uninstalling the application.
See: Implement Canonical IDs.
Reference: https://developers.google.com/cloud-messaging/http#request
A canonical registration ID is defined to be the ID of the last registration requested by your application. This is the ID that the server should use when sending messages to the device.
If later on you try to send a message using a different registration ID, GCM will process the request as usual, but it will include the canonical registration ID in the registration_id field of the response. Make sure to replace the registration ID stored in your server with this canonical ID, as eventually the ID you're using will stop working.
Reference: https://stuff.mit.edu/afs/sipb/project/android/docs/google/gcm/adv.html#canonical
If the Canonical ID is not 0, then you have a duplicate registration.
Say for instance, you have 2 registrations in your database:
registration_A
registration_B
When you send a push notification, your server will get respond with something that looks like this:
{"multicast_id":########,"success":1,"failure":0,"canonical_ids":1,"results":
[{"registration_id":"new_id_registration_id","message_id":"0:########"}]}
{"multicast_id":######### ,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:################"}]}
Store this data in an array. Notice that the first one has a "canonical_ids":1. This means there was a duplicate. So to know which record in your database is the old one. Just search for "registration_id" in the above and save the index value. This index value points to the old record in your database.
In the above example, registration_A would be the old registration_id.
Get all the records from your database. Then delete it based on the index value that you retrieved. OR you can update it. That depends on how you set up your database.
Good luck!
I need to receive push notifications from different senders in my app. Will it work?
The answer to your question is YES!
According to GCM's official documentation your app can receive messages from multiple senders (limited to 100 different senders) and your intent code should look like the above one to work correctly.
Intent intent = new Intent(GCMConstants.INTENT_TO_GCM_REGISTRATION);
intent.setPackage(GSF_PACKAGE);
intent.putExtra(GCMConstants.EXTRA_APPLICATION_PENDING_INTENT,
PendingIntent.getBroadcast(context, 0, new Intent(), 0));
String senderIds = "968350041068,652183961211";
intent.putExtra(GCMConstants.EXTRA_SENDER, senderIds);
ontext.startService(intent);
Feel free to check official topic at GCM page about multiple senders.
Since you have api key and sender id, then it will work. You need to use API key given by google in your server(or servers) to send message to Devices.
I have searched through net about C2DM and the process of registration of android device to the C2DM is very confusing. In the code below :-
Intent rI = new Intent ("com.google.android.c2dm.intent.REGISTER");
rI.putExtra("app",PendingIntent.getBroadcast(this, 0, new Intent(), 0));
rI.putExtra("sender", "myapp#example.com");
this.startService(rI);
What is "app", "sender" and "myapp#example.com"? I tried to signup for the Android C2DM but I couldn't understand what is the Role account email.
Any advice is appreciated.
In the code you have shown, the only thing you need to replace is myapp#example.com.
First you need to create a Google GMail account, e.g., yourappname#gmail.com
Then you need to go to the Sign Up for Android Cloud to Device Messaging page. Fill in all of the details on the sign up page and provide your GMail account as the 'Role (sender)'. Then in your code, replace myapp#example.com with the GMail address you've created.
EDIT: In response to your comment/question.
rI is an Intent and you are putting 'extra' data into that Intent which is passed to the Google C2DM registration service.
When you put data into an Intent, it has to have a key name so the receiver of the Intent is able to extract it using getStringExtra(keyName) (for example). The keys 'app' and 'sender' are reserved for C2DM registration and MUST be used as they are in that code otherwise the C2DM registration process will fail.