¿Cómo obtengo la ubicación GPS actual mediante programación en Android?


Respuestas:


432

He creado una pequeña aplicación con una descripción paso a paso para obtener las coordenadas GPS de la ubicación actual.

El código fuente completo del ejemplo se encuentra en Obtener coordenadas de ubicación actual, Nombre de ciudad - en Android .


Mira cómo funciona:

  • Todo lo que necesitamos hacer es agregar este permiso en el archivo de manifiesto:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  • Y cree una instancia de LocationManager como esta:

    LocationManager locationManager = (LocationManager)
    getSystemService(Context.LOCATION_SERVICE);
  • Compruebe si el GPS está habilitado o no.

  • Y luego implemente LocationListener y obtenga coordenadas:

    LocationListener locationListener = new MyLocationListener();
    locationManager.requestLocationUpdates(
    LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
  • Aquí está el código de muestra para hacerlo


/*---------- Listener class to get coordinates ------------- */
private class MyLocationListener implements LocationListener {

    @Override
    public void onLocationChanged(Location loc) {
        editLocation.setText("");
        pb.setVisibility(View.INVISIBLE);
        Toast.makeText(
                getBaseContext(),
                "Location changed: Lat: " + loc.getLatitude() + " Lng: "
                    + loc.getLongitude(), Toast.LENGTH_SHORT).show();
        String longitude = "Longitude: " + loc.getLongitude();
        Log.v(TAG, longitude);
        String latitude = "Latitude: " + loc.getLatitude();
        Log.v(TAG, latitude);

        /*------- To get city name from coordinates -------- */
        String cityName = null;
        Geocoder gcd = new Geocoder(getBaseContext(), Locale.getDefault());
        List<Address> addresses;
        try {
            addresses = gcd.getFromLocation(loc.getLatitude(),
                    loc.getLongitude(), 1);
            if (addresses.size() > 0) {
                System.out.println(addresses.get(0).getLocality());
                cityName = addresses.get(0).getLocality();
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        String s = longitude + "\n" + latitude + "\n\nMy Current City is: "
            + cityName;
        editLocation.setText(s);
    }

    @Override
    public void onProviderDisabled(String provider) {}

    @Override
    public void onProviderEnabled(String provider) {}

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


36
¿Esto significa que tiene que mudarse antes de que haya una actualización de ubicación? ¿Por qué no muestra tu ubicación actual la primera vez que lo intentas después de la instalación?
Nii Laryea

15
@NiiLaryea porque obtengo Location usando el método " onLocationChanged () " que ofrece cada vez una nueva ubicación mientras te mueves, pero si quieres solo una vez, debes llamar a " getLastKnownLocation () "
swiftBoy

Si solo hay una dirección en adressesla línea que comienza cityName =, fallará con una excepción. El uso de llaves lo arreglaría.
Carrotman42

2
Escuché que la gente dice que getLastKnownLocation()es una ubicación más "obsoleta", ¿por qué es esto? ¿Las llamadas getLastKnownLocation()no obtienen la última lectura de GPS del GPS del teléfono?
Don Cheadle

99
@mmcrae No, no lo hace. El GPS no siempre está funcionando. getLastKnownLocation no lo enciende. Obtiene la última ubicación desde la última vez que estuvo encendido. El sombrero podría ser realmente fresco, de una hora de antigüedad, o incluso nulo.
Gabe Sechan

139

Aquí hay información adicional para otras respuestas.

Como Android tiene

GPS_PROVIDER and NETWORK_PROVIDER

puede registrarse en ambos y comenzar a buscar eventos onLocationChanged(Location location)de dos al mismo tiempo. Hasta aquí todo bien. Ahora la pregunta, ¿necesitamos dos resultados o deberíamos tomar lo mejor? Como sé, los GPS_PROVIDERresultados tienen mejor precisión que NETWORK_PROVIDER.

Definamos el Locationcampo:

private Location currentBestLocation = null;

Antes de comenzar a escuchar el cambio de ubicación , implementaremos el siguiente método. Este método devuelve la última ubicación conocida, entre el GPS y la red. Para este método más nuevo es el mejor.

/**
 * @return the last know best location
 */
private Location getLastBestLocation() {
    Location locationGPS = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    Location locationNet = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

    long GPSLocationTime = 0;
    if (null != locationGPS) { GPSLocationTime = locationGPS.getTime(); }

    long NetLocationTime = 0;

    if (null != locationNet) {
        NetLocationTime = locationNet.getTime();
    }

    if ( 0 < GPSLocationTime - NetLocationTime ) {
        return locationGPS;
    }
    else {
        return locationNet;
    }
}

Cada vez que recuperamos una nueva ubicación, la compararemos con nuestro resultado anterior.

...
static final int TWO_MINUTES = 1000 * 60 * 2;
...

Añado un nuevo método para onLocationChanged:

@Override
public void onLocationChanged(Location location) {

    makeUseOfNewLocation(location);

    if(currentBestLocation == null){
        currentBestLocation = location;
    }

    ....
}


/**
 * This method modify the last know good location according to the arguments.
 *
 * @param location The possible new location.
 */
void makeUseOfNewLocation(Location location) {
    if ( isBetterLocation(location, currentBestLocation) ) {
        currentBestLocation = location;
    }
}

....

/** Determines whether one location reading is better than the current location fix
 * @param location  The new location that you want to evaluate
 * @param currentBestLocation  The current location fix, to which you want to compare the new one.
 */
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
    if (currentBestLocation == null) {
        // A new location is always better than no location
        return true;
    }

    // Check whether the new location fix is newer or older
    long timeDelta = location.getTime() - currentBestLocation.getTime();
    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
    boolean isNewer = timeDelta > 0;

    // If it's been more than two minutes since the current location, use the new location,
    // because the user has likely moved.
    if (isSignificantlyNewer) {
        return true;
        // If the new location is more than two minutes older, it must be worse.
    } else if (isSignificantlyOlder) {
        return false;
    }

    // Check whether the new location fix is more or less accurate
    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    boolean isLessAccurate = accuracyDelta > 0;
    boolean isMoreAccurate = accuracyDelta < 0;
    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

    // Check if the old and new location are from the same provider
    boolean isFromSameProvider = isSameProvider(location.getProvider(),
                                                currentBestLocation.getProvider());

    // Determine location quality using a combination of timeliness and accuracy
    if (isMoreAccurate) {
        return true;
    } else if (isNewer && !isLessAccurate) {
        return true;
    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
        return true;
    }
    return false;
}

// Checks whether two providers are the same
private boolean isSameProvider(String provider1, String provider2) {
    if (provider1 == null) {
        return provider2 == null;
    }
    return provider1.equals(provider2);
}

....

Hola, ese es un buen ejemplo ... pero ¿podrías darme un ejemplo más completo? Tengo problemas para integrarlo en mi código existente. Además, estoy usando solo GPS como proveedor.
beerBear

1
@quantumstates Creo que es bastante completo. Simplemente cree el campo private Location currentBestLocation = null;y agregue `makeUseOfNewLocation (location);` al método onLocationChanged (..)
Maxim Shoustin

Gracias Maxim Tengo una pregunta. ¿Dónde utiliza el método 'getLastBestLocation'?
SeyedPooya Soofbaf

@SeyyedPuyaSoofbaf Generalmente, la nueva ubicación que obtenemos después de unos 30 segundos. Si nos registramos en ambos Gerentes, podemos obtener de inmediato las 2 últimas ubicaciones conocidas y decidir cuál es la más nueva.
Maxim Shoustin

No me doy cuenta de cuáles son las diferencias entre getLastBestLocation y isBetterLocation. Estos dos métodos se han utilizado para comparar dos ubicaciones.
SeyedPooya Soofbaf

84

Puede encontrar la ubicación ya sea por GPS_PROVIDER or NETWORK_PROVIDER.

Descripción general de los servicios de ubicación en Android.

Aquí hay un ejemplo que intenta encontrar la ubicación usando el GPS. Si su GPS no está disponible, intente usar la red para encontrar la ubicación.

GPSTracker.java

 public class GPSTracker extends Service implements LocationListener {

    private final Context mContext;

    // Flag for GPS status
    boolean isGPSEnabled = false;

    // Flag for network status
    boolean isNetworkEnabled = false;

    // Flag for GPS status
    boolean canGetLocation = false;

    Location location; // Location
    double latitude; // Latitude
    double longitude; // Longitude

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;

    public GPSTracker(Context context) {
        this.mContext = context;
        getLocation();
    }

    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext
                    .getSystemService(LOCATION_SERVICE);

            // Getting GPS status
            isGPSEnabled = locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);

            // Getting network status
            isNetworkEnabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                // No network provider is enabled
            } else {
                this.canGetLocation = true;
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                // If GPS enabled, get latitude/longitude using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }


    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app.
     * */
    public void stopUsingGPS(){
        if(locationManager != null){
            locationManager.removeUpdates(GPSTracker.this);
        }
    }


    /**
     * Function to get latitude
     * */
    public double getLatitude(){
        if(location != null){
            latitude = location.getLatitude();
        }

        // return latitude
        return latitude;
    }


    /**
     * Function to get longitude
     * */
    public double getLongitude(){
        if(location != null){
            longitude = location.getLongitude();
        }

        // return longitude
        return longitude;
    }

    /**
     * Function to check GPS/Wi-Fi enabled
     * @return boolean
     * */
    public boolean canGetLocation() {
        return this.canGetLocation;
    }


    /**
     * Function to show settings alert dialog.
     * On pressing the Settings button it will launch Settings Options.
     * */
    public void showSettingsAlert(){
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        // Setting Dialog Title
        alertDialog.setTitle("GPS is settings");

        // Setting Dialog Message
        alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

        // On pressing the Settings button.
        alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog,int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
            }
        });

        // On pressing the cancel button
        alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
            dialog.cancel();
            }
        });

        // Showing Alert Message
        alertDialog.show();
    }


    @Override
    public void onLocationChanged(Location location) {
    }


    @Override
    public void onProviderDisabled(String provider) {
    }


    @Override
    public void onProviderEnabled(String provider) {
    }


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


    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}

