How to implement permanent, regular, background location updates? - android

The app needs an underlying feature that picks up locations and sends them to a server. This must happen regularly (approx every 1-5mins) but most importantly it must happen all the time, never stopping, protected against the OS shutting processes down to reclaim memory, and when the app itself is not running.
The following solutions have been suggested to me. I'm familiar with handling Android locations, the issue here is to ensure they continue, even if the app is not in memory, and to persist through memory reclaims.
SERVICE. Use a service to collect location events and handle them. Use the boot and screen-on broadcasts to ensure the service is always running (and possibly also increase the service priority to protect from memory reclaims).
ALARMS. I gather these can be shut down when memory is short. How would I protect against that? This seems an ugly solution as the locations will arrive on a schedule anyway, so it seems unnecessary to have another time-based component.
LOCATIONS VIA BROADCAST. Locations delivered via a broadcast intent would mean I can then handle the location events in a broadcast receiver. Will these location alerts continue indefinitely? Will anything other than device shutdown or the app turning them off cause them to stop?
What's the most durable approach?

This must happen regularly (approx every 1-5mins) but most importantly it must happen all the time, never stopping, protected against the OS shutting processes down to reclaim memory, and when the app itself is not running.
This is not strictly possible, on a variety of fronts.
Let's take them one piece at a time:
This must happen regularly (approx every 1-5mins)
You may not be able to get locations, period, let alone every 1-5 minutes. The user might have all location providers disabled. The user might have the device in airplane mode. The user might be in a large building (blocking GPS) with poor connectivity (making the network provider unreliable).
never stopping
The user can always get rid of you via the Manage Services screen in Settings or a task killer. If they do so, particularly on Android 3.1+, your app will never run again for any reason until the user starts an activity of yours (e.g., via the launcher). The user could also uninstall your app, of course.
protected against the OS shutting processes down to reclaim memory
You cannot guarantee against this. You can reduce the odds, but that is it.
Now, let's look at your various solutions:
Use a service to collect location events and handle them.
From the way you phrase this (and subsequent sentences), you mean an everlasting service, one that is designed to run 24x7. By definition, this means that your app is running, which violates one of your rules. Assuming you relax this rule, this solution massively increases the odds that the user will get rid of your service, and it increases the odds that Android will get rid of your service. You can minimize the latter by use of startForeground().
ALARMS. I gather these can be shut down when memory is short.
Not that I am aware of. However, if the user gets rid of you, your alarms will be removed.
This seems an ugly solution as the locations will arrive on a schedule anyway
No, they will not. The time parameter on requestLocationUpdates() does not mean that "locations will arrive on a schedule anyway".
Locations delivered via a broadcast intent would mean I can then handle the location events in a broadcast receiver.
No, you cannot. You have indicated that part of your work will be to send this data to a server. You cannot reliably do that on the main application thread, as it may take too long. A getService() PendingIntent, pointing to an IntentService would be more reliable.
Will these location alerts continue indefinitely?
No. See below.
Will anything other than device shutdown or the app turning them off cause them to stop?
The user can get rid of your app (uninstall, task killer, Manage Services). The user can disable location providers. The user may enter an area where the location cannot be determined. Etc.
Also, the device may fall asleep, AFAIK. It's possible the system keeps a WakeLock for the duration of your registered request for updates. It's even possible that the system will use AlarmManager internally to arrange to wake itself up on your supplied period, so it does not have to keep the device awake continuously. However, you will want to test this thoroughly.
What's the most durable approach?
If the concerns in my previous paragraph are handled by the OS, your third option is probably the most robust. Use startForeground() in your IntentService() and call stopForeground() just before exiting onHandleIntent() -- even short-lived services started by AlarmManager may get killed off due to low memory, much to my surprise.
That being said, your desired behavior seems like it may consume more battery life than the user might want. Please allow the user to control the polling period, including an option for "never poll, I'll update things manually".

Related

Android 8.0: keeping a background service alive

