Solución:
ACTUALIZAR
La respuesta original a continuación es usar Java y el SettingsApi ahora obsoleto.
Aquí hay un enfoque más moderno usando Kotlin y SettingsClient:
override fun showEnableLocationSetting()
activity?.let
val locationRequest = LocationRequest.create()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
val builder = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest)
val task = LocationServices.getSettingsClient(it)
.checkLocationSettings(builder.build())
task.addOnSuccessListener response ->
val states = response.locationSettingsStates
if (states.isLocationPresent)
//Do something
task.addOnFailureListener e ->
if (e is ResolvableApiException)
try
// Handle result in onActivityResult()
e.startResolutionForResult(it,
MainActivity.LOCATION_SETTING_REQUEST)
catch (sendEx: IntentSender.SendIntentException)
En MainActivity, defina la constante:
companion object
const val LOCATION_SETTING_REQUEST = 999
RESPUESTA ORIGINAL:
Parece que el problema principal es que tiene todo el código en un Fragmento, y desde startResolutionForResult()
necesita que se le pase una Actividad, la Actividad es lo que obtiene el onActivityResult()
llamar de vuelta.
Una forma de evitarlo es utilizar la técnica descrita aquí, llamar manualmente al Fragmento onActivityResult()
método de la Actividad cuando llegue el resultado.
Acabo de hacer funcionar este sencillo ejemplo.
Primero, la Actividad, que agrega el Fragmento, y también tiene funcionalidad para transmitir el resultado de onActivityResult()
al Fragmento:
public class MainActivity extends AppCompatActivity
LocationFragment lFrag;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lFrag = LocationFragment.newInstance();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, lFrag).commit();
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
if (requestCode == LocationFragment.REQUEST_LOCATION)
lFrag.onActivityResult(requestCode, resultCode, data);
else
super.onActivityResult(requestCode, resultCode, data);
Aquí está el Fragmento, que contiene toda la funcionalidad para mostrar el diálogo y manejar el resultado. En este ejemplo simple, solo utilicé mensajes de Toast para verificar que funciona como se esperaba. Tenga en cuenta que el cambio principal que hice aquí desde el código de su pregunta es el uso de getActivity()
para obtener la referencia de actividad necesaria para la llamada a startResolutionForResult()
.
public class LocationFragment extends Fragment
implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
PendingResult result;
final static int REQUEST_LOCATION = 199;
public static LocationFragment newInstance()
LocationFragment fragment = new LocationFragment();
return fragment;
public LocationFragment()
// Required empty public constructor
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
mGoogleApiClient.connect();
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_location, container, false);
@Override
public void onResume()
super.onResume();
@Override
public void onConnected(Bundle bundle)
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(30 * 1000);
mLocationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback()
@Override
public void onResult(LocationSettingsResult result)
final Status status = result.getStatus();
//final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode())
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
//...
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(
getActivity(),
REQUEST_LOCATION);
catch (IntentSender.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.
//...
break;
);
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
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
Toast.makeText(getActivity(), "Location enabled by user!", Toast.LENGTH_LONG).show();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
Toast.makeText(getActivity(), "Location not enabled, user cancelled.", Toast.LENGTH_LONG).show();
break;
default:
break;
break;
@Override
public void onConnectionSuspended(int i)
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
Estos son los resultados visualmente, primero se muestra el cuadro de diálogo si el Modo de ubicación está deshabilitado:
Luego, si el usuario hace clic en No, el resultado se pasa de la Actividad al Fragmento, que muestra un brindis:
Lo mismo ocurre cuando el usuario hace clic en Sí, pero con un resultado exitoso, y el Modo de ubicación está habilitado:
Tenga en cuenta que podría ser una mejor opción simplemente mantener toda esta funcionalidad en la Actividad y luego llamar a un método público en el Fragmento cuando llegue el resultado.
Aquí hay un código completamente funcional para mantener la funcionalidad en la Actividad. Por supuesto, en esta solución, necesitaría agregar una llamada al Fragmento para actualizar el estado del Modo de ubicación después onActivityResult()
se llama.
public class MainActivity extends AppCompatActivity
implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
PendingResult result;
final static int REQUEST_LOCATION = 199;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
mGoogleApiClient.connect();
@Override
public void onConnected(Bundle bundle)
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(30 * 1000);
mLocationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback()
@Override
public void onResult(LocationSettingsResult result)
final Status status = result.getStatus();
//final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode())
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
//...
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(
MainActivity.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.
//...
break;
);
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
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
Toast.makeText(MainActivity.this, "Location enabled by user!", Toast.LENGTH_LONG).show();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
Toast.makeText(MainActivity.this, "Location not enabled, user cancelled.", Toast.LENGTH_LONG).show();
break;
default:
break;
break;
@Override
public void onConnectionSuspended(int i)
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
Debe agregar esto a su devolución de llamada de resultado:
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try
fragment.startIntentSenderForResult(status.getResolution().getIntentSender(), REQUEST_CHECK_SETTINGS, null, 0, 0, 0, null);
catch (IntentSender.SendIntentException e)
// Ignore the error.
break;
onActivityResult
se llamará en su fragmento, no necesita llamarlo manualmente en su actividad. Esto es esencialmente como startResolutionForResult
obras.
Si desea que los resultados vuelvan a su fragmento, utilice
startIntentSenderForResult(status.getResolution().getIntentSender(), REQUEST_CODE_LOCATION_SETTING, null, 0, 0, 0, null);
en lugar de status.startResolutionForResult(YourActivity, LOCATION_REQUEST);
UTILIZAR el método anterior devolverá el resultado solo a su fragmento.
Si entiendes que te ha resultado de ayuda este post, sería de mucha ayuda si lo compartes con el resto programadores de esta manera contrubuyes a difundir este contenido.