Actividad -AndroidGPSTrackingActivity.java

    public class AndroidGPSTrackingActivity extends Activity {

    Button btnShowLocation;

    // GPSTracker class
    GPSTracker gps;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnShowLocation = (Button) findViewById(R.id.btnShowLocation);

        // Show location button click event
        btnShowLocation.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // Create class object
                gps = new GPSTracker(AndroidGPSTrackingActivity.this);

                // Check if GPS enabled
                if(gps.canGetLocation()) {

                    double latitude = gps.getLatitude();
                    double longitude = gps.getLongitude();

                    // \n is for new line
                    Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
                } else {
                    // Can't get location.
                    // GPS or network is not enabled.
                    // Ask user to enable GPS/network in settings.
                    gps.showSettingsAlert();
                }
            }
        });
    }
}

Layout- main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button android:id="@+id/btnShowLocation"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Location"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"/>
</RelativeLayout>

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />

44
Creo que hay un problema con este ejemplo, parece que nunca usas el oyente de ubicación. Siempre está usando GetLastKnownLocation () que podría no ser la última
Madhur Ahuja

16
Tengo que votar a favor de sobrevalorado. El código aquí es decente, pero está siendo utilizado por muchas personas que no lo entienden, y tiene algunas fallas en su uso de getLastKnownLocation: recibimos muchas preguntas de personas que lo usan y obtienen ubicaciones obsoletas, sin saber Están rancios. Además, el valor de canGetLocation es incorrecto, lo establece en función de si el proveedor está habilitado pero no verifica si getLastKnownLocation devuelve un valor real; simplemente asume que lo hará. Creo que esto podría hacerse bien, pero no sugeriría que nadie lo use como está.
Gabe Sechan

1
El permiso ACCESS_FINE_LOCATION es suficiente de acuerdo con los documentos de Android: si está utilizando NETWORK_PROVIDER y GPS_PROVIDER, solo necesita solicitar el permiso ACCESS_FINE_LOCATION, ya que incluye permiso para ambos proveedores. (El permiso para ACCESS_COARSE_LOCATION incluye permiso solo para NETWORK_PROVIDER.)
Eng. Samer T

Probé este código y su ubicación no es precisa.
misha312

No es la versión correcta del código, no da la ubicación correcta
Moeez

45

Ya hay muchas respuestas allí, pero quiero mostrar la última forma de obtener la ubicación utilizando la API de Google, para que los nuevos programadores puedan usar un nuevo método:

He escrito un tutorial detallado sobre la ubicación actual en Android en mi blog demonuts.com También puedes encontrar el código fuente completo desarrollado con Android Studio.

En primer lugar, pon esto en el archivo gradle

 compile 'com.google.android.gms:play-services:9.0.2'

luego implemente las interfaces necesarias

public class MainActivity  extends BaseActivitiy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener

declarar instancias

  private GoogleApiClient mGoogleApiClient;
  private Location mLocation;
  private LocationManager locationManager;
  private LocationRequest mLocationRequest;

poner esto en onCreate()

 mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

Por fin, anule los métodos necesarios

 @Override
    public void onConnected(Bundle bundle) {
        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;
        } startLocationUpdates();
        mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if(mLocation == null){
            startLocationUpdates();
        }
        if (mLocation != null) {
            double latitude = mLocation.getLatitude();
            double longitude = mLocation.getLongitude();
        } else {
            // Toast.makeText(this, "Location not Detected", Toast.LENGTH_SHORT).show();
        }
    }

    protected void startLocationUpdates() {
        // Create the location request
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(UPDATE_INTERVAL)
                .setFastestInterval(FASTEST_INTERVAL);
        // Request location updates
        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;
        }
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                mLocationRequest, this);
        Log.d("reque", "--->>>>");
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG, "Connection Suspended");
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.i(TAG, "Connection failed. Error: " + connectionResult.getErrorCode());
    }

    @Override
    public void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
    }
    @Override
    public void onLocationChanged(Location location) {

    }

No olvide iniciar el GPS en su dispositivo antes de ejecutar la aplicación.


