Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android FusedLocationProviderApi: Incoming intent has no LocationResult or LocationAvailability

I am trying to subscribe to location updates via Google's FusedLocationProviderApi. I want to receive updates in the background, so that I will receive updates even if the app is killed. Following the online documentation as best as I can, I've written the following code. Note: this is being done in an intent service, not on the UI thread, which is why I'm using blocking connect/result methods.

private void startLocationServices(String deviceId, int pollingInterval) {
    Log.i(TAG, "Starting location services with interval: " + pollingInterval + "ms");
    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
    final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
    wakeLock.acquire();

    final GoogleApiClient googleApiClient =
            new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .build();

    ConnectionResult result = googleApiClient.blockingConnect();

    if (!result.isSuccess() || !googleApiClient.isConnected()) {
        Log.e(TAG, "Failed to connect to Google Api");
        wakeLock.release();
        return;
    }

    LocationRequest locationRequest = new LocationRequest();
    locationRequest.setInterval(pollingInterval);
    locationRequest.setFastestInterval(10000);
    locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

    Intent locationIntent = new Intent(this, GeoBroadcastReceiver.class);
    locationIntent.putExtra(EXTRA_LOCATION_UPDATE_DEVICE_ID, deviceId);
    locationIntent.setAction(GeoBroadcastReceiver.ACTION_LOCATION_UPDATE);
    PendingIntent locationPendingIntent = PendingIntent.getBroadcast(
            this, 0, locationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    PendingResult pendingResult = LocationServices.FusedLocationApi
            .requestLocationUpdates(googleApiClient, locationRequest, locationPendingIntent);

    Result requestResult = pendingResult.await();
    Status requestStatus = requestResult.getStatus();

    if (requestStatus.isSuccess()) {
        Log.i(TAG, "Successfully subscribed to location updates.");
    } else {
        Log.e(TAG, String.format(
                        "Failed subscribe to location updates. Error code: %d, Message: %s.",
                        requestStatus.getStatusCode(),
                        requestStatus.getStatusMessage()));
    }

    googleApiClient.disconnect();
    wakeLock.release();
}

When I run this, I see that requestStatus.isSuccess() returns true, indicating that I've successfully subscribed to the location updates. Additionally, The GeoBroadcastReciever, which extends WakefulBroadcastReceiver, receives an intent at the correct polling interval, with the correct action. Good so far, it would seem. Here is what I'm doing in the onReceive method for the GeoBroadcastReceiver:

    if (LocationResult.hasResult(intent)) {
        LocationResult locationResult = LocationResult.extractResult(intent);
        Location location = locationResult.getLastLocation();
        if (location != null) {
            GeoMonitoringService.wakefulLocationUpdate(context, location);
        } else {
            Log.e(TAG, "LocationResult does not contain a LastLocation.");
        }
    } else {
        Log.e(TAG, "Intent does not contain a LocationResult.");
    }

The problem is, whenever the intent comes in, it does not contain the LocationResult, nor does it contain the LocationAvailabilityResult. I inspected the incoming intent in the debugger, and the only item in the intent's extras is the extra I added when setting up the intent (the device id). As such, LocationResult.hasResult() returns false. Every single time.

I've tried this on a Galaxy Note 4 running 4.0.1, and a Nexus 4 running 5.1.1, with the same result.

If I disable location on the phone, I stop receiving intents altogether, as expected.

like image 561
fpsulli3 Avatar asked Oct 01 '15 17:10

fpsulli3


2 Answers

Remove the extras from the pending intent, otherwise the location result is not delivered. I can't find where in the documentation this is explained but I found out after lot of trial and error.

like image 199
Fernando Gallego Avatar answered Sep 20 '22 14:09

Fernando Gallego


You can use:

int id = 7;
String name = "myName";
uriBuilder.scheme("http")
            .authority("workaround.com")
            .appendPath("extra")
            .appendQueryParameter("id", String.valueOf(id))
            .appendQueryParameter("name", name);
intent.setData(uriBuilder.build());

and

@Override
protected void onHandleIntent(Intent intent) {
    if (LocationResult.hasResult(intent)) {
        int id = Integer.valueOf(uri.getQueryParameter("id"));
        String name = uri.getQueryParameter("name");
        ....
    }
}
like image 27
Amir Avatar answered Sep 21 '22 14:09

Amir