Goal
Create a long-running background service with a network connection, similar to Zello app.
Problem
Starting with API level 26 (Oreo), there're tight restrictions on background services and their network activity.
Looking at the Zello app which has a constantly running background service which is able to accept audio and text messages even if the device is sleeping, I wonder how they achieved that?
Their service is not running on the foreground. Also, it doesn't look like they use push messages for that, since the app works quite stable in conditions where there's a problem with push messages reception (e.g. low-end Xiaomi phones).
Any ideas would be appreciated.
From what I gathered these apps use the Firebase Cloud messaging service:
https://firebase.google.com/docs/cloud-messaging/
The Firebase Service is embedded in the Android system and maintains a constant network connection to the firebase server. The apps then contact the firebase server which in turn to notifies the destination device.
Advantages:
The Android system is responsible of keeping the server connection alive and running
The network load is minimized because one connection is used for all apps using the firebase service.
Disadvantages:
All data is sent through the firebase server and is therefore (in theory) directly accessible by Google
Depedning on how many devices use your app, you need to pay for the service.
A similar question asked might be helpful in tackling the problem too:
How does push notification technology work on Android?
These apps don't have long-running services with constant network connections. They use push notifications. When there is a new message for a user, the server sends a push notification to wake the device up.
Related
For devices that don't have Google Play Services, there are a few options to be able to receive push notifications.
Those options can be Baidu in China, Pushy, Facebook own push notifications, etc.
But I cannot understand how is that even possible to overcome those two main problems :
Since we cannot have an "SDK" of some sort like the Google Play Service on a device-level, our only option is to integrate it on an app-level. This means, we cannot have one socket connection to the push server that would be mutual for all apps, like the GCM does. Instead, we need to have as many socket connections alive as the number of apps installed.
Even if we close an eye on problem number 1, to make that connection survive Doze and App Standby, we would have to handle them in a Foreground Service, which is the only way to guarantee its running even after killing the app, or when the device enters Doze state.
But how come we don't see the notification of a foreground service in the notification bar in Chinese phones, or apps that use Pushy for example?
Are they simply polling the push server periodically? with AlarmManager (marked with setAndAllowWhileIdle) and a BroadcastReceiver ? that would be too resource-heavy and inefficient.
What I'm trying to ask is:
Whether these apps are relying on FCM/GCM (or any other type of) push notifications for syncing their data or are they using a socket connection in background through a service?
If they are relying on push notifications then why they don't have any loss in receiving notifications (in background) while I miss 10-15% of notifications in busy hours.
And if they are relying on a socket connection in background, then
ain't this eat battery like a dinosaur?
What I have found is that if I force stop Messenger and Facebook I still receive messages but somewhat late than usual.
Plus there is an option of 'Allow background activity' in Messenger, Facebook, Slack and Skype, which when I disable, I can't receive a notification at all.
Interesting this is that WhatsApp don't have this kinda option in its app info and If I just force stop WhatsApp it simply stops showing me message notifications.
Whether these apps are relying on FCM/GCM (or any other type of) push
notifications for syncing their data or are they using a socket
connection in background through a service?
They must be relying on FCM.
If they are relying on push notifications then why they don't have any
loss in receiving notifications (in background) while I miss 10-15% of
notifications in busy hours.
They must be using FCM high priority which are reliably delivered in doze mode.
And if they are relying on a socket connection in background, then
ain't this eat battery like a dinosaur?
They might not be running CPU intensive work.
Mobile applications like Whatsapp must be requesting permission to exempt them from Doze/battery saving and App standby mode. you can refer to my answer here for more details.
Adding on to Sagar answer.
1)Never show the notification from FCM notification payload unless required.
2)Once High priority FCM received you can do network operations for sometime and fetch data from server and then show up. If it fails whatsapp do puts ups with special msg.
https://www.quora.com/Why-do-I-get-You-may-have-new-messages-notification-on-WhatsApp
3)use foreground service/ cpu lock tied with app icon momentarily till the data is fetched ,later close it.
PS:No whatsapp do not request for Battery Optimization. they probably reply on FCM high-priority message.
Well I have no idea what EXACTLY are they doing in background (maybe no one has), but lets take a look at the concept.
In distributed systems and web applications, no one usually goes for push notification system in background for their services to talk to each other. While it is possible, but these alive services have better options to choose such as publisher/subscriber pattern and technologies that bring this service for us (ex: reddis, MQ, Nats.io), they are high available and with no single point of failure, and the data is still synced over all server.
Your second question starts with an if which might have a false result. But lets say they do. You should never compare your "client to server connections and logic" with "Server to server connections and logic". What I mean is maybe they use Reddis pub/sub service, it doesn't mean their client should use same system to connect to server. It has a big cost to keep those servers connections alive while supporting big numbers of messages to sync.
And about third question. No, socket connections don't always drain battery. It really depends on how you use them. You can check for sockets idle modes too.
Also, systems like firebase might be still be able to send notifications when an application is not running or not connected to server. Happened to me a lot of times in Telegram, when government of Iran has blocked it but I could still receive notifications. Its whole other story, I think you can find more about it with a little search.
PS: Please avoid asking too many questions at once. thanks.
For services which exchanging frequently messages like messenger, WhatsApp, and WeChat etc there are message brokers (Activemq Artemis, RabbitMQ, Kafka etc) which is running on the server and having active stomp connection with each client app. This broker forward the message to the respective client as it received, and if the client is not online then it hold the message in memory untill the client become online. For further details that how a message broker works visit the official website of my favorite Activemq Artemis docs.
I have an Android app, instant messaging is one of the key features. For implementing the IM feature, we use our push server based on websocket.
For my app, I have a PushService, in this service, I establish a websocket connection which connects to the push server and receive push message.
The code works well when app in foreground (i.e.: works well while user plays with the app), but when the app doesn't in foreground, it stop receiving push messages after a while (about 1 minute). Same issue when user turns off screen.
I have set a repeat task with AlarmManager, which checks the websocket connection status, if it is not in connected status, then re-try to connect so as to back to normal to receive push messages.
This works well below Android M, for example on the Android 5 phones, it seldom misses push messages. But on Android M / Android N, it doesn't work as good as on Android 5.x. I can confirm the service itself is keep running , check from the 'Running services'.
I've noticed that starts from Android M, Android introduces Doze and Standby mode, not sure if they are related, if yes, how can I make the app continue to work again? On my phone the WeChat and Skype Android App work well, what's the mechanism behind it? I know FCM is the best solution, but I cannot use that for customers in China, so I need a workaround.
Edit: I had proposed to use a foreground service but PM doesn't like the notification tray always being shown in the status bar he wants to keep it clean.
Any advice will be appreciated!
I don't know about WeChat or Skype communication, but i know the WhatsApp using you own service notification with the same tecnology of FCM.
They using the Jaber server with implements the XMPP communication protocols
link
I am from Apple world, so I don't have much experience with Android.
But what I am looking is a way that Android devices receive push notification, without using any third party servers. Notification need to be standard Android notification (look and feel)
The reason I need this is, because I would need this in a room that does not have access to outer world. (can't connect to any server) But I have my own WiFi so users can receive push notification from my server via my wifi.
I know that on iOS this is not possible, what about Android?
it is possible using Service left running in system (background) after app exit. some samples HERE, you should be interested in START_STICKY flag
you have to keep some connection (socket?) or interval requesting (not so well, but possible) inside your Service. Google Services (including Firebase) does that by itself and "redeliver" received push messages to properly declared (in manifest) app
Can Pusher messages be received on Android/iOS app when the app is closed or the phone is turned off?
What i expect to happen...
When phone is on & app is on, it's pretty straight forward from the Pusher docs on how to react to pusher messages sent to the app.
When phone is on & app is closed, the phone should receive a notification that something has been sent to the app.
When phone is turned off, a notification should be received by the phone when it's turned back on to notify that something has been sent to the app.
Are these even possible? If yes, what are some suggestions to lookout for? If no, what can be some workaround?
When an application using Pusher moves into the background on iOS and Android the connection to Pusher will likely stay active for a few minutes. But eventually that connection will be closed. You can't stop that happening within your application (although there may be a "hack" around stating your app is a Voice app when submitting to the Apps store).
Therefore, you should monitor your application moving to the background and put a fallback in place to delivery messages to the phone when it's not connected.
Please see How get pusher events when the iOS app go to the background? for libPusher (the Pusher iOS library).
Here's an extract from the Android Processes & Threads Lifecycle docs on a "Service Process":
A process that is running a service that has been started with the startService() method and does not fall into either of the two higher categories. Although service processes are not directly tied to anything the user sees, they are generally doing things that the user cares about (such as playing music in the background or downloading data on the network), so the system keeps them running unless there's not enough memory to retain them along with all foreground and visible processes.
So, running a Pusher instance in such a thread is a viable option.
However, there will still be occasions where the user goes offline. In that situation your server you can detect if a user is online by querying the Pusher HTTP API or by using WebHooks where your server can be instantly informed if the user has gone offline or come back online.
Using the mechanisms above you can facilitate smart notifications; if the user is online (the app is in the foreground) then send the message to them by Pusher, if they are offline (the app is in the background) then use an alternative mechanism for delivery (native Push Notification, SMS or email).