Utilicé su método para mostrar las coordenadas, pero no puedo ver las coordenadas, ¿puede examinar mi pregunta ?
Moeez

1
mLocationsiempre da nulo. Intenté lo mismo que se mencionó
dharanbro el

Vaya a este enlace: demonuts.com/2016/12/30/get-current-gps-location-android-studio y descargue el código fuente desde allí y verifique si el código fuente funciona en su PC o no
Parsania Hardik

55
Esta debería ser la respuesta aceptada. Y para ser más compacto, puede usar en compile 'com.google.android.gms:play-services-location:11.0.4'lugar de agregar todos los servicios de Google Play a su aplicación.
Morris Franken

37

Como no me gustó parte del código en las otras respuestas, aquí está mi solución simple. Esta solución está destinada a ser utilizable en una Actividad o Servicio para rastrear la ubicación. Se asegura de que nunca devuelva datos demasiado obsoletos a menos que solicite explícitamente datos obsoletos. Se puede ejecutar en modo de devolución de llamada para obtener actualizaciones a medida que las recibimos, o en modo de encuesta para buscar la información más reciente.

Interfaz genérica de LocationTracker. Nos permite tener múltiples tipos de rastreadores de ubicación y enchufar fácilmente el apropiado:

package com.gabesechan.android.reusable.location;

import android.location.Location;

public interface LocationTracker {
    public interface LocationUpdateListener{
        public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime);
    }

    public void start();
    public void start(LocationUpdateListener update);

    public void stop();

    public boolean hasLocation();

    public boolean hasPossiblyStaleLocation();

    public Location getLocation();

    public Location getPossiblyStaleLocation();

}

ProviderLocationTracker: esta clase rastreará la ubicación para GPS o RED.

package com.gabesechan.android.reusable.location;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class ProviderLocationTracker implements LocationListener, LocationTracker {

    // The minimum distance to change Updates in meters
    private static final long MIN_UPDATE_DISTANCE = 10; 

    // The minimum time between updates in milliseconds
    private static final long MIN_UPDATE_TIME = 1000 * 60; 

    private LocationManager lm;

    public enum ProviderType{
        NETWORK,
        GPS
    };    
    private String provider;

    private Location lastLocation;
    private long lastTime;

    private boolean isRunning;

    private LocationUpdateListener listener;

    public ProviderLocationTracker(Context context, ProviderType type) {
        lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        if(type == ProviderType.NETWORK){
            provider = LocationManager.NETWORK_PROVIDER;
        }
        else{
            provider = LocationManager.GPS_PROVIDER;
        }
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //The provider is on, so start getting updates.  Update current location
        isRunning = true;
        lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
        lastLocation = null;
        lastTime = 0;
        return;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;

    }


    public void stop(){
        if(isRunning){
            lm.removeUpdates(this);
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        if(lastLocation == null){
            return false;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return false; //stale
        }
        return true;
    }

    public boolean hasPossiblyStaleLocation(){
        if(lastLocation != null){
            return true;
        }
        return lm.getLastKnownLocation(provider)!= null;
    }

    public Location getLocation(){
        if(lastLocation == null){
            return null;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return null; //stale
        }
        return lastLocation;
    }

    public Location getPossiblyStaleLocation(){
        if(lastLocation != null){
            return lastLocation;
        }
        return lm.getLastKnownLocation(provider);
    }

    public void onLocationChanged(Location newLoc) {
        long now = System.currentTimeMillis();
        if(listener != null){
            listener.onUpdate(lastLocation, lastTime, newLoc, now);
        }
        lastLocation = newLoc;
        lastTime = now;
    }

    public void onProviderDisabled(String arg0) {

    }

    public void onProviderEnabled(String arg0) {

    }

    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
    }
}

El es el FallbackLocationTracker, que rastreará tanto por GPS como por RED, y usará cualquier ubicación que sea más precisa.

package com.gabesechan.android.reusable.location;

import android.content.Context;
import android.location.Location;
import android.location.LocationManager;

public class FallbackLocationTracker  implements LocationTracker, LocationTracker.LocationUpdateListener {


    private boolean isRunning;

    private ProviderLocationTracker gps;
    private ProviderLocationTracker net;

    private LocationUpdateListener listener;

    Location lastLoc;
    long lastTime;

    public FallbackLocationTracker(Context context) {
        gps = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.GPS);
        net = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.NETWORK);
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //Start both
        gps.start(this);
        net.start(this);
        isRunning = true;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;
    }


    public void stop(){
        if(isRunning){
            gps.stop();
            net.stop();
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        //If either has a location, use it
        return gps.hasLocation() || net.hasLocation();
    }

    public boolean hasPossiblyStaleLocation(){
        //If either has a location, use it
        return gps.hasPossiblyStaleLocation() || net.hasPossiblyStaleLocation();
    }

    public Location getLocation(){
        Location ret = gps.getLocation();
        if(ret == null){
            ret = net.getLocation();
        }
        return ret;
    }

    public Location getPossiblyStaleLocation(){
        Location ret = gps.getPossiblyStaleLocation();
        if(ret == null){
            ret = net.getPossiblyStaleLocation();
        }
        return ret;
    }

    public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) {
        boolean update = false;

        //We should update only if there is no last location, the provider is the same, or the provider is more accurate, or the old location is stale
        if(lastLoc == null){
            update = true;
        }
        else if(lastLoc != null && lastLoc.getProvider().equals(newLoc.getProvider())){
            update = true;
        }
        else if(newLoc.getProvider().equals(LocationManager.GPS_PROVIDER)){
            update = true;
        }
        else if (newTime - lastTime > 5 * 60 * 1000){
            update = true;
        }

        if(update){
            if(listener != null){
                listener.onUpdate(lastLoc, lastTime, newLoc, newTime);                  
            }
            lastLoc = newLoc;
            lastTime = newTime;
        }

    }
}

Dado que ambos implementan la interfaz LocationTracker, puede cambiar fácilmente de opinión acerca de cuál usar. Para ejecutar la clase en modo encuesta, solo llame a start (). Para ejecutarlo en modo de actualización, llame a start (Listener).

También eche un vistazo a mi blog en el código


Para cualquier persona curiosa, la razón por la que no uso los tiempos integrados en el objeto Ubicación es porque la API no existe hasta la API 17. Como quiero mantener la compatibilidad con 14, solo uso la hora actual. Esa es también la razón por la que no llamo a getLastKnownLocation temprano, porque no podemos obtener un tiempo y ver si está rancio.
Gabe Sechan

Su código es la mejor y la solución más completa que he encontrado en los últimos dos días de búsqueda sobre este tema. Funciona sin errores y como un encanto, es impresionante. Solo una cosa, cambié FallbackLocationTracker (contexto de contexto, tipo de tipo de proveedor), a FallbackLocationTracker público (contexto de contexto) ya que no necesitamos enviar un proveedor a esta clase, tiene en cuenta tanto el GPS como la red, ¿estoy en lo cierto?
zeeshan

