ubicacion - obtener ubicación actual android studio
obtener la ubicación actual rápidamente y una vez en Android (4)
Tengo una aplicación de Android que necesita la ubicación actual del dispositivo (latitud y longitud). He intentado algunos tutoriales en la red y especialmente algunas soluciones del desbordamiento de la pila, pero no funcionan bien para mí. Mi requisito es tan simple: primero necesito que sea rápido y necesito la ubicación una vez cuando empiece el fragmento. En segundo lugar, necesito que sea lo más preciso posible, me refiero a que primero debería usar GPS si el GPS no está disponible y luego usar el proveedor de red.
Por ejemplo, he intentado esta solución, pero devuelve null después de 30 segundos, pero sé que hay algunas cosas que están bien porque el mapa de Google y otras aplicaciones funcionan bien.
Algo que casi todas las respuestas sugieren es usar getLastKnownLocation (), pero supongo que no es el actual y no lo quiero si es así.
¿alguien puede sugerirme algún tipo de manera simple y rápida para obtener la ubicación UNA VEZ ?!
Gracias por adelantado
Lo que desea hacer se logra utilizando LocationManager#requestSingleUpdate
. Este método adjunta un oyente en un looper determinado (si lo desea o lo tiene) y notifica la ubicación lo antes posible que se reciba, solo una vez. El método que sugiera se usa solo como una posición inexacta antes de que se le otorgue el real.
En cualquier caso, será más rápido que milisegundos (a menos que tenga la suerte de comenzar a escuchar cuando llega una ubicación en el dispositivo). Piensa en el GPS como un elemento que habilitas cuando esperas ubicaciones y deshabilita cuando quitas esta escucha. Este comportamiento se realiza para evitar el drenaje de la batería del usuario.
Así que para resumir:
- El tiempo entre que comienza a escuchar y recibe la posición depende del GPS del dispositivo (fabricación, ubicación del usuario, cobertura de satélite ...)
- Hay un método en el SDK de Android para escuchar una única actualización.
- Al proporcionar un objeto de criterios, puede administrar qué criterios son aceptables para que usted reciba una ubicación. Criterios más fuertes significa más tiempo para obtener una respuesta precisa.
// 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;
}
Aquí, puedes usar esto ...
Ejemplo de uso:
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());
}
});
}
Es posible que desee verificar que lat / long sean valores reales y no 0 o algo así. Si mal no recuerdo, esto no debería arrojar un NPE, pero es posible que desee verificarlo.
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;
}
}
}
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;
}
}