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/
Related
If I receive a GCM message in a BroadcastReceiver and then do some very basic logic, how much battery will that use? I am thinking around ~30 messages per day. What about data?
EDIT: I understand that different devices have different battery sizes and CPU efficiencies, etc. I'm not asking for a precise percentage used, more just "you should worry about that" vs "you don't have to worry".
The logic involves reading a long from the db (last sync time) and comparing it with current time.
The messages will mostly all be received in a span of ~4 minutes.
EDIT2: I guess what I am asking is is it worth it to limit/batch up the amount of push notifications that my server sends? Ideally, ignoring battery life, I would want my server should send a push notification every time new data gets updated. The phone can then decide whether or not to actually pull the updates from the server. If it doesn't decide to pull, then at least the phone knowingly decided to not update the data. As opposed to if I limit the amount of times my server sends push notifications to my phone to tell it there is new data, then the phone thinks it has updated data but it actually doesn't.
It really depends. GCM can be received over Wifi, or over a cellular connection. The cellular radio consumes much more power than Wifi. Also there's a "warm up" and "keep alive" after each use of the radio, so sending/receiving things in one big burst is more energy efficient than sending them spaced a few minutes apart. This Youtube video from GoogleDevelopers has some more information about how to optimize network access to minimize battery consumption.
That said, the exact amount of power used will likely depend on the handset, distance to tower/Wifi access point, network protocol used (802.11g, CDMA, GSM, etc), and other factors.
"you don't have to worry" is the answer. GCM services is one process which manage push notification for all android app. It is for sure better than many different apps which ask continuosly to a remote server for new messages. It will use some battery percentage, but less than any other way
I have an android app that uses GCM for push notifications. Lets say I need this for ambulance drivers when new calls are received. Right now there is a delay between when the server sends out the push notification and when the android device receives it, sometimes more than a minute. I've read on Stack Overflow about sending the heartbeat out, set delay_while_idle to true/false( yes I've seen both) etc...
What I need to know is if this is just how it is with GCM or if there is a way to make push notification times much more reliable. I've had suggestions of sockets, test messages etc... Because this is potentially for medical services I can't afford to have delays longer than what is absolutely necessary.
I've read that GCM notification delivery isn't guaranteed so is there a direction someone can point me to maybe do this on my own so that I can make something is guaranteed???
GCM push notifications are not reliable.
Have a look at "Pushy": https://pushy.me/
They state the following on their website:
The most reliable push notification gateway, perfect for real-time
applications.
Google Cloud Messaging simply doesn't cut it for time-sensitive,
real-time apps, due to its instability and push notification
throttling.
Pushy works by maintaining a dedicated background socket connection
using the MQTT protocol, an extremely light-weight pub/sub protocol
that consumes very little network bandwidth and battery, which makes
it perfect for mobile.
You can use it for free with up to 100 devices, so you could just give it a try to see, if it fits your needs. I didn't try it.
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
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.
According to this Android C2DM keeps a socket alive with a heartbeat mechanism, making it able to receive push messages. This made me hope I could deliver messages to sleeping phones with an active wifi connection.
I've made an implementation setting the "delay_while_idle" to '0'. The message is delivered if my phones' screen is powered off, but not if the phone goes to sleep (tested with intervals 20mins, 1-6 hours).
I have acquired a partial cpu lock + a full wifi lock just in case.
Have I simply made something fundamentally wrong or did I misunderstand the C2DM push functionality?
Can I send messages to sleeping phones or not?
Using alarmmanager instead of wakelocks could keep your phone alive just enough. See this implementation. Will test a variant of this.