web-dev-qa-db-fra.com

obtenir la position actuelle rapidement et une fois dans android

J'ai une application Android qui nécessite l'emplacement actuel du périphérique (latitude et longitude). J'ai essayé un didacticiel sur Internet et plus particulièrement des solutions de débordement de pile, mais elles ne fonctionnent pas bien. Mon exigence est si simple: d’abord, j’ai besoin d’être rapide et de localiser le fragment une fois que j’ai commencé. Ensuite, j’ai besoin d’être aussi précis que possible. utiliser le fournisseur de réseau.

Par exemple, j'ai essayé cette solution mais elle retourne à zéro après 30 secondes, mais je sais qu'il y en a toutes les choses qui vont, car Google Map et d'autres applications fonctionnent bien !!!

Quelque chose que presque toutes les réponses suggèrent est d'utiliser getLastKnownLocation (), mais je suppose que ce n'est pas le courant et que je ne le veux pas s'il en est ainsi.

quelqu'un peut-il me suggérer une méthode simple et rapide pour obtenir l'emplacement UNE FOIS?!

Merci d'avance

39
Evil

Ici, vous pouvez utiliser ceci ...

Exemple d'utilisation:

public void foo(Context context) {
  // when you need location
  // if inside activity context = this;

  SingleShotLocationProvider.requestSingleUpdate(context, 
   new SingleShotLocationProvider.LocationCallback() {
     @Override public void onNewLocationAvailable(GPSCoordinates location) {
       Log.d("Location", "my location is " + location.toString());
     }
   });
}

Vous voudrez peut-être vérifier que les lat/long sont des valeurs réelles et non 0 ou quelque chose. Si je me souviens bien, cela ne devrait pas générer un NPE, mais vous voudrez peut-être vérifier.

public class SingleShotLocationProvider {

  public static interface LocationCallback {
      public void onNewLocationAvailable(GPSCoordinates location);
  }

  // calls back to calling thread, note this is for low grain: if you want higher precision, swap the 
  // contents of the else and if. Also be sure to check gps permission/settings are allowed.
  // call usually takes <10ms
  public static void requestSingleUpdate(final Context context, final LocationCallback callback) {
      final LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
      boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
      if (isNetworkEnabled) {
          Criteria criteria = new Criteria();
          criteria.setAccuracy(Criteria.ACCURACY_COARSE);
          locationManager.requestSingleUpdate(criteria, new LocationListener() {
              @Override
              public void onLocationChanged(Location location) {
                  callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
              }

              @Override public void onStatusChanged(String provider, int status, Bundle extras) { }
              @Override public void onProviderEnabled(String provider) { }
              @Override public void onProviderDisabled(String provider) { }
          }, null);
      } else {
          boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
          if (isGPSEnabled) {
              Criteria criteria = new Criteria();
              criteria.setAccuracy(Criteria.ACCURACY_FINE);
              locationManager.requestSingleUpdate(criteria, new LocationListener() {
                  @Override
                  public void onLocationChanged(Location location) {
                      callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
                  }

                  @Override public void onStatusChanged(String provider, int status, Bundle extras) { }
                  @Override public void onProviderEnabled(String provider) { }
                  @Override public void onProviderDisabled(String provider) { }
              }, null);
          }
      }
  }


  // consider returning Location instead of this dummy wrapper class
  public static class GPSCoordinates {
      public float longitude = -1;
      public float latitude = -1;

      public GPSCoordinates(float theLatitude, float theLongitude) {
          longitude = theLongitude;
          latitude = theLatitude;
      }

      public GPSCoordinates(double theLatitude, double theLongitude) {
          longitude = (float) theLongitude;
          latitude = (float) theLatitude;
      }
  }  
}
67
Ashton Engberg

AndroidManifest.xml

<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
<uses-feature Android:name="Android.hardware.location.gps" />

Demander les autorisations utilisateur


build.gradle (Module: app)

dependencies {
    ...
    implementation 'com.google.Android.gms:play-services-location:15.0.0'
    ...
}

Si vous recevez une erreur, vérifiez que votre build.gradle de niveau supérieur contient une référence au référentiel google () ou à maven {url " https://maven.google.com "}

Configurer les services Google Play


LocationService.kt

import Android.Manifest
import Android.annotation.SuppressLint
import Android.app.Activity
import Android.content.Intent
import Android.content.pm.PackageManager
import Android.location.Location
import Android.net.Uri
import Android.os.Looper
import Android.provider.Settings
import Android.support.v4.app.ActivityCompat
import Android.support.v4.content.ContextCompat
import com.google.Android.gms.common.api.ApiException
import com.google.Android.gms.common.api.ResolvableApiException
import com.google.Android.gms.location.*
import org.jetbrains.anko.alert
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.okButton

object LocationService {

