How reliable is FCM upstream message delivery? - android

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.

Related

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.

Using websockets for Android chat

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.

Android Websocket Service Persistent Connection

I implemented a chat application in Android with websockets. However when the user closes the application, the websocket connection to the server is lost and no new messages can be received.
I am essentially lost and do not know where else to turn, how can I setup the service in the app to stay connected to the server as the user logs in as well as after the app has been stopped?
As we're all aware, continuous background code execution is not feasible on Android; different ROMs will man-handle your background services without any guarantees (e.g. START_STICKY will not get your service restarted on some devices), so we need to do the best we can with the code that is reliably executed.
In this situation, you have a websocket server delivering continous information to your client. When your app is in the background, it may miss out on some data. When your app returns to the foreground, your information may be out of sync, so you need to synchronize again with your server, and then reconnect to your websocket.
In my chat app I achieve this by checking whether my websocket service is running onResume in an activity which is a superclass of all the activities that I want to have access chatting data (i.e. not login/registration activities). If the service is not running, I synchronize my data by pulling the changes from an endpoint and then restarting the service. This way, even if the service is killed in the background I will still get the latest data and real-time experience once the app returns to the foreground.

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

Why do I need to use two services in my app?

I'm developing a MMS-like app on the advanced interphone for the airport using private network. I receive the messages from the specific server using socket. If the user log on the message system, the user should always receive the messages until he logout.
My idea to solve such issue is as follows:
By using one local service as a Manager service, this service will receive the command from the UI,and one remote service to maintain the connection with the server.
When the local service receive the different cmd from UI, it will check the UserState stored in a Application sub-class, then send the required information to the remote service.
The remote service will generate different message-packets to send to the server.
While the receiving procedure is like: After the remote service receiving and parsing different messages(such as sms,address list of contacts), it send necessary strings, file URI or object to the local service, and the local service send the info to the activity.
I don't know whether this idea will work well. For I need a Role like Manager to handle different sending cmd and receving messages and a consistent connection, what the structure should my app be like?
use one local service as a Manager service,this service will receive the command from the UI,and one remote service to maintain the connection with the server.
No. Use one local service, period. A second service adds no value; a remote service makes your app worse, not better, by wasting RAM, CPU, and battery for no benefit.
can you tell me an method how to make the connection service is always running?
You cannot have a service running "always". If you use startService() and startForeground(), it will be the least likely to be automatically terminated. However, the user can elect to force-stop your app or use a task killer if they so choose.
For in service document, local service can be killed more easily than a remote service(running in its own process) by the system.
That is incorrect.

Categories

Resources