I have a location service that runs in the background and uses the location manager to send lat and long values to my server every 30 seconds. I want this service to run infinitely long until the user stops the service. But what i am observing is after few hours, the service vanishes as it reaches more than 30+ mb. I want to know how I can make it run as long as it is not stopped by the user?
Few of my observations(correct me if I am wrong):
In the allocation tracker, most of the objects that occupy the memory are the location manager objects.
In the heap, when i cause gc, the memory allocated by my objects are vanishing and so i guess there is no memory leak.
In the applications-->running services, i do not see any services running for 4+ hours. So What I am trying to do is not possible?
Any help/suggestions are greatly appreciated.
Thanks in advance.
I'm not sure why your service starts to take up more than 30 megabytes, but it is possible you are leaking memory somehow.
In the end though, your design is flawed.The best thing you can do is:
Use the PendingIntent method registerLocationUpdates to register for location updates. You can specify the minTime between updates here.
If you need send the position updates precisely every 30 seconds, you can also register a PendingIntent with the AlarmManager to have an intent get sent every 30 seconds.
Have this PendingIntent start an IntentService.
Have the IntentService send the location data to your server.
When the user stops your application, simply unregister your PendingIntents with the LocationManager (and potentially AlarmManager).
I have a location service that runs in the background and uses the location manager to send lat and long values to my server every 30 seconds.
Please allow the user to choose the polling period, including "never poll".
Also, please realize that this will seriously impact the user's battery.
I want this service to run infinitely long until the user stops the service.
This is not possible. The closest you can get is via startForeground(), but not even that guarantees that your service will live forever.
Moreover, this is a serious anti-pattern in Android. Users hate applications that try to run forever, which is why we have to contend with task killers and the like.
But what i am observing is after few hours, the service vanishes as it reaches more than 30+ mb.
In a few hours of keeping the GPS on and the device awake all of the time, your user's battery will be dead, at which point your service and everything else vanishes.
With respect to the memory, if you think you are leaking memory, use MAT to track down the leaks.
Why don't you issue gc programatically - say every hour?
I don't know if it is impossible what you want to do. I guess it should be possible after all.
What makes me wonder is: why doesn't the VM start gc and does instead crash?
Maybe there is in fact an issue with memory leakage?
Avoiding memory leaks-blogentry can give some hints, maybe.
Perhaps someone can give you more sophisticated advice if you give us some code of yours?
Related
I'm trying to develop an Android app that among other things, uses location services to get user location and sends it to a remote server. The user can turn this feature on and off according to his own will, but as long as it's turned on, it will get user location periodically (maybe each 30 seconds, don't know it for sure yet). Also, while it is turned on, it must keep tracking the user even if the application is closed.
So far I've considered 2 options:
Option 1 - Use Service, call startForeground to make sure Android don't kill it (the sticky notification is not an issue to me) and use a LocationListener with the said interval, but this seems rather inefficient as the service would be doing nothing most of the time, I mean, the listener would be called each 30 seconds, send the location to the server and the service itself would spend the next 29.9 seconds or whatever just waiting for the next location.
Option 2 - Doing some research, I've seen some approaches using AlarmManager to trigger some background service (like seen in this post), but I'm concerned that using alarms that often (every 30 seconds) might not be good for the battery and system general performance (in a code snippet in this page of Android's Developer guide there's a comment saying that "hopefully your alarm will have a frequency lower than 30 MINUTES").
Maybe there's another option that I still haven't thought about, or maybe there's a way to put the service from option 1 to sleep for some time or something like that. Bottom line, I'm looking for the approach that doesn't impacts on performance, consumes the minimum amount of battery and has the least chance of being killed by Android.
Any help and/or suggestions are welcome.
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".
I've created an android app that is so far working quite well. It contains a local service which is responsible for getting the users location every couple of minutes and relaying that via UDP to a collection server which is in turned displayed on a web application map.
The app needs to be constantly running unless the user explicitly signs out of the application. Currently, it seems the OS is shutting down the service and restarting it as needed. I can see this because normally it would report its location consistently every 2 minutes. Instead, there are gaps in these intervals.
So I'm looking for some advice on how I can write a service which (at the battery's expense unfortunately) can stay running always and pool the location service just enough to send accurate fixes at a 2 minute interval.
I have a well working code base so far, so if demonstrating where I currently am with code would help, don't hesitate to ask.
Thanks in advance to those that lend a hand.
Your best bet is to use the AlarmManager to wake up every two minutes, do some processing and quickly go back to sleep.
If you think you're hardcore, you could even use a wake lock, but that will keep the phone's CPU turned on persistently without mercy. You don't want that.
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.
I believe it's because of some power saving option or whatever but I cant debug it since it only fails when it's on battery
I have a service that checks on a webpage every 60 seconds
I use an asyncTask in the service to do this
and I make it Thread.thisThread.sleep(60000); before checking
am I doing something wrong? could the sleep function cause the server to be stopped by android?
I have a service that checks on a webpage every 60 seconds I use an asyncTask in the service to do this and I make it Thread.thisThread.sleep(60000); before checking
Please don't do that.
First, make the period configurable, including a "don't do this, ever" option. Users really do not like it when developers write apps whose primary purpose appears to be to use up a ton of battery life. Keeping the device awake and polling a Web server every minute is going to use up a ton of battery life. It is behavior like this that is causing users to run to every task killer they can find.
Second, particularly for periods greater than a minute or so, please use AlarmManager and a [WakefulIntentService][1]. Schedule the AlarmManager to invoke your application at the user-chosen period (ideally via setInexactRepeating()). Have the WakefulIntentService poll your Web page. If you follow the documented WakefulIntentService recipe, the device will stay awake long enough for you to get your data, then will fall back asleep. Your service will not remain in memory all of the time. You get your functionality, and the user gets better device performance.