    @SuppressLint("StaticFieldLeak")
    private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
    private lateinit var locationRequest: LocationRequest
    private val locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            doAsync {
                location = locationResult.lastLocation
                onSuccess(location)
            }
        }
    }
    private lateinit var onSuccess: (location : Location) -> Unit
    private lateinit var onError: () -> Unit
    lateinit var location: Location

    fun init(activity: Activity) {
        fusedLocationProviderClient = FusedLocationProviderClient(activity)
        locationRequest = LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(1000).setFastestInterval(1000).setNumUpdates(1)
    }

    private fun checkLocationStatusAndGetLocation(activity: Activity) {
        doAsync {
            when {
                ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED -> LocationServices.getSettingsClient(activity).checkLocationSettings(LocationSettingsRequest.Builder().addLocationRequest(locationRequest).setAlwaysShow(true).build()).addOnCompleteListener { task ->
                    doAsync {
                        try {
                            task.getResult(ApiException::class.Java)
                            fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
                        } catch (exception: ApiException) {
                            when (exception.statusCode) {
                                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                                    try {
                                        (exception as ResolvableApiException).startResolutionForResult(activity, 7025)
                                    } catch (ex: Exception) {
                                        promptShowLocation(activity)
                                    }
                                }
                                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                                    promptShowLocation(activity)
                                }
                            }
                        }
                    }
                }
                ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION) -> activity.runOnUiThread {
                    activity.alert("To continue, allow the device to use location, witch uses Google's Location Service") {
                        okButton {
                            val ite = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", activity.packageName, null))
                            ite.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                            activity.startActivity(ite)
                            onError()
                        }
                        negativeButton("Cancelar", { onError() })
                        onCancelled { onError() }
                    }.show()
                }
                else -> ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 7024)
            }
        }
    }

    private fun promptShowLocation(activity: Activity) {
        activity.runOnUiThread {
            activity.alert("To continue, allow the device to use location, witch uses Google's Location Service") {
                okButton {
                    activity.startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS))
                    onError()
                }
                negativeButton("Cancelar", { onError() })
                onCancelled { onError() }
            }.show()
        }
    }

    fun onRequestPermissionsResult(activity: Activity, requestCode: Int, grantResults: IntArray) {
        if (requestCode == 7024) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                checkLocationStatusAndGetLocation(activity)
            } else {
                onError()
            }
        }
    }

    fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int) {
        if (requestCode == 7025) {
            if (resultCode == Activity.RESULT_OK) {
                checkLocationStatusAndGetLocation(activity)
            } else {
                onError()
            }
        }
    }

    fun getLocation(activity: Activity, onSuccess: () -> Unit, onError: () -> Unit) {
        this.onSuccess = onSuccess
        this.onError = onError
        checkLocationStatusAndGetLocation(activity)
    }

}

votre activité

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    LocationService.init(this)
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    LocationService.onRequestPermissionsResult(this, requestCode, grantResults)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    LocationService.onActivityResult(this, requestCode, resultCode)
}

private fun yourFunction() {
    LocationService.getLocation(this, { location ->
        //TODO: use the location
    }, {
        //TODO: display error message
    })
}
3
Ruan Barroso

AndroidManifest.xml:

<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
<uses-feature Android:name="Android.hardware.location.gps" />

MainActivity.Java:

public class MainActivity extends AppCompatActivity implements LocationListener {

    private LocationManager locationManager;
    private Location onlyOneLocation;
    private final int REQUEST_FINE_LOCATION = 1234;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
            ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION);
    }

    @Override public void onLocationChanged(Location location) {
        onlyOneLocation = location;
        locationManager.removeUpdates(this);
    }
    @Override public void onStatusChanged(String provider, int status, Bundle extras) { }
    @Override public void onProviderEnabled(String provider) { }
    @Override public void onProviderDisabled(String provider) { }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
        case REQUEST_FINE_LOCATION:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.d("gps", "Location permission granted");
                try {
                    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
                    locationManager.requestLocationUpdates("gps", 0, 0, this);
                }
                catch (SecurityException ex) {
                    Log.d("gps", "Location permission did not work!");
                }
            }
            break;
    }
}
2
Lou Morda
    // Get LocationManager object
    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

    // Create a criteria object to retrieve provider
    Criteria criteria = new Criteria();

    // Get the name of the best provider
    String provider = locationManager.getBestProvider(criteria, true);

    // Get Current Location
    Location myLocation = locationManager.getLastKnownLocation(provider);

    //latitude of location
    double myLatitude = myLocation.getLatitude();

    //longitude og location
    double myLongitude = myLocation.getLongitude();

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
1
IskoldNinja

