I've setup an Android app with GCM support, and have a little test app to send a msg to the app.
When I run the App in the emulator, I can see (via logging msgs) that it registers with GCM and gets a Token.
Then when I put the token in my test app and have it send a msg, the result shows that 1 msg was sent, 0 failed, and 0 had ID changes.
Sometimes the msg shows up almost immediately, sometimes it takes 20 minutes.
On Friday, my 2 test msgs took 15 and 20 minutes.
The first 2 I sent this morning were immediately, the next one hasn't shown up yet - it's only been 10 minutes...
Is there anything I can do to make the delivery times consistently fast? A random 20 minute delay will be pretty much an unacceptable condition.
We had the same problem, but it varied from network-to-network. We think it was the home hub router (a Virgin Super Hub) dropping the connection after five minutes of inactivity. You can confirm by sending an empty GCM message every two minutes to keep the connection alive.
Here is a more in-depth explanation of what we did: https://groups.google.com/d/msg/android-gcm/Y33c9ib54jY/YxnCkaPRHRQJ
You cannot guarantee fast delivery because GCM to device connectivity may be poor as CommonsWare has pointed out. There are however, two possible delays in the delivery train: 1) GCM connecting to the phone (as mentioned previously) and 2) The delay in the message actually being sent out from the GCM server. If you set the 'time_to_live' parameter to 0 seconds in your sending application, then you can at least test where the delay is occurring.
A value of 0 seconds means that the message will be sent immediately and if delivery is unsuccessful, the message will be discarded on the GCM server. It is not a practical value for real life use, but will enable you to find out which part of the delivery train is causing the delay.
This is indeed caused by unrealistic heartbeat intervals in Google Cloud Messaging.
This is possibly the most frustrating bug in GCM. GCM works by maintaining an idle socket connection from an Android device to Google’s servers. This is great because it barely consumes battery power (contrary to polling), and it allows the device to be woken up instantly when a message arrives. To make sure that the connection remains active, Android will send a heartbeat every 28 minutes on mobile connection and every 15 minutes on WiFi. If the heartbeat failed, the connection has been terminated, and GCM will re-establish it and attempt to retrieve any pending push notifications. The higher the heartbeat interval, the less battery consumed and the less times the device has to be woken up from sleep.
However, this comes at a great price: the longer the heartbeat interval, the longer it takes to identify a broken socket connection. Google has not tested these intervals in real-life situations thoroughly enough before deploying GCM. The problem with these intervals is caused by network routers and mobile carriers, who disconnect idle socket connections after a few minutes of inactivity. Usually, this is more common with cheap home routers, whose manufacturers decided on a maximum lifespan of an idle socket connection, and terminate it to save resources. These routers can only handle a finite number of concurrent connections, and so this measure is taken to prevent overload. This results in terminated GCM sockets, and when the time comes to deliver a GCM message, it does not reach the device. The device will only realize that the connection has been broken when it’s time to send a heartbeat, 0 – 28 minutes later, rendering the push notification useless in some situations (when the message is time-critical, for example). In my experience, most cheap routers terminate idle connections after about 5 – 10 minutes of inactivity.
I wrote an entire post about this and other GCM issues:
http://eladnava.com/google-cloud-messaging-extremely-unreliable/
An Alternative to Google Cloud Messaging
Pushy (https://pushy.me/) is a standalone push notification gateway, completely independent of GCM. It maintains its own background socket connection, just like GCM, to receive push notifications. The underlying protocol is MQTT, an extremely light-weight pub/sub protocol, utilizing very little network bandwidth and battery.
A huge advantage of Pushy is that the code for sending a push notification (from the server), and registering the device for push notifications, is actually interchangeable between GCM and Pushy. This makes it super easy to switch to Pushy after implementing GCM and having to ditch it for its instability.
(Full disclosure: I founded Pushy for my own projects and realized many apps would benefit from such a service)
GCM is reportedly having a pretty severe problem with keep-alive heartbeat not being so reliable. Therefore, since it's only dispatched once every 15 minutes (over 3G) or 28 minutes (over Wifi), if for some reason the server connection is dropped, it may not be restored for several long minutes.
These type of shenanigans prompted developing a solution that does not rely on a 3rd-party network to deliver massively-scalable and reliable push notifications to offline (backgrounded) Android apps.
https://help.pubnub.com/entries/21720011-Can-my-Android-App-Receive-Messages-While-Inactive
This matter is important to me.
I have set up this code inside a one second timer Handler to send out a GCM message every 2 minutes. The hope is that it will keep things alive
if ((mOneSecondTick %120) == 0){
// q 1 minute check when we got last call....
long lDiff = System.currentTimeMillis() - GCMlastCall;
if (PushAndroidActivity.GCMAvailable){
Log.d("pushAndroidActivity",String.format("(mOneSecondTick %d",lDiff));
if (lDiff > 122 * 1000){ // more than a minute
Intent intent = new Intent(StayInTouch.this,PushAndroidActivity.class);
2startActivity(intent);
}else{ // every 2 minutes send out a gcm message...
asyncWebCall(String.format(AgeingLib.GCMTICKLE,androidid),0);
return; // only if it sends a tickle and all is well...
}
}else{
Log.d("pushAndroidActivity",String.format("(mOneSecondTick mod60 no GCM on this device"));
}
}
GCMlastCall is the last time a message was received, so we can tell if gcm stopped.
Been working for a couple of days now seems OK
Related
In Test app, I have implemented FCM for sending notification messages using
https://github.com/firebase/quickstart-android/tree/master/messaging
For testing I sent the message(8:42 PM) from firebase console using the "New Message" under Notification.
But in my emulator, I have received the message at 9:06 PM
Please let me know if there is anything to do reduce the delay.
Thank you.
This could be caused by the unrealistic heartbeat intervals in Firebase Cloud Messaging.
FCM works by maintaining an idle socket connection from an Android device to Google’s servers. This is great because it barely consumes battery power (contrary to polling), and it allows the device to be woken up instantly when a message arrives.
To make sure that the connection remains active, Android will send a heartbeat every 28 minutes on mobile connection and every 15 minutes on WiFi. If the heartbeat failed, the connection has been terminated, and FCM will re-establish it and attempt to retrieve any pending push notifications. The higher the heartbeat interval, the less battery consumed and the less times the device has to be woken up from sleep.
However, this comes at a great price: the longer the heartbeat interval, the longer it takes to identify a broken socket connection. Google has not tested these intervals in real-life situations thoroughly enough before deploying FCM. The problem with these intervals is caused by network routers and mobile carriers, who disconnect idle socket connections after a few minutes of inactivity.
More info is available on my blog:
http://eladnava.com/google-cloud-messaging-extremely-unreliable/
As a workaround, please consider Pushy (https://pushy.me), a drop-in replacement for GCM/FCM which greatly improves notification speed & reliability (Full disclosure - I founded Pushy).
My best guess is that this has to do with the message priority.
From the docs:
Setting the priority of a message
You have two options for assigning delivery priority to downstream messages on Android: normal and high priority. Delivery of normal and high priority messages works like this:
Normal priority. This is the default priority for data messages. Normal priority messages won't open network connections on a sleeping device, and their delivery may be delayed to conserve the battery. For less time-sensitive messages, such as notifications of new email or other data to sync, choose normal delivery priority.
High priority. This is the default priority for notification messages. FCM attempts to deliver high priority messages immediately, allowing the FCM service to wake a sleeping device when possible and open a network connection to your app server. Apps with instant messaging, chat, or voice call alerts, for example, generally need to open a network connection and make sure FCM delivers the message to the device without delay. Set high priority if the message is time-critical and requires the user's immediate interaction, but beware that setting your messages to high priority contributes more to battery drain compared with normal priority messages.
I am not certain, but I believe that normal priority is used when you send a message to "All Android devices", which it seems you are doing in the question above. It is also possible that it is being sent to a FCM topic, which is optimized for throughput rather than latency
So, setting the priority to high, or sending to one specific device rather than a topic, should reduce the delay you are seeing.
Also; Be aware that push messages are based on best effort. There are no guarantees that the message will be delivered by a given time, or at all.
This issue tracker is dedicated to issues related to the Android Quickstart. The gurus working on this project don't have access to any diagnostics to help troubleshoot FCM issues. Please contact support . https://firebase.google.com/support/
When a device is using the mobile Internet (3G, 4G), it connects to Internet every 30 minutes. This can be seen with emails coming in a bunch instead 1 by 1 like when a device is on wi-fi (among other things).
How come that push-messages for chat apps (hangouts, whatsapp, viber,...) come immediately?
I actually noticed that only Skype messages do not come immediately when I am on the mobile data connection. Others come instantly.
When a device is using the mobile Internet (3G, 4G), it connects to Internet every 30 minutes. This can be seen with emails coming in a bunch instead 1 by 1 like when a device is on wi-fi (among other things).
That just means that those apps happen to be pulling down data every 30 minutes, whether via AlarmManager or JobScheduler or SyncManager or whatever. They could just as easily set their AlarmManager polling period to be 27 minutes, or 2.7 minutes, or 27 days.
How come that push-messages for chat apps (hangouts, whatsapp, viber,...) come immediately?
On a Play Services ecosystem device, either they are using GCM (which maintains an open socket connection), or they are using their own GCM-workalike (which maintains an open socket connection for however long they can keep their service running), or they are using something like AlarmManager with a small polling period (which is really bad for the battery, but that doesn't stop people).
On a Kindle Fire, they might be using Amazon equivalents of GCM, etc.
What makes mobile data interesting is that incoming packets on an open socket connection will wake up the CPU. From there, the apps for which those packets are destined can grab a WakeLock to be able to have time to process those packets. WiFi sockets are usually torn down around the time when the CPU goes into sleep mode, in part because usually the WiFi radio itself usually goes into a sleep mode around the same time, to conserve battery.
I actually noticed that only Skype messages do not come immediately when I am on the mobile data connection.
Skype might not use GCM for competitive reasons. I'm a bit surprised that they aren't using their own workaround GCM-like service (e.g., MQTT-based).
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?
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 want an Android service, which is listening for data (I have tried TCP and UDP) to wake up the service/phone when data arrives.
Currently the phone stays asleep when IP data arrives and that data is lost. Is this normal for Android? I see sleeps of 2+ hours several times a day, and 7+ hour sleeps when I am asleep.
Does GCM provided a solution which wakes up a service/phone when a message arrives.
I need messages to be displayed within a few seconds of them being sent from the server.
Can this only be achieved by keeping the CPU running all day long? Is there no interrupt from the GSM modem on the arrival of data?
As I understand it, if you have an outstanding socket connection over mobile data to a server, that socket connection is maintained while in sleep mode, and incoming packets will wake up the phone out of sleep mode (briefly) to deliver the data.
The same is not true of WiFi (and presumably not for hardwired Ethernet, either). You would need to hold a WakeLock and a WifiLock.
Does GCM provided a solution which wakes up a service/phone when a message arrives.
Yes, but...
I need messages to be displayed within a few seconds of them being sent from the server.
First, GCM has no service-level guarantee. I am not aware of any solution that does, including anything that you might roll yourself (e.g., MQTT).
Second, you have no idea if the device is capable of receiving any such messages (GCM or otherwise), as the device may be turned off, in airplane mode, etc.