I am running a service in the background that reads GPS/Network location and needs to do the following:
-
run in background without interruptions on app restart and keep it alive as much as possible without being killed (This is solved with the help of Merlin’s comment bellow)
-
on a new location received, call a web service and send the read location
-
have a repetitive task running every 60 seconds and resend last location to the web service. This will help in case the user stays in the same position.
There are a few things I have considered and I’m not sure if I understood right. The service runs in the same thread as the main app, so sending the location to the server on same thread as the UI thread may trigger UI freezes and this is not good. Also I’m not sure if GPS/Network listeners have their own threads or use the same thread as the app.
Here is a shortened code of the service to make things clearer:
public class GPSLoggerService extends Service {
@Override
public void onCreate() {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 50, locationListenerNetwork);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 50, locationListenerGps);
scheduleTaskExecutor = Executors.newScheduledThreadPool(5);
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
updateLocation(lastLocation);
}, 60, 60, TimeUnit.SECONDS);
return START_STICKY;
}
LocationListener locationListenerGps = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
updateLocation(location);
}
...
}
LocationListener locationListenerNetwork = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
updateLocation(location);
}
...
}
private void updateLocation(Location readLocation) {
//web service call
String response = WebServiceCalls.updateLocation(readLocation);
//log data in a local Sqlite database
saveLocation(readLocation)
}
My main concern is how to handle the updateLocation call and have it in a separate thread from the main app thread. The scheduleTaskExecutor I belive it’s not the way to go. Sometimes, even after I call stopService() the service remains alive, even if I tell the TaskExecutor to shutDown. I can’t find another explanation for which the service isn’t stoping.
So to recap: I need to send the location each time the listeners receive a new location and resend it every 60 seconds. I also need to be able to stop the service quickly with active threads canceling.
How would you recommend me to handle my case ?
For prevent your service to destroy you can start your service as a foreground service.
And after getting a location from onLocationChanged() method you can use a asynctask for send a location to the webservice so it will not block your UI.
Edit
You can set the minimum time and minimum distance traveled in your requestLocationUpdates method. So I don’t think you should use the scheduler task for send location to server. According to the argument about min time and min distance the location manager will check the location. If there is a location changed then it will call onLocationChanged() method with new Location.
Now for your solution about user stays in the same position. you can change some logic to server side like if there is a 1 hour difference between two successive locations location1 and location2 means that user has stayed 1 hour at location1.
You can use a single LocationListener class to listen GPS and NETWORK location.