Part of my app requires location services, so if location is currently turned off, the app will prompt the user to enable it. Here is how I am doing it: (Also seen in this Stack Overflow answer)
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>()
{
@Override
public void onResult(LocationSettingsResult result)
{
final Status status = result.getStatus();
final LocationSettingsStates = result.getLocationSettingsStates();
switch (status.getStatusCode())
{
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
...
Log.d("onResult", "SUCCESS");
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
Log.d("onResult", "RESOLUTION_REQUIRED");
try
{
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(OuterClass.this, REQUEST_LOCATION);
}
catch (SendIntentException e)
{
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
...
Log.d("onResult", "UNAVAILABLE");
break;
}
}
});
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
// This log is never called
Log.d("onActivityResult()", Integer.toString(resultCode));
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode)
{
case REQUEST_LOCATION:
switch (resultCode)
{
case Activity.RESULT_OK:
{
// All required changes were successfully made
break;
}
case Activity.RESULT_CANCELED:
{
// The user was asked to change settings, but chose not to
break;
}
default:
{
break;
}
}
break;
}
}
This code works well, however, onActivityResult()
is always skipped. Whether or not the user presses Yes
, No
, or back
from the Dialog
, onActivityResult()
doesn't run.
I need Android to call onActivityResult()
so if the user chooses not to turn on location services, I can handle it appropriately.
Google's developer page (and the code above) explicitly says that onActivityResult()
should be called. Anyone know why it's being skipped?
I also don't know what the purpose of this line is:
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
Thanks!
Edit: Basic information on the structure of my app:
- This code is contained within the
onResume()
method of aFragment
which implementsGoogleApiClient.ConnectionCallbacks
,GoogleApiClient.OnConnectionFailedListener
, andLocationListener
to receive location updates. Example seen here. - In
onLocationChanged()
theFragment
will have a customView
callinvalidate()
and re-draw itself with updated information.
It looks like the main issue is that you have all of the code in a Fragment, and since
startResolutionForResult()
needs an Activity passed into it, the Activity is what gets theonActivityResult()
callback.One way to get around that is to use the technique described here, manually call the Fragment's
onActivityResult()
method from the Activity when the result comes in.I just got this simple example working.
First, the Activity, which adds the Fragment, and also has functionality to pass along the result of
onActivityResult()
to the Fragment:Here is the Fragment, which contains all of the functionality to show the dialog, and handle the result. In this simple example I just used Toast messages to verify that it is working as expected. Note that the main change that I've made here from the code in your question is the use of
getActivity()
to get the Activity reference needed for the call tostartResolutionForResult()
.Here are the results visually, first the dialog is shown if Location Mode is disabled:
Then, if the user clicks No, the result is passed from the Activity to the Fragment, which shows a Toast:
Same thing when the user clicks Yes, but with a success result, and Location Mode is enabled:
Note that it might be a better option to just keep all of this functionality in the Activity, and then call into a public method in the Fragment when the result comes in.
Here is fully working code for keeping the functionality in the Activity. Of course in this solution, you would need to add a call into the Fragment to update the state of Location Mode after
onActivityResult()
is called.Its because of all google api codes present in the Fragments.. Try the following it will help to overcome...
1.Create a empty constructor for your fragments.
2.need oncreate() method before the onCreateView()...
3.paste the Google api code inside the oncreate()....
Click here...
Source Code
https://drive.google.com/open?id=0BzBKpZ4nzNzUOXM2eEhHM3hOZk0
Dependency in build.gradle file
compile 'com.google.android.gms:play-services-location:7.8.0'
Permission in Manifest File
If you want results back to your fragment than use
instead of
status.startResolutionForResult(YourActivity, LOCATION_REQUEST);
USING above method will deliver result back to your fragment only.
You need to add this to your result callback:
onActivityResult
will be called on your fragment, you don't need to call it manually in your activity. This is essentially howstartResolutionForResult
works.I see that you use different constants
REQUEST_CHECK_SETTINGS
andREQUEST_LOCATION
for request code. Do they have same value?For the code:
final LocationSettingsStates states = LocationSettingsStates.fromIntent(intent);
.The purpose of above code is to get the current status of Location setting(like use Network, GPS, ...) after changed the setting.
Also, in your code, I think it's should be
LocationSettingsStates.fromIntent(data);
because theintent
doesn't exixst here, maybe it's just a typo.