Using websockets for Android chat - android

I'm using WebSockets to allow for real time chat within my android application. When the app is not active and the user recieves a message, GCM works to turn the websockets service on in the background and reenable real time chatting,.
I have read concerns about WebSockets and battery life but if I use GCM to turn on the WebSockets only when the user has a new message to respond to, is this a viable solution to allow real time chatting?

No I don't think so .GCM are not 100% reliable.
Their documentation says:
GCM usually delivers messages immediately after they are sent. However, this might not always be possible. For example, if the platform is Android, the device could be turned off, offline, or otherwise unavailable. Or the sender itself might request that messages not be delivered until the device becomes active by using the delay_while_idle flag. Finally, GCM might intentionally delay messages to prevent an application from consuming excessive resources and negatively impacting battery life.
When this happens, GCM will store the message and deliver it as soon as it's feasible. While this is fine in most cases, there are some applications for which a late message might as well never be delivered. For example, if the message is an incoming call or video chat notification, it will only be meaningful for a small period of time before the call is terminated. Or if the message is an invitation to an event, it will be useless if received after the event has ended.
So you can use GCM to reconnect to the webSockets if the client is not connected,but once the connection is made ,then all the communication should be on the socket itself.

Related

How reliable is FCM upstream message delivery?

The documentation for Firebase Cloud Messaging upstream messages (messages from the device to the server) describes how messages are queued for delivery if the device is offline.
Android:
In cases where the device is offline or the FCM service is unavailable to forward upstream messages to your server, Android client app instances can accumulate a maximum of 20 pending messages.
iOS:
The FCM client library caches the message on the client app and sends it when the client has an active server connection.
But what about if the app is closed before the message can be delivered? Does Firebase attempt to use any sort of background service to deliver such messages once the connection is restored? Or are they queued until the app is next opened, or are they discarded entirely?
Edit: in my experiments, there at least is a persistent queue that saves messages across app restarts. But I'm still not sure (on each operating system) what circumstances cause the Firebase messaging service to be running or not, especially when the app is backgrounded.
In the iOS part that you mentioned, it explicitly states that:
The FCM client library caches the message on the client app and sends it when the client has an active server connection.
With that said, I think it is also the same case for Android. So long as the cache isn't cleared for the client app, it should be safe to say that the data is still there. However, it is also good to keep in mind what was mentioned in this answer by #DanHulme:
Cached background processes
Don't forget that Android keeps background processes in memory even when they've stopped running, unless/until another process needs to use that memory. If the app is 'stopped', it's not using any resources, not even if Android is keeping it in memory.
So I think it would be best for you to implement a checker in your client app, whether or not the upstream message was sent successfully, and to re-send it on a later time (when the connection is already available) if not.

If an app uses normal-priority GCM messages will it always have access to the network?

Sometimes when I receive a normal-priority GCM message in my Android app the network doesn't seem to be available. Do normal-priority GCM messages automatically grant an app temporary exemptions to Android M's new Doze and App Standby sleep conditions (namely restricting network access)?
Full Context:
I've implemented an App prior to Android-M's release that uses a GCM messaging to tickle installed app instances to download updates on-demand. This is a best practice over polling for updates.
Android-M introduces Doze and AppStandby which seem able to restrict network access when apps aren't using the the new high-priority message type.
Should I switch these tickle messages to high-priority or will I have network access when I receive normal-priority messages? My testing with Android M Previews seems to indicate the network sometimes isn't available.
Network access MIGHT be available and you should not switch your message type to high-priority just to ensure network access is available. You should only switch your message type if the GCM Message is of urgent need to a user on that device. A general rule would be that the notification would fall under the HIGH category when considering the guidance around creating notifications. If you currently use the same GCM messages for periodic sync requests as well as urgent messages you should separate them.
A little more detail on the "Network access MIGHT be available":
As of October 1st up-to-date versions of Google Play services correlate the delivery of GCM normal-priority messages with Doze's maintenance mode, so the network typically won't be restricted. A developer asking this question should consider that a robust app will typically deal with Doze and real-world network connectivity problems at the same time. The app would typically:
Not execute network work in the callbacks invoked when receiving GCM messages.
When a GCM message callback is received by the app the app would schedule work using GCMNetworkManager, JobScheduler, or at the very least SyncAdapter.
The network scheduling routines:
Correlate work execution within Doze maintenance windows.
Allow additional granular scheduling parameters that allow for better user experiences, particular with regard to battery life (Wifi vs Cellular, Charging, etc).
Acquire wakelocks to try to prevent the device from going asleep halfway through performing work. Doze will sometimes ignore wakelocks, such as at the end of the maintenance window.
Have built-in ways of indicating work is complete and rescheduling when appropriate.
Reschedule work using exponential back-off potentially providing a developer's server relief during outages as well as providing users with better battery life under network connectivity issues.
Note: When testing with a device, including one with Android M Preview, make sure Google Play services is fully up-to-date before testing (v8.1+). This typically requires opening the Google Play store app and accepting the Terms of Service.

