I've been working with de C2DM for sometime and its has been working perfect. Recently I've bumped into a problem that I can't seem to fix and couldn't anything on this forum that might help. The problem is that I have several apps that use C2DM, I've let all apps register with the same sender id which then registers the users token in my database. The problem if a user has two of my apps A & B (same sender id) and launches app A and I send a push notification to users with app B, user who launched app A the last will receive a message which was actually intended for app B.
My question is there a way to use the same sender id for all apps installed on 1 device?
No. A C2DM Registration ID is scoped to one app on one device. If a C2DM message is sent to a Registration ID, it will only ever be delivered to one app. you should have used different C2DM accounts from the start, so each app has its own registration ID. Registration IDs are not per device, they are Per App Per Device.
If you cannot reconfigure the registration IDs then you could use a receiver that then sends a broadcast intent, and both your apps could pick it up by responding to that broadcast. I expect you'd need both apps to listen-and-rebroadcast, but it should work. I'd advise you reconfigure your C2DM usage tho, as your current setup is not ideal and I expect the problem will only get worse.
I assume when you say "sender id" you mean registration id.
Related
I just started to use Google Cloud Messaging and read about User Notifications.
According to this link, all the devices owned by a particular user will be notified at once.
In my case, a particular user is identified by his/her user_id and the database would look like this:
[user_id] [gcm_registration_id]
As per the demo, on the application side this registration_id is stored as persistent data.
What happens if the user uninstalls the app and the persistent data is gone?
Will I get the same Registration ID for the same App on the same device once the user re-installs the app?
Will Google invalidate these Registration IDs after some time?
will I get the same registration_id for the same app on the same
device once the user reinstalls the app?
YES. Reg id chnages in two cases. Either your app will register OR Google refreshes the Registration ID. SO until any one cases executes your are fine with old reg id.
By any chance google invalidates these registration_ids after some
time?
YES. Google refreshes the registration ID. GCM gives you the idea about handleing of updated registartion ID.
Handle updated id on client side
If the registration is successful, the GCM server broadcasts a com.google.android.c2dm.intent.REGISTRATION intent which gives the Android application a registration ID.
The Android application should store this ID for later use (for instance, to check on onCreate() if it is already registered). Note that Google may periodically refresh the registration ID, so you should design your Android application with the understanding that the com.google.android.c2dm.intent.REGISTRATION intent may be called multiple times. Your Android application needs to be able to respond accordingly.
Actually the answer you accepted is not entirely correct.
I tested the case of un-installing and re-installing an app on a device, and in some cases you could get a different registration ID.
There are two cases :
You install an app, register to GCM and get a registration ID.
You un-install app
Your server sends a few messages to that registration ID, until you get a NotRegistered error from GCM (I believe you'll get that error only from the 2nd message you send).
You re-install the app
You receive a new registration ID when app register to GCM
If you now send a message with the old registration ID, it will still work, but you'll get the new registration ID in the response as canonical registration ID.
You install an app, register to GCM and get a registration ID.
You un-install app
The server doesn't send anything to that registration ID while the app is un-installed.
You re-install the app
You receive the same registration ID when app registers to GCM
I have multiple different deviceids in my database table pointing to same a device because google will send me different device id when a device reinstall/install. Due to which devices getting multiple notifications which is hurting me and my users very much. Is there is a way to tell google that only send one notification to single device? or is there a way to check the id is new or old before sending request? Anyone experience with this weird issue? BTW, I am using PushSharp/ASP.NET in backend.
Update: I am now relying on native device id. So, I will remove/replace the old registration ids from my database table where native device id is same.
I think you need to remove the device id from your database once you get unregistered error code.
Unregistered Device
An existing registration ID may cease to be valid in a number of scenarios, including:
If the application manually unregisters by issuing a com.google.android.c2dm.intent.UNREGISTER intent.
If the application is automatically unregistered, which can happen (but is not guaranteed) if the user uninstalls the application.
If the registration ID expires. Google might decide to refresh registration IDs.
If the application is updated but the new version does not have a broadcast receiver configured to receive com.google.android.c2dm.intent.RECEIVE intents.
For all these cases, you should remove this registration ID from the 3rd-party server and stop using it to send messages.
Happens when error code is NotRegistered.
I recommend you to handle error codes when you send a message to a device.
http://developer.android.com/google/gcm/gcm.html
Please read role of 3rd party server. You would get more details.
I have many application on android. And some users are share the same register ID. How can I specify and send the push notification to a specific app?
Different applications have different registration ids on the same device, so you shouldn't have any problem. What do you mean by users are share the same register ID? Do you mean users of the same application on the same device? That's the only case where they can share a registration ID.
Even if you use the same Google API project ID when you register the different Apps for Google Cloud Messaging, you'll still get a different registration ID for each app. I tested it.
If you cannot change the registration ID process to uniquely identify you applications (the best solution), you can send a payload with your GCM message and have your application ignore GCM messages without a specific payload.
we are implementing c2dm to push notifications to users. we want the user to be able to "opt-out" at the beginning. if they opt-in, then we register the device and send the id to our server to store for later delivery and track that by some unique device id.
the problem is that there doesn't seem a reliable way in android to get a device id. everything i've read says, "just generate a guid at first startup of the app". well, this is fine, but if a user starts up the app, opts in, then uninstalls and re-installs the app, then opts out, i have no way of removing that old device (since the device id of the second install is new).
i've tested and an old c2dm registration id works even after an uninstall and re-install.
any suggestions? how do others allow users to opt-out of notifications. how do you track their devices?
Having a Device ID is nice, but you don't need it to handle opt-outs. When you send a C2DM message from your server, include the registration ID. Then, when the device receives a message, it can compare the delivered registration ID with what it thinks its registration ID is.
If it matches, show the notification. If it doesn't match, ping your server and tell it to opt-out that registration ID.
On first run of your app, you could ask the user whether or not they would like to receive C2DM messages, and send that answer to your server. Then it follows that you would only send C2DM messages to devices that want them.
Instead of a GUID, I would look into getting their associated Android Market account (i.e. email address). This way, reinstalls won't change anything assuming they're using the same Android Market account.
I just added C2DM capability to my Android App.
At the moment the following happens if C2DM is started in my App.
My App sends the registration Intent
The answer broadcast is received by my app
The device token is retrieved from the intent and sent to my server
From that moment everything is working fine. The client receives the push notifications etc.
A problem occurs if the following hapens:
The user uninstalls the application without disabling push. (Completely deleting it not only updating)
The user reinstalls the application
If after step 5 a push notification is sent my app still receives this notification.
It seems that the token which was retrieved from the previous install is still active and is reconnected to the new instance of my application.
This leeds to the following problem:
A user who reinstalls my app but has no intention of receiving push notifications has no possibility to remove himself from the service because the new instance of the app has no way to unregister the old token from my server.
Is this a bug in the C2DM system or is something wrong in my setup?
Update
I followed Berdons advice and did the following:
For testing purposes only start an unregister Intent every time my app starts up.
After I send the unregister intent no push notification from my server is sent to my application. That seems to do the trick, but if I now go the C2DM Settings Screen and turn on push notifications for my app all the old tokens get active again and I receive information that I did not register for in the current installation of my app.
Next Update
It seems I'm not the only one with this problem:
Android C2DM : Duplicate message to the same device and App
I hoped that Google would manage those tokens in a way that old tokens from the same device get disabled after a new one was issued. I also expect that after I sent an unregister Intent all tokens for that application and that device are marked as invalid or deleted from the Google Server for ever. If this is somehow a design decision by Google for special use cases I don't see please enlighten me.
We now found a solution that should work in most of the cases.
The server adds the C2DM registration id as a data field with every C2D Message.
The device now only shows a notification if the token in the message and the token that is stored in a pref file match. That way we guarantee that we don't show messages for device tokens that were obtained by previous installs.
If the tokens do not match we found an old token that should not be active anymore. We now mark the token on our own web server as inactive to prevent the server from sending more unnecessary C2D Messages
This solution enables us to show only relevant data without the need to store a unique user id.
In my C2DM implementation, each user's device token is saved in a database against their UDID and the package name of the app (among other things). The UDID and package name form the primary key, meaning that the table can list multiple apps from the same device (UDID). When a user runs a particular app, the device token is recorded, and if they uninstall and re-run the app, the new device token would be recorded over the old one. We also have columns to record whether push is active for that particular app/device combo, and which types of push messages the user has enabled/disabled.
When the time comes to send a push for a particular app, no UDID will be registered more than once (since these two fields form the primary key), and therefore only the latest device token will be used. Furthermore, our query only returns the rows that have push messages enabled.
This solution should solve your problem because it prevents you from sending the push to both device tokens. I hope this helps!
More like an unexpected "feature". You might consider issuing an unregister request on the "first run" (first run ever) of your application to prevent this from occuring.
Update
You could could do the work of differentiating between different C2DM messages by using the collapse_key (or anything of your own creation) as an identifier. Update it between registrations and pass it to the device following registrations, unregistrations and messages.