androidgoogle-play-servicesgoogle-location-services

Can I pass a ResolvableApiException to a new activity?


I am using Google Play Services to get a user's location (package com.google.android.gms:play-services-location:16.0.0). As described here, you can prompt the user to turn on location settings if necessary via a dialog that is launched using startResolutionForResult:

task.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
    if (e instanceof ResolvableApiException) {
        try {
            ResolvableApiException resolvable = (ResolvableApiException) e;
            resolvable.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
        } catch (IntentSender.SendIntentException sendEx) {
            // Ignore the error.
        }
    }
}

However, I would like to launch this dialog in a new activity started by tapping a notification. To do so, I am trying to add the ResolvableApiException resolvable to the intent for the new activity so I can call startResolutionForResult inside the new activity class. Specifically, I have:

final Intent intent = new Intent(context, NewActivity.class);
final Bundle extras = new Bundle();
extras.putSerializable(EXTRA_EXCEPTION, resolvable);
intent.putExtras(extras);

I get the following error:

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.google.android.gms.common.api.ResolvableApiException)
Caused by: java.io.NotSerializableException: com.google.android.gms.common.api.Status

ResolvableApiException ultimately inherits from Throwable, which implements Serializable, so I was hoping I could add resolvable as a serializable extra. But it seems that ResolvableApiException's Status field is not serializable.

Any suggestions on how I can make this approach work or another approach I can use to trigger the dialog via tapping a notification? Thanks!


Solution

  • I now have a working solution!

    The key is to use getResolution() rather than startResolutionForResult(), as described here. getResolution() returns a pending intent, which is Parcelable and can be attached to the intent for the new activity launched when the notification is tapped:

    final Intent intent = new Intent(context, NewActivity.class);
    intent.putExtra(EXTRA_PENDING_INTENT, resolvable.getResolution());
    

    I can then extract the pending intent in my new activity and launch the dialog via startIntentSenderForResult():

    @Override
    protected void onCreate(@Nullable final Bundle savedInstanceState) {
        ...
    
        final PendingIntent pendingIntent = getIntent().getParcelableExtra(EXTRA_PENDING_INTENT);
    
        try {
            startIntentSenderForResult(pendingIntent.getIntentSender(), RC_LOCATION_SETTINGS, null, 0, 0, 0);
        } catch (IntentSender.SendIntentException e) {
            // Ignore the error
        }
    }
    

    This approach with the pending intent makes a lot more sense because it allows you to choose when to launch the resolution dialog.