Parse.com Push Service Battery Impact

I cannot use GCM and I am looking for solutions to support Push service in my application.
I saw PPNS from Parse.com and I am now using it. I starts a consistent websocket connection and checks the connection every 15min. And it also checks it on every device wake-up.
What is the approximate battery impact of just this PushService system?
Is anyone using it and tested it?
TL;DR: That's how push notification works. Don't worry about the battery usage if it's a required feature in your app.
Long version:
From what I understand (and indeed, have developed on my own App using my own MQ), that's what most/all other APIs that handle push notifications do, i.e. they maintain a persistent connection to an MQ of sorts (ActiveMQ, MSMQ, etc.) and subscribe to a specific topic which "pushes" messages to clients.
All of them require a WakeLock in order to keep this connection live in the event the phone is "sleeping" or network connection is recovered in order to make sure notifications are delivered. Some of them even maintain some level of persistence in case a message arrives when connection is lost so that they can playback the messages when they reconnect (although this would be an expensive feature in terms of server resources).
Your users most likely already have a WakeLock in one/many of their installed apps (WhatsApp, Skype, etc. -- You can check this by looking at the permissions WhatsApp requires for instance. One of them would be "preventing the phone from sleeping").
This in turn means that adding an extra WakeLock will have no material effect as the phone never REALLY goes to complete sleep anyway. If yours is the only app that has this WakeLock, then there would be a real cost to the battery but it's unavoidable unless you make sure you persist messages in the queue and only display notifications when the user unlocks the phone which is (1) expensive to maintain on your queue and (2) not very convenient as the user will miss notifications unless they're already actively using the phone so background notifications will go amiss.
I also don't imagine battery life would be hugely impacted if you're simply pinging the server every 15 minutes or so (the interval is usually the keep-alive time for the underlying message queue).
This link should help you understand how a local implementation for messaging works and should give you an idea why the ping is necessary and why you would want to maintain that WakeLock:
http://dalelane.co.uk/blog/?p=1599
edit: added TL;DR

Keep a permanent connection (same LAN) in the background, without using GCM

I need to keep an open connection in the background, even when the app is not running. It's not possible to use GCM because the connection will be in the same LAN as the server, and the device may not have a working Internet connection.
The connection will be some kind of local Push, so the device will just get some short relevant data from time to time (in addition to the keep-alive messages).
My use case is quite specific so I can consider that the battery is not an issue. I may show a huge red warning saying that enabling the feature will drain the battery, or just disable it if the device is not charging.
On the other hand, is quite important that the process with the connection is not "randomly" killed by Android.
I thought about implementing this with a service, but I would like to hear opinions from someone else. Maybe there is a better way to do it, considering the constraints mentioned before.
"even when the app is not running"
That means that your app is not running, and it doesn't have a process. Without using a third part app (such as the GCM service) that awakes your app, nothing can reach you.
You can, however, have a service that remains active and keeps a connection to a server (say, for instance, an XMPP server) to receive notifications and wake up this or that activity.
You can also do that in a separate application.
You can add robustness with a regular watchdog started by the alarm manager, for example.

Android GCM messages take too long to come

I work with GCM in my application, and I have a problem.
Most of the time I get the messages right away, but sometimes the messages come after 5 minutes, one after another, like they got stuck on the way. Is this normal?
The GCM framework part on the client phone use a TCP connection on the port 5228. This connection its used for push notifications, but as every tcp connection it can go on timeout with some routers/carriers that apply strict policies to kill inactive tcp connections (tcp idle timeout).
Most wifi routers kills inactive connections after 5 minutes for example, like mine.
The GCM framework use a keep-alive mechanism to send an heartbeat network packet every 15 minutes on wifi and every 28 minutes on 3G. This keep-alive is not always reliable for all users.
I opened the issue to google here:
https://productforums.google.com/forum/#!category-topic/nexus/connecting-to-networks-and-devices/fslYqYrULto
They agree there is currently an issue.
I've yet to notice that in my extremely limited testing so far, but from my understanding of the documentation, that doesn't sound terribly surprising:
GCM will usually deliver messages immediately after they are sent. However, this might not always be possible. For example, the device could be turned off, offline, or otherwise unavailable. In other cases, the sender itself might request that messages not be delivered until the device becomes active by using the delay_while_idle flag. Finally, GCM might intentionally delay messages to prevent an application from consuming excessive resources and negatively impacting battery life.
Between this and language throughout the rest of the documentation, what you've described sounds like exactly what I'd expect. There's no guarantee of immediate delivery; you'll usually have messages delivered right away, but sometimes you won't.
I am finding the same thing as the original poster. It seems to take up to 5 minutes to "wake up" and then it deals with the messages very quickly.
My app is handling text items in a conversation with a deaf person. The caller initiates the conversation, and the deaf person responds by phone. The delay occurs only in the first step, the new message "out of the blue". Once it's done the first one for that (application, device, system-Id?) the others come through very quickly, almost instantaneously.

Categories

Resources