Ce que vous voulez faire est réalisé en utilisant le LocationManager#requestSingleUpdate . Cette méthode attache un écouteur dans un boucleur donné (si vous le souhaitez ou le possédez) et notifie l'emplacement une fois qu'il est reçu, une seule fois. La méthode que vous suggérez n’est utilisée que comme une position inexacte avant que la vraie ne vous soit donnée.

Dans tous les cas, ce sera plus rapide que quelques millisecondes (à moins que vous n'ayez la chance de commencer à écouter lorsqu'un emplacement est arrivé sur l'appareil). Pensez au GPS comme un élément que vous activez lorsque vous attendez des emplacements et que vous désactivez lorsque vous supprimez cette écoute. Ce comportement est fait pour éviter de vider la batterie de l'utilisateur.

Pour résumer:

  • Le temps écoulé entre le moment où vous commencez à écouter et le moment où vous recevez la position dépend du GPS de l'appareil (fabricant, localisation de l'utilisateur, couverture satellite ...).
  • Il existe une méthode dans le SDK Android) pour écouter une seule mise à jour.
  • En fournissant l'objet Critères, vous pouvez gérer les critères acceptables pour recevoir un emplacement. Des critères plus stricts signifient plus de temps pour obtenir une réponse précise.
1
droidpl

Toutes les réponses ci-dessus ne fonctionnent pas pour moi, alors j'ai répondu à cette question. Initialement, ajoutez les dépendances.

<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
<uses-feature Android:name="Android.hardware.location.gps" />

après avoir ajouté la classe MyLocationListiner.Java

package com.example.firebase_auth;

/**
 * Created by Chromicle(Ajay Prabhakar).
 */

import Android.content.Context;
import Android.content.pm.PackageManager;
import Android.location.Location;
import Android.location.LocationListener;
import Android.location.LocationManager;
import Android.os.Build;
import Android.os.Bundle;
import Android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import static Android.content.Context.LOCATION_SERVICE;

public class MyLocationListener implements LocationListener {

    public static double latitude;
    Context ctx;
    Location location;
    LocationManager locationManager;
    boolean isGPSEnabled = false;
    boolean isNetworkEnabled = false;
    public static double longitude;
    MyLocationListener(Context ctx) {
        this.ctx = ctx;
        try {
            locationManager = (LocationManager) ctx.getSystemService(LOCATION_SERVICE);
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            Toast.makeText(ctx, "GPS Enable " + isGPSEnabled, Toast.LENGTH_LONG).show();
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            Toast.makeText(ctx, "Network Enable " + isNetworkEnabled, Toast.LENGTH_LONG).show();

            if ( Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission
                    ( ctx, Android.Manifest.permission.ACCESS_FINE_LOCATION )
                    != PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission( ctx,
                            Android.Manifest.permission.ACCESS_COARSE_LOCATION) !=
                            PackageManager.PERMISSION_GRANTED) {  }
            if (isGPSEnabled == true) {
                locationManager.requestLocationUpdates(
                        LocationManager.GPS_PROVIDER,     0,       0, this);
                location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            }
            if (isNetworkEnabled==true) {
                locationManager.requestLocationUpdates(
                        LocationManager.NETWORK_PROVIDER,    0,     0, this);
                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            // Toast.makeText(ctx,"latitude: "+latitude+" longitude: "+longitude,Toast.LENGTH_LONG).show();


        }
        catch(Exception ex)
        {

            Toast.makeText(ctx,"Exception "+ex, Toast.LENGTH_LONG).show();
        }
    }
    @Nullable
    @Override
    public void onLocationChanged(Location loc)
    {
        loc.getLatitude();
        loc.getLongitude();
        latitude=loc.getLatitude();
        longitude=loc.getLongitude();
    }

    @Override
    public void onProviderDisabled(String provider)
    {
        //print "Currently GPS is Disabled";
    }
    @Override
    public void onProviderEnabled(String provider)
    {
        //print "GPS got Enabled";
    }
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras)
    {

    }
}

Pour utiliser cette classe ajouter cet emplacement de méthode est stocké dans la chaîne d'adresse

public void getLocation(){
        Double latitude = 0.0, longitude;
        String message = "";
        LocationManager mlocManager = null;
        LocationListener mlocListener;
        mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        mlocListener = new MyLocationListener(this);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
        if (mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {

            latitude = MyLocationListener.latitude;
            longitude = MyLocationListener.longitude;
            message = message +"https://www.google.com/maps/dir/@"+ latitude +","+  longitude;
            address=message;
            Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
            if (latitude == 0.0) {
                Toast.makeText(getApplicationContext(), "Currently gps has not found your location....", Toast.LENGTH_LONG).show();
            }

        } else {
            Toast.makeText(getApplicationContext(), "GPS is currently off...", Toast.LENGTH_LONG).show();
        }
    }

J'espère que ça vous sera utile

0
ajay prabhakar