@zeeshan Tienes razón, y actualicé el código aquí. Lo haré en mi blog la próxima vez que encuentre algo de tiempo (un recurso difícil de conseguir para mí en estos días). Como probablemente haya adivinado, creé el respaldo copiando y pegando de la otra clase y nunca hice esa limpieza.
Gabe Sechan

12
mejor solución ... pero solo falta una cosa ... Un principiante no puede implementarlo ... también debería haber un ejemplo de uso en él ...
Zaffar Saffee

1
hola @GabeSechan He implementado tu método, pero cada vez que enciendo el GPS en la configuración de mi dispositivo Android y dejo la red encendida, siempre devuelve nulo en el método getLocation. FallbackLocationTracker fallbackLocationTracker = new FallbackLocationTracker(mContext); fallbackLocationTracker.start(); if (fallbackLocationTracker.hasLocation()) { return fallbackLocationTracker.getLocation(); }
neteot

18

Obtener ubicación de gps por -

LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

LocationListener locationListener = new LocationListener() 
{

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderEnabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderDisabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLocationChanged(Location location) {
                // TODO Auto-generated method stub
                double latitude = location.getLatitude();
                double longitude = location.getLongitude();
                double speed = location.getSpeed(); //spedd in meter/minute
                speed = (speed*3600)/1000;      // speed in km/minute               Toast.makeText(GraphViews.this, "Current speed:" + location.getSpeed(),Toast.LENGTH_SHORT).show();
            }
        };

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);

}

2
El objetivo siempre es un código menos preciso y no exagerar la verificación de ubicación simple como muchas de las otras respuestas. Gracias por responder la pregunta que se hizo.
SmulianJulian

Cómo obtener la ubicación cada 1 segundo
Ruchir Baronia

Gracias por la forma sencilla de obtener GPS, ¡funciona! Un microbug: location.getSpeed()devuelve la velocidad en metros / seg (no metros / min).
Spectorsky

16

Necesitas usar lo último / más nuevo

GoogleApiClient Api

Básicamente lo que necesitas hacer es:

private GoogleApiClient mGoogleApiClient;
mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

Entonces

@Override
    public void onConnected(Bundle connectionHint) {
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);
        if (mLastLocation != null) {
            mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
            mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));
        }
    }

para la ubicación más precisa y confiable. Mira mi publicación aquí:

https://stackoverflow.com/a/33599228/2644905

No utilice LocationListener, que no es preciso y tiene una respuesta retrasada. Para ser honesto, esto es más fácil de implementar. Lea también la documentación: https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient


1
Esta es la mejor respuesta para la última API.
dramzy

1
Si. Esta es la forma correcta de hacerlo, en estos días. @nickfox proporcionó algunos buenos enlaces en su segunda respuesta a esta pregunta , de los creadores originales de la API de servicios de ubicación, que vale la pena consultar.
gMale

11
class MyLocation {
    Timer timer1;
    LocationManager lm;
    LocationResult locationResult;
    boolean gps_enabled = false;
    boolean network_enabled = false;

    public boolean getLocation(Context context, LocationResult result) {
        // I use LocationResult callback class to pass location value from
        // MyLocation to user code.
        locationResult = result;
        if (lm == null)
            lm = (LocationManager) context
                    .getSystemService(Context.LOCATION_SERVICE);

        // Exceptions will be thrown if the provider is not permitted.
        try {
            gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        }
        catch (Exception ex) {
        }
        try {
            network_enabled = lm
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        }
        catch (Exception ex) {
        }

        // Don't start listeners if no provider is enabled.
        if (!gps_enabled && !network_enabled)
            return false;

        if (gps_enabled)
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                    locationListenerGps);
        if (network_enabled)
            lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
                    locationListenerNetwork);
        timer1 = new Timer();
        timer1.schedule(new GetLastLocation(), 5000);
        return true;
    }

    LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerNetwork);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerGps);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    class GetLastLocation extends TimerTask {
        @Override
        public void run() {
            lm.removeUpdates(locationListenerGps);
            lm.removeUpdates(locationListenerNetwork);

            Location net_loc = null, gps_loc = null;
            if (gps_enabled)
                gps_loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (network_enabled)
                net_loc = lm
                        .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

            // If there are both values, use the latest one.
            if (gps_loc != null && net_loc != null) {
                if (gps_loc.getTime() > net_loc.getTime())
                    locationResult.gotLocation(gps_loc);
                else
                    locationResult.gotLocation(net_loc);
                return;
            }

            if (gps_loc != null) {
                locationResult.gotLocation(gps_loc);
                return;
            }
            if (net_loc != null) {
                locationResult.gotLocation(net_loc);
                return;
            }
            locationResult.gotLocation(null);
        }
    }

    public static abstract class LocationResult {
        public abstract void gotLocation(Location location);
    }
}

Espero que esto ayude...


1
No olvide agregar la siguiente línea a su archivo AndroidManifest:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Dr. Failov

7

Ahora que los servicios de ubicaciones de Google Play están aquí, recomiendo que los desarrolladores comiencen a usar el nuevo proveedor de ubicaciones fusionadas. Le resultará más fácil de usar y más preciso. Mire el video de Google I / O Más allá del punto azul: nuevas características en la ubicación de Android de los dos tipos que crearon la nueva API de servicios de ubicación de Google Play

He estado trabajando con las API de ubicación en varias plataformas móviles, y creo que lo que han hecho estos dos tipos es realmente revolucionario. Se ha librado de una gran cantidad de las complejidades del uso de los distintos proveedores. Stack Overflow está plagado de preguntas sobre qué proveedor usar, si usar la última ubicación conocida, cómo establecer otras propiedades en el LocationManager, etc. Esta nueva API que han construido elimina la mayoría de esas incertidumbres y hace que los servicios de ubicación sean un placer. utilizar.

He escrito una aplicación de Android que periódicamente obtiene la ubicación utilizando los servicios de ubicación de Google Play y la envía a un servidor web donde se almacena en una base de datos y se puede ver en Google Maps . He escrito tanto el software del cliente (para Android, iOS, Windows Phone y Java ME ) como el software del servidor (para ASP.NET y SQL Server o PHP y MySQL ). El software está escrito en el idioma nativo en cada plataforma y funciona correctamente en segundo plano en cada una. Por último, el software tiene la licencia MIT . Puede encontrar el cliente de Android aquí:

https://github.com/nickfox/GpsTracker/tree/master/phoneClients/android


7

Más simple que puedas encontrar

   package com.javapapers.android.geolocationfinder;

    import android.os.Bundle;
    import android.app.Activity;
    import android.content.Context;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.widget.TextView;

    import android.util.Log;

    public class MainActivity extends Activity implements LocationListener{
    protected LocationManager locationManager;
    protected LocationListener locationListener;
    protected Context context;
    TextView txtLat;
    String lat;
    String provider;
    protected String latitude,longitude; 
    protected boolean gps_enabled,network_enabled;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    txtLat = (TextView) findViewById(R.id.textview1);

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
    }
    @Override
    public void onLocationChanged(Location location) {
    txtLat = (TextView) findViewById(R.id.textview1);
    txtLat.setText("Latitude:" + location.getLatitude() + ", Longitude:" + location.getLongitude());
    }

    @Override
    public void onProviderDisabled(String provider) {
    Log.d("Latitude","disable");
    }

    @Override
    public void onProviderEnabled(String provider) {
    Log.d("Latitude","enable");
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    Log.d("Latitude","status");
    }
    }

