I'm having trouble sending a string extra with my PendingIntent
that I pass to LocationServices.FusedLocationApi.requestLocationUpdates(GoogleApiClient client, LocationRequest request, PendingIntent callbackIntent)
.
It appears that the username extra i'm putting onto the Intent
is mangling the location that requestLocationUpdates
is trying to hand off to my IntentService
as intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED)
returns null
.
EDIT
I've tried making a User
class that implements Parcelable
and putting it as an extra:
mRequestLocationUpdatesIntent.putExtra("username", new User(username));
and I've also tried to put the Parcelable User
inside a Bundle
as suggested via comment in this bug report https://code.google.com/p/android/issues/detail?id=81812:
Bundle userBundle = new Bundle();
userBundle.putParcelable("user", new User(username));
mRequestLocationUpdatesIntent.putExtra("user", userBundle);
in my service:
Bundle userBundle = intent.getBundleExtra("user");
User user = userBundle.getParcelable("user");
String username = user.getUsername();
However neither of these approaches has made any difference. Whenever I put any extra onto my intent, the location is never added to the intent when the updates occur.
I setup this IntentService
to handle location updates:
public class LocationUpdateService extends IntentService {
private final String TAG = "LocationUpdateService";
public LocationUpdateService() {
super("LocationUpdateService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent");
Bundle extras = intent.getExtras();
Log.d(TAG, "keys found inside intent: " + TextUtils.join(", ", extras.keySet()));
String username = intent.getStringExtra("username");
if (username != null) {
Log.d(TAG, "username: " + username);
} else {
Log.d(TAG, "username: null");
}
if (!intent.hasExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED)) {
Log.d(TAG, "intent does not have location :(");
}
Location location = intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
if (location == null) {
Log.d(TAG, "location == null :(");
}
Log.d(TAG, "latitude " + String.valueOf(location.getLatitude()));
Log.d(TAG, "longitude " + String.valueOf(location.getLongitude()));
...
}
}
When the user clicks a button, the startLocationUpdates
is called in my main activity:
main activity class:
...
Boolean mLocationUpdatesEnabled = false;
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(LOCATION_UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(LOCATION_UPDATE_FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
protected void startLocationUpdates() {
Log.d(TAG, "startng location updates...");
mLocationUpdatesEnabled = true;
if (mLocationRequest == null) {
createLocationRequest();
}
// create the Intent to use WebViewActivity to handle results
Intent mRequestLocationUpdatesIntent = new Intent(this, LocationUpdateService.class);
// create a PendingIntent
mRequestLocationUpdatesPendingIntent = PendingIntent.getService(getApplicationContext(), 0,
mRequestLocationUpdatesIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
// request location updates
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest,
mRequestLocationUpdatesPendingIntent);
Log.d(TAG, "location updates started");
}
protected void stopLocationUpdates() {
Log.d(TAG, "stopping location updates...");
mLocationUpdatesEnabled = false;
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient,
mRequestLocationUpdatesPendingIntent);
Log.d(TAG, "location updates stopped");
}
This all works well and good; When the user presses the button, toggleLocationUpdates
is called, which calls LocationServices.FusedLocationApi.requestLocationUpdates
which calls my LocationUpdateService
where I'm able to get the location.
The trouble comes when I tried to put a string extra onto my Intent
using Intent.putExtra(String, String):
main activity class:
...
protected void startLocationUpdates(String username) {
....
// create the Intent to use WebViewActivity to handle results
Intent mRequestLocationUpdatesIntent = new Intent(this, LocationUpdateService.class);
//////////////////////////////////////////////////////////////////
//
// When I put this extra, IntentService sees my username extra
// but the parcelableExtra `location` == null :(
//
//////////////////////////////////////////////////////////////////
mRequestLocationUpdatesIntent.putExtra("username", username);
...
}
...
EDIT I had started the next sentence as a statement rather than a question: "I am using..."
Am I using the correct approach to sending some extra data to this location update handling IntentService
or is there a more-sane way to go about this?
Is this a bug or just poor documentation?
Using the IntentService coupled with the FusedLocationProviderAPI will present issues. From the Developer Docs titled Receiving Location Updates:
Further, a
PendingIntent
is used for extending permissions for another piece of code (FusedLocationProviderAPI
in Google Play Services) to execute their code within your apk. AnIntentService
is used to start a Service defined within the scope of your apk.So, the method requires an implementation of
LocationListener
for foreground updates, or aPendingIntent
for background updates coupled with a Broadcast Receiver.This is a working example of some methods used to request location updates from a
PendingIntent
coupled with extra values.Note:
LocalStorage.java
is a utility class for storing local variables, it is not part of the Android APIGPSPlotter
BackgroundLocationReceiver
EDIT The method below builds a LocationRequest necessary for invoking the
requestLocationUpdates()
methodEDIT After a long discussion in chat with Catherine, we came to the conclusion that google play services library 7.5 has a bug that does not process the Parcelable Extra Location passed from FusedLocationProviderAPI when other extras are put into the Intent. However, 7.0 does provide this capability. She said that she will submit a bug and we'll see how long it takes the Android team to resolve