UPDATE: I'm getting this error, like it's explained in this questions (1 and 2), but according to this answer, this is only an internal log and shouldn't have impact on the functionality
V/GoogleSignatureVerifier: com.google.android.gms signature not valid
ORIGINAL QUESTION:
I have to implement different features related to the user location that have to work even if the app is killed. To achieve that, I'm using a service. I have issues when I try to track the user, because it seems that I have a problem requesting the location updates.
Here's the most relevant parts of my service:
DISCLAIMER: The code have been simplified for the reading sake. All the methods related to the service binding, along with several callbacks, have been removed because aren't part of the problem
public class LocationService extends RoboService implements LocationListener {
private static final String TAG = "LocationService";
private static final long UPDATE_INTERVAL_IN_MILLISECONDS = TimeUnit.SECONDS.toMillis(5);
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = TimeUnit.SECONDS.toMillis(1);
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
@Override
public void onCreate() {
super.onCreate();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_REDELIVER_INTENT;
}
public Location getCurrentLocation() {
ConnectionResult connectionResult = mGoogleApiClient.blockingConnect();
if (connectionResult.isSuccess()) {
return LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
return null;
}
public void startLocationUpdates() {
ConnectionResult connectionResult = mGoogleApiClient.blockingConnect();
if (connectionResult.isSuccess()) {
Log.d(TAG, "startLocationUpdates: Posting request");
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "startLocationUpdates: Request posted");
}
}
@Override
public void onLocationChanged(Location newLocation) {
System.out.println("LocationService.onLocationChanged");
}
}
I'm using mGoogleApiClient.blockingConnect()
because I can't use the connection callbacks due to architecture constrains, but I don't have any problems when I try to get the current location.
When I call startLocationUpdates()
the execution seems to be lost when I request the location updates and neither Log.d(TAG, "startLocationUpdates: Request posted")
nor onLocationChanged(Location newLocation)
are ever called.
Here's the logcat:
05-23 11:42:47.509 13547-13547/com.example.location D/MapPresenterImpl: onRouteAdded: Starting route tracking
05-23 11:42:47.512 13547-13950/com.example.location D/LocationService: startLocationUpdates: Posting request
05-23 11:43:28.115 13547-13557/com.example.location W/art: Suspending all threads took: 7.530ms
My code is basically copied from the Android examples. I downloaded the example source code and I have it working correctly. The two only differences between my code and the example's is mine being inside a service and using mGoogleApiClient.blockingConnect()
, but I don't know how this could affect in this way.
Someone have ever faced this kind of behaviour? I'm truly lost and I would preciate any help.
WORKAROUND:
At the end I solved this problem using PendingIntent instead of the Callback approach. I still would be glad to know why this happened, but if someone faces this problem and doesn't know how to proceed, here's my workaround.
Method to start the location updates:
public void startLocationTracking(long routeId) {
ConnectionResult connectionResult = mGoogleApiClient.blockingConnect();
if (connectionResult.isSuccess()) {
Intent intent = new Intent(this, TrackingService.class);
PendingIntent pi = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
LocationRequest request = new LocationRequest();
request.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
request.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, pi);
}
}
Tracking service:
public class TrackingService extends IntentService {
public TrackingService() {
super("TrackingService");
}
@Override
protected void onHandleIntent(Intent intent) {
if (LocationResult.hasResult(intent)) {
LocationResult locationResult = LocationResult.extractResult(intent);
Location location = locationResult.getLastLocation();
// Do whatever you need with the location
}
}
}
Using this method I faced another weird problem. If you put some extra in the Intent used to build the PendingIntent, when TrackingService is called there isn't any location in the Intent extras, only what was added when the Intent was created. My workaround for this was using the SharedPreferences to pass an id that I needed to have, but I'm not really convinced by this patch. This issue is discussed in this question.