Jeff Engebretsen
Jeff Engebretsen

Reputation: 676

Why is LocationSettingsResult startResolutionForResult not calling onActivityResult?

I've seen this Q&A LocationSettingsRequest dialog - onActivityResult() skipped. It isn't the same issue because everything is being done in an Activity already.

The code used is almost verbatim what is given in the Google Play Services examples.

I have an activity, LocationActivity, that connects to GoogleApiClient for getting the user's location. Once connected I create a LocationSettingsRequest to make sure that location settings are turned on. The activity is implementing ResultCallback<LocationSettingsResult>.

ResultCallback<LocationSettingsResult>.onResult() is called and if result.getStatus().getStatusCode() == LocationSettingsStatusCodes.RESOLUTION_REQUIRED then status.startResolutionForResult(this, REQUEST_CHECK_SETTINGS) is called and the dialog is shown. The problem, no matter what is selected, onActivityResult() is never called.

@Override
public void onConnected(Bundle connectionHint) {
    Log.i(TAG, "GoogleApiClient connected");
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
        .addLocationRequest(new LocationRequest().setPriority(LocationRequest.PRIORITY_LOW_POWER));

    PendingResult<LocationSettingsResult> result =
        LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());

    result.setResultCallback(this);
}

.

@Override
public void onResult(LocationSettingsResult result) {
    final Status status = result.getStatus();
    Log.d(TAG, "onResult() called with: " + "result = [" + status.getStatusMessage() + "]");
    switch (status.getStatusCode()) {
        case LocationSettingsStatusCodes.SUCCESS:
            getLocation();
            break;
        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
            // Location settings are not satisfied. But could be fixed by showing the user
            // a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                status.startResolutionForResult(this, REQUEST_CHECK_SETTINGS);
            } catch (IntentSender.SendIntentException e) {
                Log.d(TAG, "", e);
                // Ignore the error.
            }
            break;
        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
            showManualInputDialog();
            break;
    }
}

I never get here:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "onActivityResult() called with: " + "requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");
    switch (requestCode) {
        case REQUEST_CODE_RESOLUTION:
            retryConnecting();
            break;
        case REQUEST_CHECK_SETTINGS:
            if (resultCode == Activity.RESULT_OK) {
                getLocation();
            } else {
                showManualInputDialog();
            }
            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
    }
}

As an aside. It worked a few times on my S3. From what I can tell it stopped working when I chose to never ask again. But, it hasn't ever worked on an emulator or a Tab 10 and it no longer works on my S3.

Upvotes: 16

Views: 21721

Answers (6)

AKoch
AKoch

Reputation: 599

You can use the registerActivityForResult API and bypass the activity alltogether.

val registration: ActivityResultLauncher<IntentSenderRequest> = fragment.registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { // callback

Then when capturing the exception

when (exception.statusCode) {
    LocationSettingsStatusCodes.RESOLUTION_REQUIRED ->
        try {
            if (exception is ResolvableApiException) {
            val request: IntentSenderRequest = IntentSenderRequest.Builder(
                                    exception.resolution.intentSender
                                ).setFillInIntent(Intent())
                                    .setFlags(0, 0)
                                    .build()
                                registration.launch(request)
                            }
                        } catch (e: SendIntentException) {
    ```

Upvotes: 4

Shubhayu
Shubhayu

Reputation: 13562

If anyone has stumbled on to this problem, gianlucaparadise's answer is one of the better way's of solving this problem. Although the answer is deleted, it adds a lot of value.

Upvotes: 0

Bhaumik Ghodasara
Bhaumik Ghodasara

Reputation: 11

If you are running this code in Fragment than don't use startResolutionForResult(). Instead use startIntentSenderForResult(status.getResolution().getIntentSender(), REQUEST_CODE_LOCATION_SETTING, null, 0, 0, 0, null);

and overrider onaActivityResult() in your fragment. Result will be delivered to this method only.

Upvotes: 14

Vyacheslav
Vyacheslav

Reputation: 27221

In my case there was this error: I've used

public abstract class AGoogleDriveBase extends ABase implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {
//...
@Override
    protected void onActivityResult(int requestCode, int resultCode,  Intent data) {
//...

and this function not called using

try {
            result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
        } catch (SendIntentException e) {
            Log.e(TAG, "Exception while starting resolution activity", e);
        }

because when I used a main activity

public class myAct extends AGoogleDriveBase implements ... {
//...
@Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {

the super method not called (not existed this string):

 super.onActivityResult(requestCode, resultCode, data);

Upvotes: 2

Jeff Engebretsen
Jeff Engebretsen

Reputation: 676

Well I feel silly. My Activity had noHistory="true" in the Manifest so when the other Activity was started there was nothing to come back to.

Upvotes: 10

adjuremods
adjuremods

Reputation: 2998

You can check out the Google Play Location Sample since your code is quite similar it.

From what I can tell on your samples, onResult() may not be called because the case is not LocationSettingsStatusCodes.RESOLUTION_REQUIRED. Its not calling the startResolutionForResult or an underlying setActivityForResult inside it.

Upvotes: 0

Related Questions