15

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.

Community
  • 1
  • 1
Jeff Engebretsen
  • 666
  • 2
  • 8
  • 21

6 Answers6

14

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.

  • can you say why you suggest this, I put like this before, some crash i found in crashlytics Fatal Exception: java.lang.NullPointerException Attempt to invoke virtual method 'void android.app.Activity.startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int)' on a null object reference e.startResolutionForResult( activity, RequestCode.LOCATION_SETTING ) – Siru malayil Aug 19 '21 at 09:55
  • @Sirumalayil There is no other way of achieving this in fragments. – Bhaumik Ghodasara Aug 31 '21 at 07:10
  • The question is about Activity. – The incredible Jan Jun 30 '23 at 13:02
10

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.

Jeff Engebretsen
  • 666
  • 2
  • 8
  • 21
3

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) {
    ```
AKoch
  • 461
  • 4
  • 4
2

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);
Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
0

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.

adjuremods
  • 2,938
  • 2
  • 12
  • 17
  • 2
    `onResult()` is being called and the `LocationSettingsStatusCodes.RESOLUTION_REQUIRED` case is being hit which brings up the dialog to turn on settings. It's after that where my code doesn't get any callback into `onActivityResult()`. – Jeff Engebretsen Dec 21 '15 at 15:43
0

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.

Shubhayu
  • 13,402
  • 5
  • 33
  • 30