I have an Android app capable of receiving two different types of Push messages. Our backend server, depending on its business rules generates these messages with appropriate Payload, no collapse keys (do not collapse) but different TTL ( first message lives only for an hour and other for 24 hour).
Everything works fine when the Android device is connected to a network.
However, when the device is not connected to the internet, and if it happens to receive messages of both types, when the device is brought online it only seems to receive message with longer TTL.
Can someone share insight to what is going on here?
I'm assuming that you're connecting the device to internet after TTL (time to live) has elapsed.
In that case, if your device doesn't come online for an hour, GCM will discard that message, which is exactly what is happening in your case.
Is your first message getting discarded even before TTL elapses and you get the device online?
Related
I have a large scale project with hundreds of devices out in the field that I communicate with using GCM. Recently I've been experiencing a strange issue where many of these devices have stopped responding to my GCM messages. A couple things to note:
Sending my payload to Google's GCM servers still returns a proper 200 response.
The GCM keys for these devices have been verified to be correct/active.
The device will start receiving GCM messages if I move the device to a different network/subnet.
The device will start receiving GCM messages if I change its IP address on the same network.
The device will start receiving GCM messages with its initial IP address if I clear data of the Google Playservices package and restart my application.
It seems as if the socket for GCM has gotten stuck in a disconnected state and does not reconnect. These devices are typically connected via wifi which does sometimes drop, however... This past weekend, over 100 of these devices stopped responded so that leads me to believe some sort of TTL has expired and a refresh never happened.
Has anyone experienced anything like this before, or have any thoughts or suggestions about this?
I'm currently developing a titanium app that uses the gcm.js module to handle GCM messages. But GCM seems to be really buggy when it comes to message delivery. It happens very often that I get the messages with a delay of several hours, if they are received at all.
I know that GCM tries to save energy. But strangely, GCM is the most unreliable, when the phone is connected to my computer via USB, and I am debugging the app. In my opinion, GCM should not try to save energy in this case at all! Notifications should arrive immediately, when the phone is currently charging.
I've event tried to send the messaged with a TTL value of 0-10, to make use of the "now or never" effect, but this only resulted in never getting any messages.
So, what I need is a way to manually force my android phone to fetch new GCM messages, so that I can debug what happens when I receive them. I don't have the time to wait hours until the phone receives the message.
Is there a way to do this?
PS: Yes, I've tried several phones, including Nexus 5, Galaxy Nexus and some htc devices. Everywhere the same :/
You can try this (just for debugging purposes):
1) Make sure delay_while_idle flag is set to false (wouldn't advice to keep it as false in final product).
2) Keep TTL as is.
3) Use message with payload (remember the limit is 4 kb). You can set this by removing collapse_key parameter.
4) Now implement message_type in your receiver.
My logic here is that you send a message with proper payload and since its going to live for only 10 seconds, it will collapse. Once collapsed, through message_type_deleted you can fetch that message. (Sync app to fetch)
PS: I doubt this will be a stable technique but it will serve the purpose most likely.
Hopefully it helped!
I have a server with sql database.
Also have about 100k users on android application.
What I need now is to send immediately notifications from the server to all devices.
Im researching the GCM system but as I see there`s a huge delay on the receiving side.
What I need is when I click the send button on my server,everyone device to receive it in a few seconds.
Is the delay only happening when using the HTTP connection?
Is it going to be different with the XMPP connection ?
You are trying to broadcast a message to nearly 100k users and currently xmpp downstream messaging does not support broadcasting. Use http server to send message to 1000 devices at a time. This can be improved by using multi curl. see this https://github.com/mseshachalam/GCMMessage-MultiCURL
In general the GCM is the right choice for massive broadcasting.
On the other hand the messages are not guaranteed to be delivered immediately, the delay might be up to 25(!) minutes given, that all devices have your app up and running.
See Google Cloud Messaging - messages either received instantly or with long delay for explanations why
I am having issues with C2DM. Sometimes works perfectly, sometimes my messages simply do not get pushed. Is there reliable way to enforce this connection? To pull messages. I read somewhere that what google do is keep low bandwidth TCP connection to their server at all time. So I assume that
when switching between network types TCP connection falls down and Android tries to reestablish connection to C2DM servers. So that might fail on WiFi with restricted network. Is that wrong assumption?
I have noticed with WhatsApp that on WiFi sometimes I do not get messages. When I switch to 3G I usually get them at the moment of the switch. What tips from your experience with C2DM would you offer?
C2DM is not suitable for critical parts of your application, since Google currently does not offer an SLA or paid tiers that will guarantee you reliable service and throughput.
I've considered several alternatives myself: XMPP via asmack, Parse, Deacon, Urban Airship, and MQTT.
After some reading and experimenting I decided to go with MQTT. It is a very lightweight telemetry protocol invented at IBM that fits quite nicely in the Android push notifications scenario. I recommend you give it a try, here's a nice blog post to guide you: Using MQTT in Android mobile applications.
Hope this helps.
C2DM does not guarantee that your message will be delivered, and your application should not assume that in order to work correctly. Therefore, your C2DM message should never contain the data itself but, rather, a notification that there is data available. In other words, the loss of a C2DM message should never cause your application to lose data; it should, at most, cause it to take longer to notice that a certain piece of data is available on your server.
A typical app should connect to its server once in a while (a long while) to retrieve messages, even when using C2DM, to cover the case where C2DM messages might not be delivered.
Depending on network configuration, the device might not be able to receive C2DM messages; restrictive firewalls or other strange WiFi configs might do that.
With C2DM reliability is not a guarantee. So best to have a ACK
message or some way in which you (the sender) the realize the message was received successfully.
Also make it a point to override onRegister class properly because the device Reg ID keep on shuffling.
Lastly, if you are planning to send updates regularly, I'd prefer polling to C2DM just because of the amount of requirements to get it functioning while reliability and ultimate control is still not assured.
I've been struggling with the same problem myself. The behaviour you describe is accurate. I'm developing an app that uses c2dm mainly with Wifi connection, and I had to implement an AsyncTask to periodically (minute and a half) call WifiManager.reassociate() (turning wifi off and on again triggers the arrival of all pending notifications, that's what inspired this solution) so I can keep the notification arrival as accurate as possible. Not so sure about the correctness of this practice, though.
Have you tested it every 15 minute connection? I created a schedule task to send the message. I use NotifyMyAndroid to push it. C2DM sometime pushes the message about 10 mninutes after not instantly. But, sometimes you get it in around a second.
The best way you can do this is by testing. I have a mechanism in my app that when I enable debugging I receive a HTTP request from the client saying that they received the message.
I find that this number is about 80%. Fortunately that's enough for the scope of my application.
Wifi shouldn't interfere in the C2DM ability of receive messages. At least while the phone is active.
What happens is that android turns the wifi OFF after the phone is in standby for a while. The messages won't be available at that period of time, simply because there's no internet connection available. Right after the user wakes the phone up, they should receive the messages.
After a long time research pretty much "all the internet" for an answer, I've found it. As I posted before, I was struggling with the problem myself and found out it was not a C2DM problem, or even a implementation problem. It was simply a router or firewall misconfiguration. Android uses a persistent TCP connection with a heartbeat keep-alive mecanism to ensures that the connection stays up. Google uses the state of the connection to determine if your device is idle or not. But if your router has a protection policy that checks for "unused" connections and terminates them, that won't work. Android notifications should be delivered (close to) instantly. I've tested this in my school network and home network, with two diferrent behaviour.
To resume: be sure to check your network configurations.
Some APNs work better than others with C2DM. Google "gtalk apn", for example, to find forums about the impact of the APN on C2DM.
I'm trying to place a best guess estimate as to whether C2DM messages can be received.
I've created an application that relies on pushing information to a phone while it is physically inaccessible. I understand that C2DM isn't guaranteed delivery, but I'd at least like to know when the delivery of a message is even possible; when it isn't we fall back to our own push service (and can actually tell when we're connected).
I've noticed C2DM on android will still issue auth tokens even when there is not a logged in google account; messages still seem to be delivered in this instance even though it's stated that they shouldn't be. If GTalk isn't connected (firewall or other reasons), no response at all is returned when requesting an auth token. Auth tokens are returned to the application when the phone is in airplane mode. This means it's not as simple as checking if an internet is available. I can't find a reliable way of checking if GTalk is logged in.
Again, I don't need to guarantee the delivery of messages, but I'd at least like to know if delivery is even possible. Does anyone have interesting solutions?
Go watch this video, it's a Google I/O talk about C2DM, how to use it and how it works. AFAIK, you can't know if it's connected or not. Probably most of the time they don't even know (until they have to deliver a message and fail).
However, it is highly recommended (in the video as well) that you do not send important data through C2DM (as messages can get lost). The service should only be used as a "network tickle" (with a footprint as small as possible). Your application should be woken up by this tickle and it should start fetching the information it needs itself.
Now, if you implement it this way, it should be easy to implement a polling mechanism. Since you already separated the "tickle" from the actual information retrieval, you can just trigger the retrieval every once in a while if there's no tickle.
Something you can do to check whether C2DM is connected is something like a ping:
Send message to phone via C2DM
The app receives (or doesn't receive) the message and sends a "pong" back to your server
The server waits for the "pong" for a predetermined amount of time (1-2 minutes, I'd say) before marking the device as "offline".
Edit: relying on GTalk is not feasible. GTalk relies on C2DM just like your app, it doesn't have anything "extra". Also, GTalk is not present on all devices. I'm not sure how the GTalk app determines whether it's offline or not (it's not open source, unfortunately), but I'd guess it just tries to ping a server and fails.
No that is impossible.As you device authenticated once and generate registration ID and send to third party server(As you already know).Now your work is over once the device has been registered.So Wait for message either you got or not(No guarantee of delivering message as C2DM used UDP Protocol ).
Alternative Solution
Although its impossible to check from Google side directly as i mentions above,But if you have any urgency to check connection from your phone
then you can take approach like this
Step 1): Make one Web service to check connection
Step 2): Call this web service from application that will command to server to send push notification for checking purpose.
Step 3): Now from server side,server will immediately send push notification for particular device(FROM which it get command)
Step 4): Now if you got push notification that means you are still connected to C2DM.
this will not take much time.But follow it only when checking connection is urgent and it is on user
This may be a bit naive as I am not an active C2DM user, but wouldn't it be possible to read
/proc/net/netstat
and see if there are any active TCP connections. If there aren't any, then C2DM can't possibly be working. You could also make this technique more versatile by forming a C2DM whitelist that you would expect to find (or maybe its possible to filter on a special C2DM port?)
If the device is inaccessible, even your fallback push messaging system wouldn't work. The C2DM doesn't guarantee that it will deliver your message, but the event of non-delivery would be very rare. So would be the case with any other service. The best workaround that you could have is to poll your server to check if you have any new messages that hasn't been delivered yet. I am assuming that your application is such that it's very important not to miss even a single message in 500 or may be 1000. In that case, you could implement a hybrid of push and pull.
I've worked a little with C2Dm, I've created my own push 3rd party server .
I've implemented a little logic based oh C2DM http response code to know if a push message was sent or not .
Here is some of the code I used :
int responseCode = conn.getResponseCode();
if (responseCode == HttpServletResponse.SC_UNAUTHORIZED || responseCode == HttpServletResponse.SC_FORBIDDEN) {
LOGGER.warn("Unauthorized - need token");
return false;
}
here I'm almost sure that the push message was sent from the c2dm servers because I've got an id ont the response:
if (responseParts[0].equals("id")) {
LOGGER.info("Successfully sent data message to device: " + responseLine);
return true;
}
I've used other methods to get other result codes from Google if you want I can post them.I hope that I've helped you a bit .
I don't think there's any way to determine in ADVANCE whether there's any chance a push attempt will work, but I can think of a fairly straightforward way to verify receipt (but not queueing for future delivery via C2DM) -- just complete the message loop.
Remember, C2DM's main benefit is that it allows notifications when then phone is asleep and nominally offline. Once your application gets the notification, there's little to stop you from waking up the phone at that point, bringing up the network, and sending a confirmation. I don't think you'd even have to request "keep phone awake" permissions, because I believe the mere act of having registered for C2DM notifications and receiving one is sufficient to wake up the phone and allow the app to continue running normally (at least, long enough to bring up the network and send the confirmation).
While you're at it, you should keep track of confirmations that happen LONG after you expected them to be a lost cause. If you see more than a few, you might have to alter the resend strategy.
The only real-world edge case where this might fail is if you had users who bent over backwards to disable data while leaving voice/SMS enabled (I'm pretty sure C2DM uses 4 bytes of the response datagram sent when a phone polls for incoming calls & text messages that were originally set aside for RIM, then later repurposed for Apple and Google).
try to shut down all network connections and reconnect again. if you will get an registration id, then you can receive messages.
Something related to the long running C2DM-connection that is used to deliver the triggers:
On WLAN it sends a heartbeat every 15 minutes.
On mobile networks the timeout is 28 mintes.
28 Minutes might be to long, depening on the hardware your mobile carrier uses, 2g/3g repeaters in garages, etc.
You can get lots of information about the connection by opening the Google Talk Service Monitor Application: http://www.honeytechblog.com/monitor-google-talk-service-android/
Dial: ##8255##
Theres also a button that sends a heartbeat right now and resets the timeout.
If you want to ensure (on the client side) that c2dm-messages can be received at a given time, your best bet is to re-send the heartbeat. This can be done programmatically - only on rooted devices though. I might release an apk to the market sometime that does exactly that.