#commonsware let me start by saying thanks for all the help that you give this community, i swear the majority of issues that i google you were the accepted answer.
anyway, had a few questions after i started using the locationpoller
as noted in another post, once i start your polling service, i occasionally get this:
03-07 15:42:03.260: W/MessageQueue(14699): Handler (android.location.LocationManager$ListenerTransport$1) {419425f8} sending message to a Handler on a dead thread
is this a concern still? i couldn't tell if this was just something the locationmanager is screwing up of it was maybe the timeout handler
next is my main concern for creating this post:
i need to track users while their screen is off as part of a destination aware navigation-like application, and for some reason its not waking up after going underground for a while.
i get some weird test results when playing with no network too. for now i start the service like you suggest
Intent i=new Intent(this, LocationPoller.class);
i.putExtra(LocationPoller.EXTRA_INTENT, new Intent(this, LocationReceiver.class));
i.putExtra(LocationPoller.EXTRA_PROVIDER, LocationManager.NETWORK_PROVIDER);
everything seems to work as u documented, when testing with airplane mode turned on PollerThread#onPreExecute() gets called every time, and then never makes it to the end, and 2 minutes later, my receiver finally gets notified when the onTimeout Runnable gets triggered.
then when i turn airplane mode off again, everything seems to go back to normal, with my receiver eventually catching up again.
My issue is that when i test in the real world, and take the subway home but leave the app and service running, once i reconnect above ground, i cant seem to find any trace in the logs that the service continues on, and my receiver, which uses another wakelock to turn the screen back on / send a notification when close to your destination, never gets triggered until i re-open my app
long story short - is this an issue with the library? an issue with how locationmanager works? have you any ideas on a better way to test this rather than just using airplane mode?
above ground, biking around, driving, etc, everything seems to work just fine, but once i introduce the subway and i lose all connections, shit stops working, and i just dont know enough about the finer points of locationmanager to understand why the service seems to stop
disclaimer this app isn't meant for people on the subway but im just not sure (havent had any way to test) if a user is out in the middle of nowhere and loses network connectivity i hope they dont lose tracking as well (since they can choose to just use network provider or gps depending on the settings)
is this a concern still?
I have no idea. If you can create a reproducible test case that demonstrates this, please post an issue to the project's issue tracker.
My issue is that when i test in the real world, and take the subway home but leave the app and service running, once i reconnect above ground, i cant seem to find any trace in the logs that the service continues on
The service is not supposed to "continue on". The service will try for a short while to get a location fix, then will shut down after delivering the timeout message. It is up to you, via AlarmManager or similar means, to do the actual "polling".
Quoting the documentation:
You simply set up an AlarmManager alarm to contact LocationPoller on whatever frequency you wish, and it will handle all of the location work from there, sending you the results via a broadcast Intent... Next, you need to create an alarm via AlarmManager, so you can control how frequently the location is retrieved and whether it should wake up the device if it is asleep. Please do not request location updates frequently, as this will drain the user's battery, particularly if you are using GPS.
So, your first step would be to determine if your alarms are working properly. You can use adb shell dumpsys alarm to examine the registered alarms and see what is going on.
Related
Hello all i want location updates when my app is triggered first and after even it is killed i want my service to run i tried broadcast receiver for this purpose but it run on phone reboot Can anybody guide me to the right direction? Thanks
depending on the layout of your code, I believe it might be as easy as making the app perform the location update request on onResume while leaving onPause blank to test if it works for what you want. At least if I understood you correctly, that's what worked for me but it might drain your battery if you are using some power demanding location provider like GPS. And about your service to survive reboot I'm not really acquainted on that topic but from a quick read, indeed using broadcast receiver and listening for BOOT_COMPLETED to set off an intent.setAction declared after onCreate on your MainActivity should do it, but haven't tested that myself yet. Anyhow, it would be best if you can post the code you're working with so that others can see exactly what you have so far and be more helpful.
Hope it helps
My goal
Get user location updates for quite long time (e.g. 8 hours) with quite high frequency (e.g. every 30 seconds) even when the application is not running in foreground (meaning the activity where the location tracking was started might be destroyed).
Issue
I've found many articles regarding location tracking in Android apps.
The newer ones usually explain how to use Google Play Services' location APIs.
The problem is that in most cases, they demonstrate getting location updates in co-operation with Activity and LocationListener. For example in Google's tutorial. It's obvious this is not what I need. The only approach for long-running background location updates was based on periodical starting (via AlarmManager) of a service that run until it got accurate enough location update. However, this approach doesn't seem right for the frequency I need.
So, I ended up with custom idea how to solve the topic, but your critique would be welcomed. Here it is:
Idea of a possible solution
MainActivity - used just for starting/stopping the tracking by starting/stopping the MonitoringService
MonitoringService - a foreground service, where the whole connecting to LocationServices from Google Play services happens. Also, once connected a requestLocationUpdates method is called, but its variant with PendingIntent object. The pending intent contains intent invoking MyWakefulBroadcastReceiver class. Also, the service holds a partial wake_lock to prevent the device going to sleep and interrupting receiving of the location updates. Here, I'm not sure if holding the wake lock really helps.
MyWakefulBroadcastReceiver - extends WakefulBroadcastReceiver, just starts LocationProcessingIntentService via the startWakefulService
LocationProcessingIntentService - processes the location update passed via intent to it. Network communication performed here. Therefore, it is done in separate service and not directly in the MonitoringService
Currently, I have the solution described above implemented without acquiring the partial wake lock in the MonitoringService. When connected to debugger in Android Studio, I see the processing of the location updates work. However, I'm not sure what it will do after e.g. 4 hours of running without being connected to laptop (like it is for the debugging purposes)
Questions
Is this approach OK from architecture/performance/battery life point of view?
Should I use the wake lock for being sure the device won't go to sleep?
If answer to 2. is yes, do I still need to use WakefulBroadcastReceiver for starting the IntentService processing the location updates?
Any other recommendations?
What you have is mostly fine. You don't need the MonitoringService. The PendingIntent will wake your BroadcastReceiver, regardless of the state of your app. You don't need a permanent wake-lock. Just use the PendingIntent in your setup Activity to requestLocationUpdates.
Remember that the location services are already running in the background (as long as the user has enabled location services), so you don't need to run your permanent wake-lock service also (you can wake-lock after BroadcastReceiver#onReceive(), but don't forget to release the wake-lock after processing).
The only time you might have to worry about the PendingIntent not waking your BroadcastReceiver is if the user force-stops your app. In that case, you could choose to respect the user's decision. You can also explore using intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); which should wake your BroadcastReceiver from the stopped state, but I haven't tested this flag in this scenario.
My application requests for updates in a service on background when a boolean flag is set to true. If flag is set to true, then i acquire a PARTIAL_WAKE_LOCK to let my background service run.
My questions are:
Since I requested for updates from location manager ( i don't manually request updates but subscribed for locationManager.requestLocationUpdates )... does the locationManager keep working as normal/usual even if device goes to sleep with PARTIAL_WAKE_LOCK ?
I've read there is a WifiLock -> WIFI_MODE_SCAN_ONLY that I'm not acquiring. Since location manager uses wifi scans to detect location through wifi hotspots, should I acquire this as well ?
What about gps location updates when device goes to sleep ?
no, it does not. More (very good) info here, including possible solutions/ hacks.
regarding 1, I would have to make an educated guess and say it wouldn't make a difference
from what I can gather, it doesn't make a difference which provider you are using for the updates, LocationManager.NETWORK_PROVIDER or LocationManager.GPS_PROVIDER.
in danger of going a bit OQ, I am a bit curious which kind of application would need to aquire a wake lock to keep a service running at all. As far as I know, having a wake lock doesn't ensure your Service keeps running. The only thing which ensures a Service keeps running is to have it in the foreground (Service.startForeground()). Otherwise the system still might kill the service, regardless if it aquired a wake lock or not.
That being said, if it is running, it can do it's work with a Handler or something.
If you are using this approach, and I think you are based on the scenario, I would advise against it. Basically you are creating a service, have it run in the foreground (guess) AND you are aquiring a wake lock just to request for location updates when the screen is off. This seems a bit overkill.
There's a more efficient way, which has the benefit it has by far more accurate timing then the dreaded timing of Handler.postAtTime or Handler.postDelayed: AlarmManager.setRepeating(). Set type to ELAPSED_REALTIME_WAKEUP or RTC_WAKEUP so it will run if the device sleeps, then when the alarm event is fired and received by a BroadcastReceiver you will have to create, you could request for updates and handle other events.
If you're not using a Handler, but are merely requesting location updates, this approach still probably would be better, because it doesn't require you to have a running Service or to acquire a wake lock.
And it seems LocationManager.addProximityAlert() is the way to go here. Which is flawed as well (see 1)
Similar question here by the way: Android: GPS location updates when the cellphone is in sleep?
I've spent days trying to get WiFi and cell-based locations with locked screen with Android 6.0 on Nexus 6. And looks like the native android location service simple does not allow to do it. Once device got locked it still collects location update events for 10-15 minutes then stops to providing any of location updates.
In my case the solution was to switch from native Android location service to Google Play Services wrapper called com.google.android.gms.location: https://developers.google.com/android/reference/com/google/android/gms/location/package-summary
Yes, I know that some of Android devices lack of GMS, but for my application this is the only solution to perform.
It does not stop sending location updates even when in the background and device screen is locked.
Me personally prefer RxJava library to wrap this service into a stream (examples included): https://github.com/mcharmas/Android-ReactiveLocation
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.