6

LocationManager es una clase que proporciona métodos integrados para obtener la última ubicación conocida

PASO 1: Cree un objeto LocationManager como se muestra a continuación

LocationManager locationManager = (LocationManager) context.getSystemService (Context.LOCATION_SERVICE);

PASO 2: Agregar criterios

*Criteria is use for setting accuracy*

Criteria criteria = new Criteria();
int currentapiVersion = android.os.Build.VERSION.SDK_INT;

if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {

    criteria.setSpeedAccuracy(Criteria.ACCURACY_HIGH);
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setAltitudeRequired(true);
    criteria.setBearingRequired(true);
    criteria.setSpeedRequired(true);

}

PASO 3: OBTENGA un proveedor disponible

Hay dos tipos de proveedores de GPS y red.

 String provider = locationManager.getBestProvider(criteria, true);

PASO 4: Obtener la última ubicación del saber

Location location = locationManager.getLastKnownLocation(provider);

PASO 5: Obtenga latitud y longitud

Si el objeto es nulo ubicación luego tratar Dont al llamado método de abajo s

getLatitude and getLongitude is methods which returns double values


6

Obtener actualizaciones de ubicación requiere un montón de código bolierplate en Android, debe cuidar

  • Verificación de disponibilidad de los servicios de Google Play,
  • Actualice Google Play Service si es antiguo o no está disponible
  • Creación de cuadros de diálogo de GoogleApiClient y sus devoluciones de llamada conectadas, desconectadas, etc.
  • Detener y liberar recursos para actualizaciones de ubicación
  • Manejo de escenarios de permisos de ubicación
  • Comprobar que los servicios de ubicación están activados o desactivados
  • Obtener la última ubicación conocida tampoco es tan fácil
  • Vuelva a la última ubicación conocida si no obtiene la ubicación después de cierta duración

Para facilitar todos estos pasos, he creado Android-EasyLocation (pequeña biblioteca de Android) que se encargará de todo esto y puede centrarse en la lógica empresarial.

Todo lo que necesita es extender EasyLocationActivity y esto

requestSingleLocationFix(easyLocationRequest);

o

requestLocationUpdates(easyLocationRequest);

Consulte la aplicación de muestra y los pasos necesarios aquí en https://github.com/akhgupta/Android-EasyLocation


5

Hice un proyecto desde el cual podemos obtener la ubicación precisa utilizando los servicios de Google Play, GPS y proveedores de red. Este proyecto se puede encontrar aquí .

La estrategia para encontrar la mejor ubicación es obtener primero la ubicación de los servicios de Google Play si se encuentra la ubicación, luego verifique si el clima es mejor o no, si la ubicación se encuentra nula, reinicie los servicios de Google Play e intente obtener la ubicación desde la API de ubicación de Android. Registre la ubicación en los oyentes de cambios y, cuando se encuentre la mejor ubicación, la devolución de llamada la devuelve a la actividad principal.

Es muy simple de usar e implementar en código solo dos clases que necesitamos incrustar , es decir , LocationManagerInterfacey está implementando la interfaz y usando SmartLocationManager para obtener la ubicación.SmartLocationManagerLocationActivity

/**
 * Created by Syed Raza Mehdi Naqvi on 8/10/2016.
 */
public interface LocationManagerInterface {
    String TAG = LocationManagerInterface.class.getSimpleName();

    void locationFetched(Location mLocation, Location oldLocation, String time, String locationProvider);

}

aquí está la clase de administrador de ubicación

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import java.text.DateFormat;
import java.util.Date;

/**
 * Created by Syed Raza Mehdi Naqvi on 8/9/2016.
 */
public class SmartLocationManager implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private static final String TAG = SmartLocationManager.class.getSimpleName();

    private static final int TWO_MINUTES = 1000 * 60 * 2;
    private static final int PERMISSION_REQUEST_CODE = 1000;
    private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

    // default value is false but user can change it
    private String mLastLocationUpdateTime;                                                         // fetched location time
    private String locationProvider;                                                                // source of fetched location

    private Location mLastLocationFetched;                                                          // location fetched
    private Location mLocationFetched;                                                              // location fetched
    private Location networkLocation;
    private Location gpsLocation;

    private int mLocationPiority;
    private long mLocationFetchInterval;
    private long mFastestLocationFetchInterval;

    private Context mContext;                                                                       // application context
    private Activity mActivity;                                                                     // activity context
    private LocationRequest mLocationRequest;
    private GoogleApiClient mGoogleApiClient;
    private LocationManagerInterface mLocationManagerInterface;

    private android.location.LocationManager locationManager;
    private android.location.LocationListener locationListener;

    boolean isGPSEnabled;
    boolean isNetworkEnabled;

    private int mProviderType;
    public static final int NETWORK_PROVIDER = 1;
    public static final int ALL_PROVIDERS = 0;
    public static final int GPS_PROVIDER = 2;