I believe you all are already familiar with "background service limitations" imposed on Android 8.0 and up (https://developer.android.com/about/versions/oreo/background.html#services).
I'm having a very particular problem right now. My application is meant for a very specific use case. App checks for certain data on the server every minute and in case of some wrong value, user is being alerted immediately. Obviously so far application was running in a form of background service and my customers never cared about (obvious) battery consumption coming from complex calculations that are being performed every minute.
Now, whole idea is that app needs to stay alive, working and in background (even with permanent notification, i don't have anything to hide) regardless of anything! If phone is in a deepest possible sleep state - service needs to keep running. If there's 2% battery left - service needs to keep running. So far, i managed to achieve that using alarms and "guardian services" which prevented any way of stopping the background service while app is installed. But now, with Android "0" - what's the way to go? Is there a JobScheduler that will guarantee execution at given rate (every minute) regardless of anything?
How SMS / Phone, WhatsApp and similar apps achieve that "awake no matter what" state?
That's what Google tells us.
A process is not forever.
If you feel you need your foreground service to stay alive
permanently, then this is an indicator that a foreground service is
not the right answer.
Effective foreground services on Android
I think you could use repetitive tasks with WorkManager or change the architecture and use FCM. In any case, Google will not let us work as it did before.

How to put GPS system service in a local service so it can be killed to turn off GPS

Like many others, I want to have an exit button that will turn off the GPS when the user leaves the app to conserve battery life. Many discussions are posted basically saying this cannot be done but I have an application that does it so continue to try and find a way. The developer of that application told me that he runs the internal GPS in a service that he wrote and that his exit key kills that service and vola, the GPS indicator goes off instantly.
My app is very time sensitive and I would like to use the equivalent of onLocationChanged that I use now when using the LocationListener part of the system service but have the system service inside a service I write so that I can kill it.
My question then is can I put the system GPS service inside a local service without adding any significant delay, without me having to poll the local service for updates. Any help on how I can do this would be appreciates as this is my first Android app and although I have written tons of C and PHP code, this is new territory and a bit strange.
Like many others, I want to have an exit button that will turn off the GPS
You cannot "turn off the GPS". You can tell Android that your app no longer needs GPS (e.g., you no longer need GPS updates). Android will then determine whether or not to power down the GPS radio, depending on what else might be trying to use GPS at the moment.
when the user leaves the app to conserve battery life.
You do not need a button for this. Simple apps, where only one activity needs GPS access, can simply request location updates in onResume() and remove them in onPause(). More complex apps might request location updates on the first onResume() that needs them, then remove those updates in onUserLeaveHint(), or do a reference-count of resume/pause operations to determine when to remove updates.
There may be scenarios where you really do want the user to have to explicitly say "stop using GPS" by clicking a button, but if you can avoid it, please do so.
The developer of that application told me that he runs the internal GPS in a service that he wrote and that his exit key kills that service and vola, the GPS indicator goes off instantly.
Somehow the developer needs to determine when to start and stop this service. Rather than starting and stopping the service, they could request and remove the location updates, and have the same effect, while consuming less heap space and making it less likely that the user will attack you with task killers and the Force Stop button.
IMHO, the only reason to use a service with location updates is because you specifically want to consume location information in the background with no activities around.

Service requirement approach in Android

I need to run a background service in Android mobile which runs 24*7, And on Start & On mobile low battery and Hit a webservice every 1hr. Can you please suggest me any approach. I tried reading few articles but did not get any idea. I know here I need to paste some code after trying something. But I did not get any clue. Please let me know how to approach?
You will probably need to use the method startForeground(int id, Notification notification) to prevent the system from killing your Service as stated here:
A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)
Then you would need some kind of scheduled task to run every hour. Something like a ScheduledThreadPoolExecutor is ideal for this purpose, using the method scheduleAtFixedRate (Runnable command, long initialDelay, long period, TimeUnit unit).
The task that needs to be done each hour must be implemented as a Runnable and submitted to your ScheduledThreadPoolExecutor:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( 1 );
executor.scheduleAtFixedRate( new MyRunnableTask(), 0, 1, TimeUnit.HOURS );
The Runnable task should be something like:
private class MyRunnableTask implements Runnable {
public void run() {
//Do what needs to be done.
}
I need to run a background service in Android mobile which runs 24*7
Please don't. For starters, it is not possible.
Users complain loudly and often about services that "run 24*7", because the services are tying up system resources (e.g., RAM) for no value. As a result, between third-party task killers and Force Stop options in Settings, users get rid of such services. When they do, particularly on Android 3.1+, your application will not run again, ever until the user manually launches an activity of yours from the launcher.
Android itself will get rid of such services on its own, because too many developers are too sloppy with their service management.
And on Start & On mobile low battery and Hit a webservice every 1hr.
Based on this list, you do not need "a background service in Android mobile which runs 24*7". You need to do work:
when the device starts up
when the device's battery is low
every hour
You can find out when the device starts up by the ACTION_BOOT_COMPLETED broadcast Intent. You can find out when the device's battery is low via the ACTION_BATTERY_LOW broadcast Intent. You can find out when time elapses via AlarmManager, where you establish your own alarm schedule (e.g., every hour).
All three of these triggers should call startService() on an IntentService. The IntentService will allow you to "Hit a Webservice" via its built-in background thread. And, the IntentService goes away when that work is complete, so you are not taking up memory all of the time.
And, if you want to wake up the device out of sleep mode for the every-hour condition, you will probably need to use something like my WakefulIntentService, as otherwise the device may fall back asleep while you are trying to "Hit a Webservice".
This way, your service is only running and taking up resources while it is actively delivering value to the user. It is not running and taking up resources when it is simply waiting for some other event to occur (e.g., the next 59 minutes).

Android background service and AlarmManager

I am coding an android application that gets the user position every 5 minutes, stores it in the database and sends it to a server.
I have read many ways of doing it, I was going to do the following:
User starts the application
The main UI activity starts a service.
The service runs in background and keeps turning on and off the gps, and creating new
threads that will save to database,and send the data to the server.
But I have seen that it can be done with a "Remote service" (http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html) or with an AlarmManager that schedules starting this service every 5 minutes.
The service will need to be running always: it is important that after every interval (5 minutes), it is executed.
I think I need some clarity here.
Thank you for your help,
I am coding an android application that gets the user position every 5 minutes, stores it in the database and sends it to a server.
Please allow the user to choose the location provider. Not everybody has GPS on their device. Not everybody has GPS enabled. And, not everybody will want the power hit of GPS being turned on every five minutes.
Please allow the user to choose the polling period, including "never poll -- I'll refresh the information manually from the activity". Also, please honor the background data setting (deprecated as of ICS).
I think I need some clarity here.
If the polling is supposed to go on even if the activity is not in the foreground, use AlarmManager. However, most recipes for using AlarmManager will have the real work (in your case, GPS fix and network I/O) be handled by an IntentService. This will not work in your case, because GPS is asynchronous -- you cannot just get a fix whenever you feel like it. It will take a long time, possibly forever, to get a fix, so you have to deal with the delay and eventually timing out the operation. Writing a Service to do this is possible, but tricky, particularly if you are aiming to collect this information even if the device falls asleep.
If, however, the polling is only supposed to go on while the activity is in the foreground and the device is on, I wouldn't bother with a Service at all. Just have the activity use postDelayed() to set up an every-five-minutes scheduled bit of code to run, then have it do the work.

how to structure my app to run in background

I am new to Android, and I need some advices for start up.
I want to build an application, which will show up, when the user gets into some hot situation.
By hot situation I mean:
the GPS/cell coordinates are in known zone;
known Bluetooth device detected;
known Wi-Fi network detected;
weather info has change;
I see something running in background and when one of the clauses hit, it will trigger and open the app.
How to get started?
How do I make sure my app won't be shut down?
As I read somewhere that Android OS will terminate apps if memory out occurs or consumes too much, and my app would consume a lot, making repeated measures/checks to see if situation changed.
Regards,
Pentium10
You need to use a Service for the part of your application that runs in the background.
You might find the Application Fundamentals document in the Android Developer Documentation helpful. It says this about Services:
A service doesn't have a visual user interface, but rather runs in the background for an indefinite period of time. For example, a service might play background music as the user attends to other matters, or it might fetch data over the network or calculate something and provide the result to activities that need it.
In you case you might find the LocationManager Service helpful. It is a system Service which will you can use to notify your application based on GPS position.
However, I think you'll have to write your own Services to monitor Wi-fi, Bluetooth and weather.
You can use the AlarmManager Service to get your Service to perform particular tasks at certain intervals.
It depends on how & where you want to deploy your application. In my experience it boils down to
you create an application for a specific use case where battery drain matters less than accurate results (showcase situations, prototyping, ...)
you want to distribute the application to users.
In case 1) just create one service that aggressively polls the sensors / web services. Use the AlarmManager to send a REFRESH intent (AlarmService.setRepeating(...) ).
That REFRESH intent will restart the synchronization service everytime, even if it was killed by the system. onStart() will be called everytime the REFRESH intent is emitted. You can do heavyweight setup logic in onCreate() as this will be called everytime the service is created after it was destroyed. WARNING: This will possibly drain the battery very quickly.
In case 2) I would create several services and let the user configure different polling intervals for each service to limit battery drain. I can see for example that bluetooth should be polled more regulary than GPS as it is more likely that a bluetooth device suddenly appears than a user moving extremely fast.
Weather sounds extremely expensive (network lookup, possibly triggering a network connection!)
Please do not try to be too persistent with your app in case 2). It usually makes a lot of sense for a phone to kill memory / power draining services.

Categories

Resources