Getting user location practice in service - android

I am once again facing a problem. I am having a alarmManager set up to start a Service which gets user's location every minute. My question is, is this the best practice? To recreate the service every minute, make and register new Location listener and wait for one OnLocationChanged callback ? Or is there a simpler, prettier way of doing it ? Also, don't forged, the screen will be turned off and the device asleep so I need to work with WakeLock too

You can simple start the service once, get a wake lock, and then poll for the location with a time interval of 60 seconds. This will remove the need to recreate the service every time. However, it will be possible for your service to be killed by Android if necessary. You can have it restarted automatically by returning START_STICKY in onStartCommand().
As a general rule, getting a location every minute is going to be very battery intensive, and should be avoided, especially for long periods of time.

Related

Getting elapsed time from AlarmManager

Pretty new to android, so forgive me if this is a dumb question...
So, I'm making an app with a countdown timer that will ring periodically, and then again when the countdown hits zero - simple enough. However, I want the app to keep running even when the user closes the application or the phone is asleep, so that whenever the timer rings, the app will wake up and display an activity showing the time until the countdown is finished. To do this, I'll need to use a service, and lo and behold, the google devs made the AlarmManager service just for me! Sweet!
However, I noticed 2 things:
1) the AlarmManager class has no default constructor, so I'm assuming I can't just extend it and tack some logic on so that I can get all this done in one shot. Ok, cool - I'll just make a service that instantiates AlarmManager at the start, and implement my logic there.
2) In the documentation, I don't see any way of getting either the elapsed time or the remaining time from AlarmManager once it is running.
So, my question is: does this mean that I will need two timers that I start at the same time? Say, an AlarmManager to wake the phone up and call the activity, and a CountDownTimer contained in the service to hold the remaining time and call the alarm ringtone?
Thanks for helping out my clueless ass.
You could extend AlarmManager. However the common way is to get an instance of it, which is running as a system service.
Get the instance using Context.getSystemService(Context.ALARM_SERVICE) and you will be able to register your PendingIntent to that system service, which is independent to your own app. The PendingIntent can either start an activity or send broadcast with some Intent. You don't monitor the elapsed time constantly in AlarmManager. Rather, you calculate the time difference between the current time of your method call, and the desired time to fire your event. And then you set an alarm in AlarmManager with a PendingIntent representing the action you wish to take at that interval, or a time point.
On the other hand, if you want maximum flexibility, run your service as foreground service and listen for system broadcast like ACTION_TIME_TICK, which is fired every minute. Alternatively if you don't run service in foreground you could also run your service with START_STICKY, which guarantees that your service will be restarted after the system kills it (due to sleep or closing app). Think this as a background service that is constantly running. This provides you a lot of flexibility in your implementation.

Activity, service or fragment?

I am writing an app which needs to monitor the current battery level, after every 15 minutes or so, continuously.
To try and make it relatively efficient, currently, I am using AlarmManager.RTC, with PowerManager.PARTIAL_WAKE_LOCK, and an setInexactRepeating of 15 minutes.
This will be a sort of battery drain % monitor app, so I need this app to be always logging what it finds every 15 minutes, even after boot. It checks for battery level, if the phone is charging and some other things such as if wifi is enabled, if screen is on etc. and then writes these values in sqllite for later analysis.
So which one would be the best way to go about it:
AlarmManager on an activity in a BroadcastReceiver in the
activity
AlarmManager and a service
Headless fragment
Or a better option is suited?
service - for background work, receiver for device boot event(where you should start service), and activity for showing results.. and Timer for timer taks?
do you realy need AlarmManager for this task? )

best way to implement location update service

I would like to develop an application - a service - that updates the user location to server, say, every 1 hour.
I understand from the Android docs that I have to use "Android Services" and I have to do the work on the onStartCommand()
But since I need to keep sending these location updates every 1 hour, then I need to run infinite loop inside onStartCommand() ... right?
Now, my questions are:
What will happen if system kill the service, I know my service will get started, but would it call onStartCommand() also?
Is there a better way to implement location update, for example, is it possible that the system call the onStartCommand() method periodically every 1 hour?
AlarmManager, as mentioned by the other posts, is what you're looking for.
However, It's against Android Best Practices to run things "forever, every hour" or so. If you start off by thinking "every hour, every day", you might take actions that would harm the user's battery life.
Turning on gps every hour, waiting for it to acquire a lock, then turning it off, uses a lot more battery life than if you were "smarter" while checking location.
If you do it right, e.g. setInexactRepeating, try to use WiFi location, set listeners for location update, then you can have your cake (long battery life for the user) and eat it too (still get the information you need).
For some good tips about how to keep your app from taking up too much battery (and possibly getting uninstalled), take a look at this video from GOogle IO 2012: http://www.youtube.com/watch?v=PwC1OlJo5VM
EDIT: Take a look at this, too:
http://developer.android.com/reference/android/location/LocationListener.html
You can set a listener that only gets called when the device's location is changed. YMMV, but take a look.
One possible way is to check out the AlarmManager. You can schedule your app to be run on an interval. You can also determine that perhaps I did not change since the last hour and lengthen the delay to extend battery life.
AlarmManager Documentation
Yes... Search for AlarmManager.. That is exactly what you need.
You can schedule intent to be called and therefore start your service every hour.

Running Android service for infinite time

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?

Android LocationListener leave on while phone asleep

I set an alarm with the flag RTC_WAKEUP to run a IntentService every 30 seconds to transmit location updates to a server. I'm planning to change the flag to RTC so it won't wake up the phone and just run when another process wake ups the phone. If I leave a LocationListener registered, will it still listen for location updates while the phone is asleep?
Yes - working location service has it's own wake lock. However better approach is manually set proper wake lock in your broadcast receiver. Please consider some optimization - sending data over network every 30s will drain battery.
You have multiple problems here.
I set an alarm with the flag RTC_WAKEUP to run a IntentService every 30 seconds to transmit location updates to a server.
First, you may not even get your first fix within 30 seconds, particularly if you are using GPS. You need to take into account that you may never get a fix (e.g., the user is in an underground location).
Second, please allow this figure to be user-configurable, including an option for "I'll upload the data manually please". As #piotrpo indicates, this is a significant drain on the battery. In fact, if you're using GPS, I doubt the battery will last more than a couple of hours.
Third, an IntentService will not work well in this case, because the IntentService will shut down before your fix arrives. At best, you'll leak memory. At worst, you won't get your fix, because Android terminates your process.
A better solution for doing background location checks is to use a regular Service, not an IntentService. The regular Service would register the LocationListener in onStartCommand(), plus arrange for a timeout notification (e.g., AlarmManager and set()) in case a fix is not available. When the fix arrives, run an AsyncTask to do your upload. When the AsyncTask completes, or if the timeout arrives and you did not get a fix, unregister the listener and call stopSelf() to shut down the service. Along the way, you will need to maintain your own WakeLock, to keep the device awake while all of this is going on.
For an example of most of this (minus the server upload part), see my LocationPoller.
If you are dead-set on this occurring every 30 seconds or so, you may as well not bother with AlarmManager at all. You would have to have an everlasting service, running all the time, with a permanent WakeLock and a permanent LocationListener. When fixes arrive in onLocationChanged(), upload them if they are more than 30 seconds from the previous one. And, be sure to wear a flame-retardant suit when you release the app, as those who run it may not like the results much.

Categories

Resources