//    private final double STANDARD_LOCATION_ACCURACY = 100.0;
//    private final double STANDARD_LOCATION_SEED_LIMIT = 6.95;

    public static final int LOCATION_PROVIDER_ALL_RESTICTION = 1;
    public static final int LOCATION_PROVIDER_RESTRICTION_NONE = 0;
    public static final int LOCATION_PROVIDER_GPS_ONLY_RESTICTION = 2;
    public static final int LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION = 3;
    private int mForceNetworkProviders = 0;

    public SmartLocationManager(Context context, Activity activity, LocationManagerInterface locationInterface, int providerType, int locationPiority, long locationFetchInterval, long fastestLocationFetchInterval, int forceNetworkProviders) {
        mContext = context;
        mActivity = activity;
        mProviderType = providerType;

        mLocationPiority = locationPiority;
        mForceNetworkProviders = forceNetworkProviders;
        mLocationFetchInterval = locationFetchInterval;
        mFastestLocationFetchInterval = fastestLocationFetchInterval;

        mLocationManagerInterface = locationInterface;

        initSmartLocationManager();
    }


    public void initSmartLocationManager() {

        // 1) ask for permission for Android 6 above to avoid crash
        // 2) check if gps is available
        // 3) get location using awesome strategy

        askLocationPermission();                            // for android version 6 above
        checkNetworkProviderEnable(mForceNetworkProviders);                       //

        if (isGooglePlayServicesAvailable())                // if googleplay services available
            initLocationObjts();                            // init obj for google play service and start fetching location
        else
            getLocationUsingAndroidAPI();                   // otherwise get location using Android API
    }

    private void initLocationObjts() {
        // Create the LocationRequest object
        mLocationRequest = LocationRequest.create()
                .setPriority(mLocationPiority)
                .setInterval(mLocationFetchInterval)                    // 10 seconds, in milliseconds
                .setFastestInterval(mFastestLocationFetchInterval);     // 1 second, in milliseconds

        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

        startLocationFetching();                                        // connect google play services to fetch location
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        startLocationUpdates();
        if (location == null) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            getLocationUsingAndroidAPI();
        } else {
            setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location == null) {
            getLastKnownLocation();
        } else {
            setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG, "Connection suspended");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {
            try {
                connectionResult.startResolutionForResult(mActivity, CONNECTION_FAILURE_RESOLUTION_REQUEST); // Start an Activity that tries to resolve the error
                getLocationUsingAndroidAPI();                                                                // try to get location using Android API locationManager
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
        }
    }

    private void setNewLocation(Location location, Location oldLocation) {
        if (location != null) {
            mLastLocationFetched = oldLocation;
            mLocationFetched = location;
            mLastLocationUpdateTime = DateFormat.getTimeInstance().format(new Date());
            locationProvider = location.getProvider();
            mLocationManagerInterface.locationFetched(location, mLastLocationFetched, mLastLocationUpdateTime, location.getProvider());
        }
    }

    private void getLocationUsingAndroidAPI() {
        // Acquire a reference to the system Location Manager
        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

        setLocationListner();
        captureLocation();
    }

    public void captureLocation() {
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        try {
            if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            } else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
            } else {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
    }

    private void setLocationListner() {
        // Define a listener that responds to location updates
        locationListener = new android.location.LocationListener() {
            public void onLocationChanged(Location location) {
                // Called when a new location is found by the network location provider.
                if (location == null) {
                    getLastKnownLocation();
                } else {
                    setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    if (isLocationAccurate(location) && location.getAccuracy() < STANDARD_LOCATION_ACCURACY && location.getSpeed() < STANDARD_LOCATION_SEED_LIMIT) {// no use of this if
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    } else {
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    }
                }
            }

            public void onStatusChanged(String provider, int status, Bundle extras) {
            }

            public void onProviderEnabled(String provider) {
            }

            public void onProviderDisabled(String provider) {
            }
        };
    }

    public Location getAccurateLocation() {
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        try {
            gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            Location newLocalGPS, newLocalNetwork;
            if (gpsLocation != null || networkLocation != null) {
                newLocalGPS = getBetterLocation(mLocationFetched, gpsLocation);
                newLocalNetwork = getBetterLocation(mLocationFetched, networkLocation);
                setNewLocation(getBetterLocation(newLocalGPS, newLocalNetwork), mLocationFetched);
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.getMessage());
        }
        return mLocationFetched;
    }

    protected void startLocationUpdates() {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

    public void startLocationFetching() {
        mGoogleApiClient.connect();
        if (mGoogleApiClient.isConnected()) {
            startLocationUpdates();
        }
    }

    public void pauseLocationFetching() {
        if (mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            mGoogleApiClient.disconnect();
        }

    }

    public void abortLocationFetching() {
        mGoogleApiClient.disconnect();

        // Remove the listener you previously added
        if (locationManager != null && locationListener != null) {
            if (Build.VERSION.SDK_INT >= 23 &&
                    ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            try {
                locationManager.removeUpdates(locationListener);
                locationManager = null;
            } catch (Exception ex) {
                Log.e(TAG, ex.getMessage());

            }
        }
    }

    public void resetLocation() {
        mLocationFetched = null;
        mLastLocationFetched = null;
        networkLocation = null;
        gpsLocation = null;
    }

    //  Android M Permission check
    public void askLocationPermission() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


            if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    ) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION)
                        || ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_FINE_LOCATION)) {

                    final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
                    builder.setMessage("Please allow all permissions in App Settings for additional functionality.")
                            .setCancelable(false)
                            .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
                                public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                                    Toast.makeText(mContext, "Welcome", Toast.LENGTH_SHORT).show();
                                }
                            })
                            .setNegativeButton("Deny", new DialogInterface.OnClickListener() {
                                public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                                    mActivity.finish();
                                }
                            });
                    final AlertDialog alert = builder.create();
                    alert.show();

                } else
                    ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION
                            , Manifest.permission.ACCESS_FINE_LOCATION
                    }, PERMISSION_REQUEST_CODE);

            }
        }
    }

    public void checkNetworkProviderEnable(int enforceActive) {
        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!isGPSEnabled && !isNetworkEnabled) {
            buildAlertMessageTurnOnLocationProviders("Your location providers seems to be disabled, please enable it", "OK", "Cancel");
        } else if (!isGPSEnabled && mForceNetworkProviders == LOCATION_PROVIDER_GPS_ONLY_RESTICTION) {
            buildAlertMessageTurnOnLocationProviders("Your GPS seems to be disabled, please enable it", "OK", "Cancel");
        } else if (!isNetworkEnabled && mForceNetworkProviders == LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION) {
            buildAlertMessageTurnOnLocationProviders("Your Network location provider seems to be disabled, please enable it", "OK", "Cancel");
        }
        // getting network status

        if (!isGPSEnabled && !isNetworkEnabled) {
            Toast.makeText(mContext, "Location can't be fetched!", Toast.LENGTH_SHORT).show(); // show alert
            mActivity.finish();
        }
    }

    private void buildAlertMessageTurnOnLocationProviders(String message, String positiveButtonText, String negativeButtonText) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
        builder.setMessage(message)
                .setCancelable(false)
                .setPositiveButton(positiveButtonText, new DialogInterface.OnClickListener() {
                    public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        Intent mIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        mContext.startActivity(mIntent);
                    }
                })
                .setNegativeButton(negativeButtonText, new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        mActivity.finish();
                    }
                });
        final AlertDialog alert = builder.create();
        alert.show();
    }


    public Location getLastKnownLocation() {
        locationProvider = LocationManager.NETWORK_PROVIDER;
        Location lastKnownLocation = null;
        // Or use LocationManager.GPS_PROVIDER
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return lastKnownLocation;
        }
        try {
            lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
            return lastKnownLocation;
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
        return lastKnownLocation;
    }

    public boolean isGooglePlayServicesAvailable() {
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);

        if (status == ConnectionResult.SUCCESS) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Determines whether one Location reading is better than the current Location fix
     *
     * @param location            The new Location that you want to evaluate
     * @param currentBestLocation The current Location fix, to which you want to compare the new one
     */
    protected Location getBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return location;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        boolean isNewer = timeDelta > 0;

        // If it's been more than two minutes since the current location, use the new location
        // because the user has likely moved
        if (isSignificantlyNewer) {
            return location;
            // If the new location is more than two minutes older, it must be worse
        } else if (isSignificantlyOlder) {
            return currentBestLocation;
        }

        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) {
            return location;
        } else if (isNewer && !isLessAccurate) {
            return location;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return location;
        }
        return currentBestLocation;
    }

    /**
     * Checks whether two providers are the same
     */

    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }

    public boolean isLocationAccurate(Location location) {
        if (location.hasAccuracy()) {
            return true;
        } else {
            return false;
        }
    }

    public Location getStaleLocation() {
        if (mLastLocationFetched != null) {
            return mLastLocationFetched;
        }
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
            return locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        } else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
            return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        } else {
            return getBetterLocation(locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER), locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
        }
    }
}

