尝试访问 PlacesClient.findCurrentPlace() 时获取 com.android.volley.TimeoutError

Getting com.android.volley.TimeoutError when trying to access PlacesClient.findCurrentPlace()

每次通过 FusedLocationProviderClient.requestLocationUpdates() 获取位置更新时,我都需要访问 PlacesClient.findCurrentPlace()。 我决定通过在传递给 FusedLocationProviderClient.requestLocationUpdates():

PendingIntent 调用的 BroadcastReceiver 中排队 OneTimeWorkRequest 来做到这一点
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);
    }
}

但是,有时 WorkerdoWork 从 Places SDK 调用返回的 Task<FindCurrentPlaceResponse> 中获取 com.android.volley.TimeoutError

@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();
}

我知道 Android 执行相关 power management restrictions 可能会导致网络(Places SDK 调用可能需要)不可用。 但是,即使应用程序未处于打瞌睡模式并且它仍处于 App Standby Bucket = 10(即 Active)并且不应有任何网络限制,我也会收到错误消息。 那么错误的原因可能是什么?

我找到了答案here:

A short time after the screen turns off while the device is on battery, Doze restricts network access and defers jobs and syncs.

我忽略了这一点,因为它没有在文档的主要 Doze guide 中明确提到,它仍然坚持设备也应该静止才能进入打瞌睡:

If a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode.