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.
Related
I would like to make an app that always works in the background (from boot up), which sends GPS coordinates to a server. This app should ALWAYS be active and should never close.
Should I use the services? I would like to use UDP sockets to send coordinates but I accept alternatives. I would also like to avoid using the google API.
Thanks a lot :)
If your app need to run in the background , you need Service and you need to make it a foreground service which means you need to show a notification to the user as long as your application is running.
To open app on device boot, from Android O, its not allowed. You will get an IllegalStateException.
The main reason for this is to prevent exactly what you are trying to achieve.
Its not good to keep running an app in the background and its especially bad to keep tracking users GPS coordinates and send it to the server.
Because it will drain the battery very soon.
However it is possible to keep a foreground service running which can take the GPS coordinates and send it to the server. But for that user has to open your App first.
Please refer to
https://developer.android.com/about/versions/oreo/background#services
Other alternative is to use JobIntentService which will schedule your tasks in smart ways to avoid draining users battery and data.
Regarding UDP sockets , it depends on your backend.
I am developing multiplayer game using Socket.io library. it Works Well.
But, in android 7.0 and above, system automatically suspend all network work when my app is in background. (And I must need to keep alive my socket connection).
I research about it as described here.
but, i can't understand. So, Please provide solution for that.
Unfortunately there's bad news and some good news for you on this.
Bad:
Since android marshmallow and above, there's a concept of a doze mode. If the device stays put for some time (can't confirm the duration for this and not disclosed by google), the device will go into doze mode and will suspend all network activity. There will be short maintenance windows where in you will be able to do syncs and stuff. Small workaround, do not target 23+ apis, i say small because i have observed this to not work on some phones. Another way to potentially bypass this would be to whitelist your app from battery restrictions but according to google guidelines, i don't think your app will qualify for that.
Worse news is that start from API 26, background services will also get suspended completely when app is totally backgrounded and has no visible component (a notification or a foreground service etc...). So oreo will be worse.
Good:
You might not really want to constantly keep the socket open. Instead opt for bursts of syncs. I personally have a job run every 30 - 60 mins or so to try and sync up.
You can leverage the JobScheduler apis and it will automatically handle the doze modes and stuff and you can make them run periodically when there is internet connection. While the job is running, you can connect to your server, do your thing and shut the socket. This is what google wants and is pushing all devs towards.
UPDATE 19-Apr-2021
WorkManager is the new and the best way to deal with doze mode and background limit restrictions.
Another alternative would be to have a foreground service with an active notification displayed which would constantly be connected via your socket. This will be visible to the user and it will not only annoy them that you are constantly using their data, it can also be bad for the battery. Alternative to this again is using the job scheduler to schedule and run a foreground service periodically so as to be transparent while also syncing your data every once in a while. The latter approach is what WhatsApp does, they have a job running which syncs all incoming messages with a foreground service once in a while.
In Short:
You will not be able to keep it alive always. You can try doing it in bursts using one of the methods that i described and know currently (maybe there are other alternatives that i don't know, i have tested these and they work) You will have to compromise, sorry.
I m actually developping an application in which I need my phone to be active even if it's locked.
Explanations
The applications connect to a remote nodejs server using socket.io. In that case, it cans sends realtime messages to a socket server that can handle this and make anything it needs. The fact is the socket management is in a service class (extends Service class).
The problem is that, when I lock the phone, the device stop to send heartbeat, and so is disconnected (by timeout) from the nodejs socket io server.
Actually, the normal behaviour of an android phone locked is to sleep. Meaning no activity.
Question
I was wondering how does others applications to be able to receive notifications, and so handling notif by a background service. it means that there's an activity even if the phone is sleeping right ?
How can I do to make this without draining a lot of battery ?
You use wake locks to keep CPU awake while locked: https://developer.android.com/training/scheduling/wakelock.html
You should aquire it for a small amount of time to not drain battery.
I think if you will acquire a phone wake lock it will drain the battery which is not a good thing . On the other hand, The use of service is really very good,and you talk about the notification of other apps and they works in background because notification does this by default
So in you case As I do not know what are you really trying to do with server, But Service is good option. Service works even your mobile is locked. But in your case if it stops make sure it is not bind with the class.
You should make sure that the Service is not binded with the class or activity as when the activity will be destroyed the service would also be. Just trigger your service and let it handle all the things in background.Please read the discussion in this link. It might help you in understanding better.
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
My company has, in essence, undertaken a project to replace some of its pagers with stock smartphones running Android. As long as they are signed in, the device should be listening on a particular socket to receive "pages" from a server. My naive implementation was to create a foreground service that 1) kicked off a listening thread, and 2) holds a PARTIAL_WAKE_LOCK.
This works fine unless the device has a long period of inactivity, 1+ hours. Then, it appears that the OS shuts down my app's process, understandably believing it to be not in use.
I completely understand their reasons for doing so, but I'm wondering if I can somehow get around this restriction. Are there ways to signal Android that my process really is important enough to keep alive/the device awake? I learned both Java and the Android API for this project, so there are plenty of areas where my knowledge is incomplete.
Failing that, given the description of my business needs, how would you suggest implementing this functionality? While the user is signed in to our custom app, the device should always be listening.
Thanks to everyone for reading this question.
The OS won't kill your process if you are using Service.startForground(). This is what things like music playback use, and you wouldn't want those to be killed after some amount of time.
That said, for this kind of thing you generally wouldn't need to make your service foreground -- when the system does kill your process because it has been sitting around or needs the memory, it still knows the service wants to remaining running so will restart the service shortly after that. This is how Google's own services work, they have one .apk that has a background service running that keeps a network connection open to a Google service which reports back when interesting things should be done like sync new e-mail, retrieve and deliver a C2DM Intent, etc.
Also you should not hold a wake lock during all of that time. You will kill the battery, especially on some devices like those with Samsung's Hummingbird processor. The right way to do this is to just leave the socket open and let the device fall asleep. If data is delivered to the socket, the CPU will wake up to deliver that data and at that point you should acquire a partial wake lock just for the time you need to read and process the data.
What you describe sounds like a job for Android Cloud to Device Messaging Framework.
It's currently not completely open but there is a signup link on that page. I signed up and was accepted within 20 minutes of my application. Worth a look IMO.