podemos usarlo con actividad o un fragmento, aquí lo estoy usando con actividad

import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

import com.example.raza.locationaware.location.LocationManagerInterface;
import com.example.raza.locationaware.location.SmartLocationManager;
import com.google.android.gms.location.LocationRequest;

public class LocationActivity extends AppCompatActivity implements LocationManagerInterface {

    public static final String TAG = LocationActivity.class.getSimpleName();

    SmartLocationManager mLocationManager;
    TextView mLocalTV, mLocationProviderTV, mlocationTimeTV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
        mLocationManager = new SmartLocationManager(getApplicationContext(), this, this, SmartLocationManager.ALL_PROVIDERS, LocationRequest.PRIORITY_HIGH_ACCURACY, 10 * 1000, 1 * 1000, SmartLocationManager.LOCATION_PROVIDER_RESTRICTION_NONE); // init location manager
        mLocalTV = (TextView) findViewById(R.id.locationDisplayTV);
        mLocationProviderTV = (TextView) findViewById(R.id.locationProviderTV);
        mlocationTimeTV = (TextView) findViewById(R.id.locationTimeFetchedTV);
    }

    protected void onStart() {
        super.onStart();
        mLocationManager.startLocationFetching();
    }

    protected void onStop() {
        super.onStop();
        mLocationManager.abortLocationFetching();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mLocationManager.pauseLocationFetching();
    }

    @Override
    public void locationFetched(Location mLocal, Location oldLocation, String time, String locationProvider) {
        Toast.makeText(getApplication(), "Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude(), Toast.LENGTH_LONG).show();
        mLocalTV.setText("Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude());
        mLocationProviderTV.setText(locationProvider);
        mlocationTimeTV.setText(time);
    }
}

Espero que ayude, si puede sugerir alguna mejora, publíquela en git . Gracias.


5

GoogleSamples tiene un ejemplo detallado con el último FusedLocationProviderApi. Lamentablemente, las respuestas más votadas están desactualizadas.

Siga los ejemplos a continuación para implementar Servicios de ubicación utilizando FusedLocationProviderApi

https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates

https://github.com/googlesamples/android-play-location/blob/master/LocationUpdates/app/src/main/java/com/google/android/gms/location/sample/locationupdates/MainActivity.java


3

Si está creando nuevos proyectos de ubicación para Android, debe usar el nuevo Google Play servicios de ubicación de . Es mucho más preciso y mucho más sencillo de usar.

He estado trabajando en un proyecto de rastreador GPS de código abierto , GpsTracker, durante varios años. Recientemente lo actualicé para manejar actualizaciones periódicas de teléfonos celulares Android, iOS, Windows Phone y Java ME . Es completamente funcional y hace lo que necesita y tiene la licencia MIT .

El proyecto de Android dentro de GpsTracker utiliza los nuevos servicios de Google Play y también hay dos pilas de servidores ( ASP.NET y PHP ) para permitirle rastrear esos teléfonos.


3
El problema es que no todos los dispositivos tienen servicios de Google Play, incluida cualquier ROM personalizada que no lo piratee. Si lo va a usar, tenga preparado un respaldo para LocationManager.
Gabe Sechan

3

Solo para verificar la ubicación puede usar el siguiente código. Puede ponerlo en su onStart () de la actividad principal y mostrar el diálogo de alerta si el retorno es falso.

private boolean isLocationAccurate()
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
        {
            String provider = Settings.Secure
                    .getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            if (provider != null && !provider.contains("gps"))
            {
                return false;
            }
        }
        else
        {
            try
            {
                int status = Settings.Secure
                        .getInt(this.getContentResolver(), Settings.Secure.LOCATION_MODE);
                if (status != Settings.Secure.LOCATION_MODE_HIGH_ACCURACY)
                {
                    return false;
                }
            }
            catch (Settings.SettingNotFoundException e)
            {
                Log.e(TAG, e.getMessage());
            }
        }

        return true;
    }

3

Tengo una ubicación muy precisa usando FusedLocationProviderClient
(se requieren servicios de Google Play )

Permisos requeridos

android.permission.ACCESS_FINE_LOCATION

android.permission.ACCESS_COARSE_LOCATION

Dependencia

'com.google.android.gms: play-services-location: 15.0.0'

Código Kotlin

val client = FusedLocationProviderClient(this)
val location = client.lastLocation
location.addOnCompleteListener {
    // this is a lambda expression and we get an 'it' iterator to access the 'result'
    // it.result.latitude gives the latitude
    // it.result.longitude gives the longitude 
    val geocoder = Geocoder(applicationContext, Locale.getDefault())
    val address = geocoder.getFromLocation(it.result.latitude, it.result.longitude, 1)
    if (address != null && address.size > 0) {
        // Get the current city
        city = address[0].locality
    }
}
location.addOnFailureListener {
    // Some error in getting the location, let's log it
    Log.d("xtraces", it.message)
}

3

La mejor manera de buscar la ubicación está debajo

// put dependancy
 implementation 'com.google.android.gms:play-services-location:11.0.4'

// PUT permissions in Menifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 


// create a Java file as below

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);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        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;
     }
  }

}
// FILE FINISHED


// FETCH LOCATION FROM ACTIVITY AS BELOW
public void getLocation(Context context) {
    MyApplication.log(LOG_TAG, "getLocation() ");

    SingleShotLocationProvider.requestSingleUpdate(context,
            new SingleShotLocationProvider.LocationCallback() {
                @Override
                public void onNewLocationAvailable(SingleShotLocationProvider.GPSCoordinates loc) {
                    location = loc;
                    MyApplication.log(LOG_TAG, "getLocation() LAT: " + location.latitude + ", LON: " + location.longitude);               
                }
            });
}

2

He publicado una pequeña biblioteca que puede facilitar la obtención de datos de ubicación en Android, incluso se encarga de los permisos de tiempo de ejecución de Android M.

Puede verificarlo aquí: https://github.com/julioromano/RxLocation y usarlo o su código fuente como ejemplos para su implementación.


Es una buena solución, pero no la mejor, no funciona la mayor parte del tiempo. No obtengo resultados instantáneamente después de hacer clic en el botón.
Asif Ali

@AsifAli Si encuentra un error, abra un problema o envíe un RP.
Marco Romano

Esta biblioteca porque a esta biblioteca le falta una clase AbstractSafeParcelable
Vikash Parajuli

2

Búsqueda simple de código de escritura en el método de ubicación

public void onLocationChanged(Location location) {
    if (mCurrLocationMarker != null) {
        mCurrLocationMarker.remove();
    }


    //Place current location marker
    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
    MarkerOptions markerOptions = new MarkerOptions();
    markerOptions.position(latLng);
    markerOptions.title("Current Position");
    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
    mCurrLocationMarker = mMap.addMarker(markerOptions);

    //move map camera
    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mMap.animateCamera(CameraUpdateFactory.zoomTo(18));

    PolylineOptions pOptions = new PolylineOptions()
            .width(5)
            .color(Color.GREEN)
            .geodesic(true);
    for (int z = 0; z < routePoints.size(); z++) {
        LatLng point = routePoints.get(z);
        pOptions.add(point);
    }
    line = mMap.addPolyline(pOptions);
    routePoints.add(latLng);
}

2

Recomendaré usar Smart Location Library
Muy simple de usar y envuelve muy bien la lógica de ubicación.

Para iniciar el servicio de ubicación:

SmartLocation.with(context).location()
    .start(new OnLocationUpdatedListener() { ... });

Si solo desea obtener una ubicación única (no periódica), puede usar el modificador oneFix. Ejemplo:

SmartLocation.with(context).location()
    .oneFix()
    .start(new OnLocationUpdatedListener() { ... });

0

Manera simple y fácil,

Obtenga ubicación usando https://github.com/sachinvarma/EasyLocation .

Paso 1: solo llama

new EasyLocationInit(MainActivity.this, timeInterval, fastestTimeInterval, runAsBackgroundService);

timeInterval -> setInterval (long) (inMilliSeconds) significa: establecer el intervalo en el que desea obtener ubicaciones.

rapidTimeInterval -> setFastestInterval (long) (inMilliSeconds) significa que si una ubicación está disponible antes, puede obtenerla. (es decir, otra aplicación está utilizando los servicios de ubicación).

runAsBackgroundService = True -> (El servicio se ejecutará en segundo plano y se actualiza con frecuencia (de acuerdo con timeInterval y rapidTimeInterval)) runAsBackgroundService = False -> (El servicio se destruirá después de una actualización de ubicación exitosa)

Paso 2: Prepare a los suscriptores de EventBus : declare y anote su método de suscripción, opcionalmente especifique un modo de subproceso:

p.ej:

     @Override
     public void onStart() {
         super.onStart();
         EventBus.getDefault().register(this);
     }

     @Override
     public void onStop() {
         super.onStop();
         EventBus.getDefault().unregister(this);
     }

  @SuppressLint("SetTextI18n")
  @Subscribe
  public void getEvent(final Event event) {

    if (event instanceof LocationEvent) {
      if (((LocationEvent) event).location != null) {
        ((TextView) findViewById(R.id.tvLocation)).setText("The Latitude is "
          + ((LocationEvent) event).location.getLatitude()
          + " and the Longitude is "
          + ((LocationEvent) event).location.getLongitude());
      }
    }
  }

Eso es todo.

Espero que ayude a alguien en el futuro.


0

Abril 2020

Pasos completos para obtener la ubicación actual y evitar la nulabilidad de la última ubicación conocida.

Según la documentación oficial , la última ubicación conocida podría ser nula en caso de:

  • La ubicación está desactivada en la configuración del dispositivo. A medida que borra el caché.
  • El dispositivo nunca registró su ubicación. (Nuevo dispositivo)
  • Los servicios de Google Play en el dispositivo se han reiniciado.

En este caso, debe solicitar Actualizaciones de ubicación y recibir la nueva ubicación en LocationCallback .

Con los siguientes pasos, su última ubicación conocida nunca será nula.


Requisito previo: biblioteca EasyPermission


Paso 1: en el archivo de manifiesto, agregue este permiso

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Paso 2:

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    //Create location callback when it's ready.
    createLocationCallback()

    //createing location request, how mant request would be requested.
    createLocationRequest()

    //Build check request location setting request
    buildLocationSettingsRequest()

    //FusedLocationApiClient which includes location 
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    //Location setting client
    mSettingsClient = LocationServices.getSettingsClient(this)

    //Check if you have ACCESS_FINE_LOCATION permission
    if (!EasyPermissions.hasPermissions(
            this@MainActivity,
            Manifest.permission.ACCESS_FINE_LOCATION)) {
        requestPermissionsRequired()
    }
    else{
        //If you have the permission we should check location is opened or not
        checkLocationIsTurnedOn()
    }

}

Paso 3: Cree las funciones requeridas para ser llamadas en onCreate ()

private fun requestPermissionsRequired() {
    EasyPermissions.requestPermissions(
        this,
        getString(R.string.location_is_required_msg),
        LOCATION_REQUEST,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
}

private fun createLocationCallback() {
    //Here the location will be updated, when we could access the location we got result on this callback.
    mLocationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            super.onLocationResult(locationResult)
            mCurrentLocation = locationResult.lastLocation
        }
    }
}

private fun buildLocationSettingsRequest() {
    val builder = LocationSettingsRequest.Builder()
    builder.addLocationRequest(mLocationRequest!!)
    mLocationSettingsRequest = builder.build()
    builder.setAlwaysShow(true)
}

private fun createLocationRequest() {
    mLocationRequest = LocationRequest.create()
    mLocationRequest!!.interval = 0
    mLocationRequest!!.fastestInterval = 0
    mLocationRequest!!.numUpdates = 1
    mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}

public fun checkLocationIsTurnedOn() { // Begin by checking if the device has the necessary location settings.
    mSettingsClient!!.checkLocationSettings(mLocationSettingsRequest)
        .addOnSuccessListener(this) {
            Log.i(TAG, "All location settings are satisfied.")
            startLocationUpdates()
        }
        .addOnFailureListener(this) { e ->
            val statusCode = (e as ApiException).statusCode
            when (statusCode) {
                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                    try {
                        val rae = e as ResolvableApiException
                        rae.startResolutionForResult(this@MainActivity, LOCATION_IS_OPENED_CODE)
                    } catch (sie: IntentSender.SendIntentException) {
                    }
                }
                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                    mRequestingLocationUpdates = false
                }
            }
        }
}

private fun startLocationUpdates() {
    mFusedLocationClient!!.requestLocationUpdates(
        mLocationRequest,
        mLocationCallback, null
    )
}

Paso 4:

Maneje las devoluciones de llamada en onActivityResult () después de asegurarse de que la ubicación esté abierta o que el usuario acepte abrirla.

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        LOCATION_IS_OPENED_CODE -> {
            if (resultCode == AppCompatActivity.RESULT_OK) {
                Log.d(TAG, "Location result is OK")
            } else {
                activity?.finish()
            }
        }
}

Paso 5: Obtenga la última ubicación conocida de FusedClientApi

override fun onMapReady(map: GoogleMap) {
    mMap = map
    mFusedLocationClient.lastLocation.addOnSuccessListener {
        if(it!=null){
            locateUserInMap(it)
        }
    }

}
   private fun locateUserInMap(location: Location) {
    showLocationSafetyInformation()
    if(mMap!=null){
        val currentLocation = LatLng(location.latitude,location.longitude )
        addMarker(currentLocation)
    }
}


private fun addMarker(currentLocation: LatLng) {
    val cameraUpdate = CameraUpdateFactory.newLatLng(currentLocation)
    mMap?.clear()
    mMap?.addMarker(
        MarkerOptions().position(currentLocation)
            .title("Current Location")
    )
    mMap?.moveCamera(cameraUpdate)
    mMap?.animateCamera(cameraUpdate)
    mMap?.setMinZoomPreference(14.0f);
}

Espero que esto ayude.

Happy Coding 🤓

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.