android - ubicacion - Activa los servicios de ubicación sin navegar a la página de configuración
desactivar ubicación (10)
Contra el enfoque tradicional de pedir al usuario que vaya a la página de configuración y habilite los servicios de ubicación y regrese, he notado una forma más simple de hacer lo mismo en algunas de las últimas aplicaciones.
En referencia a la siguiente captura de pantalla, se le solicita un diálogo al usuario para habilitar los servicios de ubicación con solo un clic y funciona en esas aplicaciones.
¿Cómo puedo lograr lo mismo?
Siga los pasos que se mencionan a continuación
1)
Cree una solicitud de
LocationRequest
según su deseo
LocationRequest mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000)
.setFastestInterval(1 * 1000);
2)
Crear un
LocationSettingsRequest.Builder
LocationSettingsRequest.Builder settingsBuilder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
settingsBuilder.setAlwaysShow(true);
3)
Obtenga la
Task
LocationSettingsResponse
usando el siguiente código
Task<LocationSettingsResponse> result = LocationServices.getSettingsClient(this)
.checkLocationSettings(settingsBuilder.build());
Nota:
LocationServices.SettingsApi
está en desuso, por lo tanto, use
SettingsClient
lugar.
4)
Agregue un
OnCompleteListener
para obtener el resultado de la
Task
Cuando la
Task
completa, el cliente puede verificar la configuración de ubicación mirando el código de estado del objeto
LocationSettingsResponse
.
result.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
@Override
public void onComplete(@NonNull Task<LocationSettingsResponse> task) {
try {
LocationSettingsResponse response =
task.getResult(ApiException.class);
} catch (ApiException ex) {
switch (ex.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
ResolvableApiException resolvableApiException =
(ResolvableApiException) ex;
resolvableApiException
.startResolutionForResult(MapsActivity.this,
LOCATION_SETTINGS_REQUEST);
} catch (IntentSender.SendIntentException e) {
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
break;
}
}
}
});
CASO 1:
LocationSettingsStatusCodes.RESOLUTION_REQUIRED
: la ubicación no está habilitada, pero podemos pedirle al usuario que habilite la ubicación solicitándole que active la ubicación con el diálogo (llamando a
startResolutionForResult
).
CASO 2:
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE
: no se cumple la configuración de ubicación.
Sin embargo, no tenemos forma de arreglar la configuración, por lo que no mostraremos el diálogo.
5)
OnActivityResult
podemos obtener la acción del usuario en el cuadro de diálogo de configuración de ubicación.
RESULT_OK
=> El usuario activó la ubicación.
RESULT_CANCELLED
: el usuario rechazó la solicitud de configuración de ubicación.
Android Marshmallow 6 admite permisos de tiempo de ejecución. Los permisos de tiempo de ejecución solo funcionan en Marshmallow y en pre-Marshmallow todavía funciona a la antigua usanza.
Puede obtener más información al respecto en este video oficial para desarrolladores de Android:
https://www.youtube.com/watch?v=C8lUdPVSzDk
Y solicitando permiso: http://developer.android.com/training/permissions/requesting.html
Con la actualización reciente de Marshmallow, incluso cuando la configuración de Ubicación está activada, su aplicación deberá solicitar permiso explícitamente. La forma recomendada de hacerlo es mostrar la sección Permisos de su aplicación en la que el usuario puede alternar el permiso según sea necesario. El fragmento de código para hacer esto es el siguiente:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Location Permission");
builder.setMessage("The app needs location permissions. Please grant this permission to continue using the features of the app.");
builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.setNegativeButton(android.R.string.no, null);
builder.show();
}
} else {
// do programatically as show in the other answer
}
Y anule el método
onRequestPermissionsResult
como se muestra a continuación:
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "coarse location permission granted");
} else {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
}
}
}
Otro enfoque es que también puede usar SettingsApi para consultar qué proveedor (es) de ubicación están habilitados. Si ninguno está habilitado, puede solicitar un cuadro de diálogo para cambiar la configuración desde la aplicación.
Este cuadro de diálogo es creado por LocationSettingsRequest.Builder disponible en los Servicios de Google Play.
build.gradle
agregar una dependencia a su aplicación
build.gradle
:
compile ''com.google.android.gms:play-services-location:10.0.1''
Entonces puedes usar este ejemplo mínimo:
private void displayLocationSettingsRequest(Context context) {
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).build();
googleApiClient.connect();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(10000 / 2);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
Log.i(TAG, "All location settings are satisfied.");
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to upgrade location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog not created.");
break;
}
}
});
}
Puedes encontrar el ejemplo completo here .
Gracias Mattia Maestrini por la respuesta, me gustaría agregar eso usando
compile ''com.google.android.gms:play-services-location:8.1.0''
bastaría. Esto evita que su aplicación incluya bibliotecas innecesarias y ayuda a mantener su método bajo.
Gracias a Mattia Maestrini +1
Solución de Xamarin:
using Android.Gms.Common.Apis;
using Android.Gms.Location;
public const int REQUEST_CHECK_SETTINGS = 0x1;
private void DisplayLocationSettingsRequest()
{
var googleApiClient = new GoogleApiClient.Builder(this).AddApi(LocationServices.API).Build();
googleApiClient.Connect();
var locationRequest = LocationRequest.Create();
locationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
locationRequest.SetInterval(10000);
locationRequest.SetFastestInterval(10000 / 2);
var builder = new LocationSettingsRequest.Builder().AddLocationRequest(locationRequest);
builder.SetAlwaysShow(true);
var result = LocationServices.SettingsApi.CheckLocationSettings(googleApiClient, builder.Build());
result.SetResultCallback((LocationSettingsResult callback) =>
{
switch (callback.Status.StatusCode)
{
case LocationSettingsStatusCodes.Success:
{
DoStuffWithLocation();
break;
}
case LocationSettingsStatusCodes.ResolutionRequired:
{
try
{
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
callback.Status.StartResolutionForResult(this, REQUEST_CHECK_SETTINGS);
}
catch (IntentSender.SendIntentException e)
{
}
break;
}
default:
{
// If all else fails, take the user to the android location settings
StartActivity(new Intent(Android.Provider.Settings.ActionLocationSourceSettings));
break;
}
}
});
}
protected override void OnActivityResult(int requestCode, Android.App.Result resultCode, Intent data)
{
switch (requestCode)
{
case REQUEST_CHECK_SETTINGS:
{
switch (resultCode)
{
case Android.App.Result.Ok:
{
DoStuffWithLocation();
break;
}
case Android.App.Result.Canceled:
{
//No location
break;
}
}
break;
}
}
}
La forma más sencilla que encontré durante mi investigación es crear una clase de Util para este proceso de solicitud de ubicación y luego llamarlo para activar los gps.
Por favor revise este blog! Contaba toda la historia.
Funciona de manera similar a Google Maps
Agregar dependencia en el archivo build.gradle
compile ''com.google.android.gms:play-services:8.3.0''
esta o aquella
compile ''com.google.android.gms:play-services-location:10.0.1''
import android.content.Context;
import android.content.IntentSender;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import java.util.List;
public class LocationOnOff_Similar_To_Google_Maps extends AppCompatActivity {
protected static final String TAG = "LocationOnOff";
private GoogleApiClient googleApiClient;
final static int REQUEST_LOCATION = 199;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setFinishOnTouchOutside(true);
// Todo Location Already on ... start
final LocationManager manager = (LocationManager) LocationOnOff_Similar_To_Google_Maps.this.getSystemService(Context.LOCATION_SERVICE);
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(LocationOnOff_Similar_To_Google_Maps.this)) {
Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
finish();
}
// Todo Location Already on ... end
if(!hasGPSDevice(LocationOnOff_Similar_To_Google_Maps.this)){
Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps not Supported",Toast.LENGTH_SHORT).show();
}
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(LocationOnOff_Similar_To_Google_Maps.this)) {
Log.e("keshav","Gps already enabled");
Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps not enabled",Toast.LENGTH_SHORT).show();
enableLoc();
}else{
Log.e("keshav","Gps already enabled");
Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
}
}
private boolean hasGPSDevice(Context context) {
final LocationManager mgr = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
if (mgr == null)
return false;
final List<String> providers = mgr.getAllProviders();
if (providers == null)
return false;
return providers.contains(LocationManager.GPS_PROVIDER);
}
private void enableLoc() {
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(LocationOnOff_Similar_To_Google_Maps.this)
.addApi(LocationServices.API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
googleApiClient.connect();
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d("Location error","Location error " + connectionResult.getErrorCode());
}
}).build();
googleApiClient.connect();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(LocationOnOff_Similar_To_Google_Maps.this, REQUEST_LOCATION);
finish();
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
}
}
});
}
}
}
Solución Kotlin
Agregar
build.gradle(Module:app)
implementation ''com.google.android.gms:play-services-location:17.0.0''
implementation ''com.google.android.gms:play-services-maps:17.0.0''
después de eso crea esta función
fun enablegps() {
val mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(2000)
.setFastestInterval(1000)
val settingsBuilder = LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest)
settingsBuilder.setAlwaysShow(true)
val result = LocationServices.getSettingsClient(this).checkLocationSettings(settingsBuilder.build())
result.addOnCompleteListener { task ->
//getting the status code from exception
try {
task.getResult(ApiException::class.java)
} catch (ex: ApiException) {
when (ex.statusCode) {
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {
Toast.makeText(this,"GPS IS OFF",Toast.LENGTH_SHORT).show()
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
val resolvableApiException = ex as ResolvableApiException
resolvableApiException.startResolutionForResult(this,REQUEST_CHECK_SETTINGS
)
} catch (e: IntentSender.SendIntentException) {
Toast.makeText(this,"PendingIntent unable to execute request.",Toast.LENGTH_SHORT).show()
}
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
Toast.makeText(
this,
"Something is wrong in your GPS",
Toast.LENGTH_SHORT
).show()
}
}
}
}
}
implementation ''com.google.android.gms:play-services-location:16.0.0''
Declaración Variable
private SettingsClient mSettingsClient;
private LocationSettingsRequest mLocationSettingsRequest;
private static final int REQUEST_CHECK_SETTINGS = 214;
private static final int REQUEST_ENABLE_GPS = 516;
Abrir el cuadro de diálogo con el siguiente código
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(new LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY));
builder.setAlwaysShow(true);
mLocationSettingsRequest = builder.build();
mSettingsClient = LocationServices.getSettingsClient(YourActivity.this);
mSettingsClient
.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
//Success Perform Task Here
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(YourActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sie) {
Log.e("GPS","Unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.e("GPS","Location settings are inadequate, and cannot be fixed here. Fix in Settings.");
}
}
})
.addOnCanceledListener(new OnCanceledListener() {
@Override
public void onCanceled() {
Log.e("GPS","checkLocationSettings -> onCanceled");
}
});
onActivityResult
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CHECK_SETTINGS) {
switch (resultCode) {
case Activity.RESULT_OK:
//Success Perform Task Here
break;
case Activity.RESULT_CANCELED:
Log.e("GPS","User denied to access location");
openGpsEnableSetting();
break;
}
} else if (requestCode == REQUEST_ENABLE_GPS) {
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!isGpsEnabled) {
openGpsEnableSetting();
} else {
navigateToUser();
}
}
}
private void openGpsEnableSetting() {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, REQUEST_ENABLE_GPS);
}