0

In my application, I want to record the phone's location at fixed interval. To do that, I have a TimerTask to record the location on a regular basis and a WakeLock for the recording to continue even when the phone is aslept.

My problem is that the Wakelock doesn't prevent the app from going into the "Stop" state when it is no longer displayed in the foreground. As a consequence, my app is regularly, but apparently randomly, destroyed by the system (no crash and no call to onDestroy), and the recording stops.

How can I keep my recording process going even if my app goes into the background?

VD63
  • 133
  • 1
  • 9

1 Answers1

2

In my application, I want to record the phone's location at fixed interval.

Use AlarmManager or JobScheduler to get control at your fixed interval. Use WakefulBroadcastReceiver as the recipient of the alarm event, and have it delegate the work to a Service that gets the location. Have the service call stopSelf() and completeWakefulIntent() once either it gets the location or after some timeout, as it may not be possible to get the location right now.

Or, if you are using the fused location API from Play Services, try the versions of that API that take a PendingIntent instead of a listener, and you may be able to skip the alarms.

I have a TimerTask to record the location on a regular basis

That will only work while your process is around, and it will not be around all that long.

and a WakeLock for the recording to continue even when the phone is aslept

Your users will be extremely unhappy with you for keeping the CPU on constantly and draining the battery.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I have maybe be not specific enough about what my app does. Currently, I get the position every second through a `LocationListener`. When I get a new position, I show it on a map (the current location). At a much slower and still fixed rate, I record the position in a list of points, and I update the map to show every position in the list plus the current position. The action of recording in the list could be done with a `JobScheduler`, but I have to refresh the app display if the app is in the foreground : how could this be triggered from the `Service`? – VD63 May 16 '15 at 15:36
  • @VD63: "Currently, I get the position every second through a LocationListener" -- you *ask* for the position to be given to you every second. What you get will depend on a lot of things. "but I have to refresh the app display if the app is in the foreground" -- your question does not pertain to when your app is in the foreground. – CommonsWare May 16 '15 at 15:53
  • Of course! Because I want both possibilities. When the app is in the foreground, the map has to be updated. When it is hidden, changes in the position must be recorded to be displayed the next time the app will return to the foreground. – VD63 May 16 '15 at 16:42
  • @VD63: And your current solution will not work for that, for the reasons that you outline in your question. That is what I addressed in my answer. Now, if you think that you're going to get location fixes *every second* while in the background, my `AlarmManager` solution isn't appropriate either. In that case, you will need a foreground service for your `TimerTask` and `WakeLock`, plus a fully-paid-up life insurance policy. Battery life will be measured in a few hours; users may take extreme measures to express their displeasure. – CommonsWare May 16 '15 at 16:48
  • I am currently investigating around the foreground service. I plan to have a `Service` started during my `Activity`'s`OnStop`method and to retrieve the recorded locations during my `Activity`'s `onRestart`method. I plan to retrive the data through a file, but I am wondering how to stop the `Service`from the `onStart`method and how to retrieve the complete data only once the `Service`effectively stops recording data (in order not to miss the last recorded location). – VD63 May 16 '15 at 17:38
  • @VD63: "how to stop the Servicefrom the onStartmethod" -- call `stopService()`. "how to retrieve the complete data only once the Serviceeffectively stops recording data (in order not to miss the last recorded location)" -- have the `Service` be updating the same data structure that the rest of your app is using (e.g., some singleton `LocationRoster`), with appropriate thread synchronization. – CommonsWare May 16 '15 at 17:40
  • Ok, I can stop the `Service` with `stopService(Intent)`. For the use of a common structure, there is a difficulty : if the app is destroyed by the system while stopped, the access to this shared structure from the app is lost... – VD63 May 16 '15 at 18:39
  • @VD63: "if the app is destroyed by the system while stopped, the access to this shared structure from the app is lost" -- any static data member is either for ephemeral data or is a cache for a persistent backing store (file, database, etc.). Whether you choose to persist your data or not is up to you. – CommonsWare May 16 '15 at 18:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/77996/discussion-between-vd63-and-commonsware). – VD63 May 17 '15 at 05:20
  • Thanks for your help! – VD63 May 30 '15 at 05:03