I need to access PlacesClient.findCurrentPlace() each time I get a location update through FusedLocationProviderClient.requestLocationUpdates()
.
I decided to do this by enqueing a OneTimeWorkRequest
in the BroadcastReceiver
that is called by the PendingIntent
passed to FusedLocationProviderClient.requestLocationUpdates()
:
public class LocationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
WorkRequest locationRequest = new OneTimeWorkRequest.Builder(HeartBeatWorker.class)
.build();
WorkManager.getInstance(context).enqueue(locationRequest);
}
}
However, sometimes, the Worker
's doWork
gets the com.android.volley.TimeoutError
from the Task<FindCurrentPlaceResponse>
returned by the Places SDK call:
@Override
public Result doWork() {
// Initialize the SDK
Places.initialize(getApplicationContext(), "<my API key>");
// Create a new Places client instance
PlacesClient placesClient = Places.createClient(getApplicationContext());
// Use fields to define the data types to return.
List<Place.Field> placeFields = new ArrayList<>();
placeFields.add(Place.Field.NAME);
placeFields.add(Place.Field.TYPES);
// Use the builder to create a FindCurrentPlaceRequest.
FindCurrentPlaceRequest request = FindCurrentPlaceRequest.newInstance(placeFields);
if (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// Call Places SDK to get current PlaceLikelihoods
Task<FindCurrentPlaceResponse> placeResponse =
placesClient.findCurrentPlace(request);
placeResponse.addOnCompleteListener(new OnCompleteListener<FindCurrentPlaceResponse>() {
@Override
public void onComplete(@NonNull Task<FindCurrentPlaceResponse> task) {
if (task.isSuccessful()) {
...
} else {
// sometimes I fall here, with status code 15.
// Looking into it, the error turns out to be:
// com.android.volley.TimeoutError
Exception exception = task.getException();
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
Log.d(MainActivity.LOG_TAG, "HeartBeatWorker: Place not found: " + apiException.getStatusCode());
}
}
}
});
} else {
Log.d(MainActivity.LOG_TAG, "HeartBeatWorker: No ACCESS_FINE_LOCATION permission: HeartBeatWorker returning");
}
return Result.success();
}
I'm aware that Android enacts relevant power management restrictions that could cause the network (presumably needed by the Places SDK call) to be unavailable. However I get the error even when the app is not in Doze mode and it is still in App Standby Bucket = 10 (i.e. Active) and should not have any network restrictions. What could be the cause of the error, then?
I found the answer here:
A short time after the screen turns off while the device is on battery, Doze restricts network access and defers jobs and syncs.
I overlooked this, as it is not explicitly mentioned on the main Doze guide in the documentation, which still insists that the device should also be stationary to enter Doze:
If a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode.