I am working on a feature for my app that is supposed to record the location of a user in background and to send it to the server at some later point (consider it a simple GPS tracker).
I am using the FusedLocationApi and request the location delivery via the pending intent.
When I start location tracking, I do get location broadcasts delivered to my app so things appear to be working. However, when I test the app over a prolonged period of time, things are starting to get weird:
1) While I am at the office and my device is connected to Wi-Fi, it seems like location delivery is fine. The locations are delivered accurate and there's a minimal difference in the coordinates delivered (the phone is on my desk):
19:28:29.276 [main] Location acquired, lat=53.9265544, lon=27.6993057
19:28:59.944 [main] Location acquired, lat=53.9265669, lon=27.6991762
19:29:30.884 [main] Location acquired, lat=53.9265529, lon=27.6992383
2) When I drive out of the office and my test phone gets disconnected from Wi-Fi, the locations are still delivered but it's always the same coordinates (close to my office). The log below was recorded while I was driving at high-speed motorway (all coordinates are the same):
19:54:37.341 Location acquired, lat=53.9323538, lon=27.6920177
19:59:37.385 Location acquired, lat=53.9323538, lon=27.6920177
20:04:37.499 Location acquired, lat=53.9323538, lon=27.6920177
3) After a while (while I'm still out), the delivery of the location broadcasts stops completely.
4) When I go back home (and the phone is getting connected to WiFi) the location broadcasts delivery is resumed with the correct locations being delivered.
I have tried this on two devices: Nexus 7" 2013 & Prestigio PAP 5500 and the behavior is generally the same. It seems like the locations are not correctly delivered while I'm away from Wi-Fi. Naturally, the GPS module is on (both devices).
Below is my code for reference. The LocationManager class resides inside the service which keeps running all the time during my tests (this is seen from the logs).
Any help is appreciated.
public class LocationManager extends BroadcastReceiver implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static LocationManager mInstance = null;
private GoogleApiClient mGoogleApiClient;
private PendingIntent locationReceivedPendingIntent;
public static LocationManager instance() {
if (mInstance == null) {
mInstance = new LocationManager();
}
return mInstance;
}
private LocationManager() {
mLog = LoggingManager.getLogger(getClass());
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(TimeDoctorApplication.context())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TimeTrackingModel.TASK_CHANGED);
LocalBroadcastManager.getInstance(TimeDoctorApplication.context()).registerReceiver(this, intentFilter);
locationReceivedPendingIntent = PendingIntent.getBroadcast(TimeDoctorApplication.instance().getApplicationContext(), 0, new Intent(LOCATION_RECEIVED), 0);
}
@Override
public void onConnected(@Nullable Bundle bundle) {
boolean noFLPermission = ActivityCompat.checkSelfPermission(TimeDoctorApplication.context(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED;
boolean noCLPermission = ActivityCompat.checkSelfPermission(TimeDoctorApplication.context(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED;
if (noCLPermission || noFLPermission) {
return;
}
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(5 * 60 * 1000);
locationRequest.setFastestInterval(5 * 60 * 1000);
locationRequest.setMaxWaitTime(5 * 60 * 1000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, locationReceivedPendingIntent);
}
@Override
public void onConnectionSuspended(int i) {}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {}
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case SOME_EXTERNAL_EVENT:
int servicesAvailable = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(TimeDoctorApplication.context());
if (servicesAvailable != ConnectionResult.SUCCESS) {
GoogleApiAvailability.getInstance().showErrorNotification(TimeDoctorApplication.context(), servicesAvailable);
return;
}
if (NEEDS_TRACKING) {
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
} else {
if (!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
}
break;
default:
break;
}
}
protected void recordLocation(Location l) {
//Processing location here
}
public static final String LOCATION_RECEIVED = "com.myapp.LOCATION_RECEIVED";
public static class LocationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.hasExtra("com.google.android.location.LOCATION")) {
LocationManager.instance().recordLocation((Location) intent.getExtras().get("com.google.android.location.LOCATION"));
}
}
}
}