Contrairement à l'approche traditionnelle qui consiste à inciter l'utilisateur à accéder à la page des paramètres, à activer les services de localisation et à revenir, j'ai remarqué une manière plus simple de procéder de la même manière dans certaines des dernières applications.
En vous référant à la capture d'écran ci-dessous, il invite l'utilisateur à activer une boîte de dialogue pour activer les services de localisation en un seul clic et cela fonctionne dans ces applications.
Comment puis-je atteindre le même?
Cette boîte de dialogue est créée par LocationSettingsRequest.Builder disponible dans les services Google Play.
Vous devez ajouter une dépendance à votre application build.gradle
:
compile 'com.google.Android.gms:play-services-location:10.0.1'
Ensuite, vous pouvez utiliser cet exemple minimal:
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;
}
}
});
}
Vous pouvez trouver l'exemple complet ici .
1) Créez une LocationRequest
selon votre souhait.
LocationRequest mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000)
.setFastestInterval(1 * 1000);
2) Créez un LocationSettingsRequest.Builder
LocationSettingsRequest.Builder settingsBuilder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
settingsBuilder.setAlwaysShow(true);
3) Récupère LocationSettingsResponse
Task
à l'aide du code suivant
Task<LocationSettingsResponse> result = LocationServices.getSettingsClient(this)
.checkLocationSettings(settingsBuilder.build());
Remarque: LocationServices.SettingsApi
est obsolète, utilisez SettingsClient
à la place.
4) Ajoutez un OnCompleteListener
pour obtenir le résultat de la tâche. Lorsque le Task
est terminé, le client peut vérifier l'emplacement. paramètres en regardant le code de statut de l’objet 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;
}
}
}
});
CAS 1: LocationSettingsStatusCodes.RESOLUTION_REQUIRED
: l'emplacement n'est pas activé, mais nous pouvons demander à l'utilisateur d'activer l'emplacement en l'invitant à l'activer. avec le dialogue (en appelant startResolutionForResult
).
CAS 2: LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE
: Les paramètres de localisation ne sont pas satisfaits. Cependant, nous n'avons aucun moyen de modifier les paramètres, nous n'allons donc pas afficher la boîte de dialogue.
5) OnActivityResult
nous pouvons obtenir l'action de l'utilisateur dans la boîte de dialogue des paramètres d'emplacement. RESULT_OK
=> L'utilisateur a activé l'emplacement. RESULT_CANCELLED
- L'utilisateur a refusé la demande de paramétrage d'emplacement.
Son fonctionnement est similaire à celui de Google Maps
Ajouter une dépendance dans le fichier build.gradle
compile 'com.google.Android.gms:play-services:8.3.0'
ceci ou cela
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;
}
}
});
}
}
}
implementation 'com.google.Android.gms:play-services-location:16.0.0'
Déclaration de variable
private SettingsClient mSettingsClient;
private LocationSettingsRequest mLocationSettingsRequest;
private static final int REQUEST_CHECK_SETTINGS = 214;
private static final int REQUEST_ENABLE_GPS = 516;
Ouvrir la boîte de dialogue en utilisant le code ci-dessous
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);
}
Merci à Mattia Maestrini + 1
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;
}
}
}
Merci Mattia Maestrini pour la réponse, je voudrais ajouter que l'utilisation de
compile 'com.google.Android.gms:play-services-location:8.1.0'
suffirait. Cela empêche votre application d'inclure des bibliothèques inutiles et vous aide à limiter le nombre de méthodes.
Android Marshmallow 6 prend en charge les autorisations d'exécution. Les autorisations d'exécution ne fonctionnent que sur Marshmallow et sur les versions antérieures, elles fonctionnent toujours à l'ancienne.
Vous en apprendrez plus à ce sujet dans cette Android Vidéo officielle du développeur:
https://www.youtube.com/watch?v=C8lUdPVSzDk
Et demander la permission: http://developer.Android.com/training/permissions/requesting.html
Avec la mise à jour récente de Marshmallow, même lorsque le paramètre Emplacement est activé, votre application devra demander explicitement une autorisation. Pour ce faire, il est recommandé d’afficher la section Autorisations de votre application dans laquelle l’utilisateur peut modifier l’autorisation si nécessaire. L'extrait de code permettant de faire cela est comme ci-dessous:
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
}
Et substituez la méthode onRequestPermissionsResult
comme ci-dessous:
@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);
}
}
}
}
Une autre approche consiste à utiliser le paramètre SettingsApi pour connaître le ou les fournisseurs d'emplacement activés. Si aucun n'est activé, vous pouvez demander à une boîte de dialogue de modifier le paramètre depuis l'application.
Le moyen le plus simple que j’ai trouvé lors de mes recherches est de créer une classe Util pour ce processus de demande de localisation puis de l’appeler pour activer le GPS pour nous.
S'il vous plaît vérifier ce blog! Il a raconté toute l'histoire.
Solution Kotlin
Ajouter 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'
après que créer cette fonction
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()
}
}
}
}
}