Respostas:
Eu criei um pequeno aplicativo com descrição passo a passo para obter as coordenadas GPS da localização atual.
O código-fonte completo do exemplo está nas coordenadas Obter localização atual, Nome da cidade - no Android .
Veja como funciona:
Tudo o que precisamos fazer é adicionar essa permissão no arquivo de manifesto:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
E crie uma instância do LocationManager assim:
LocationManager locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
Verifique se o GPS está ativado ou não.
E, em seguida, implemente LocationListener e obtenha coordenadas:
LocationListener locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
Aqui está o código de exemplo para fazer isso
/*---------- 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) {}
}
adresses
linha que começa com cityName =
falhará com uma exceção. Usar aparelho fixaria isso.
getLastKnownLocation()
é um local mais "obsoleto" - por que isso? A chamada getLastKnownLocation()
não recebe a última leitura GPS do GPS do telefone?
Aqui estão informações adicionais para outras respostas.
Como o Android tem
GPS_PROVIDER and NETWORK_PROVIDER
você pode se registrar nos dois e começar a buscar eventos a partir onLocationChanged(Location location)
de dois ao mesmo tempo. Por enquanto, tudo bem. Agora, a pergunta: precisamos de dois resultados ou devemos tirar o melhor. Como eu sei, os GPS_PROVIDER
resultados têm melhor precisão do que NETWORK_PROVIDER
.
Vamos definir o Location
campo:
private Location currentBestLocation = null;
Antes de começarmos a ouvir a alteração de local , implementaremos o seguinte método. Este método retorna o último local conhecido, entre o GPS e o da rede. Para este método, o mais recente é o melhor.
/**
* @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;
}
}
Sempre que recuperarmos um novo local, o compararemos com o resultado anterior.
...
static final int TWO_MINUTES = 1000 * 60 * 2;
...
Eu adiciono um novo 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);
}
....
private Location currentBestLocation = null;
e adicionar `makeUseOfNewLocation (localização);` para onLocationChanged (..) Método
Você pode encontrar a localização por GPS_PROVIDER or NETWORK_PROVIDER
.
Visão geral dos serviços de localização no Android.
Aqui está um exemplo que tenta encontrar a localização usando GPS. Se o seu GPS não estiver disponível, tente usar a rede para encontrar a localização.
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;
}
}
Activity -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" />
Já existem muitas respostas, mas quero mostrar a maneira mais recente de obter localização usando a API do Google, para que novos programadores possam usar o novo método:
Eu escrevi um tutorial detalhado sobre a localização atual no android no meu blog demonuts.com Você também pode encontrar o código fonte completo desenvolvido com o android studio.
Primeiro, coloque isso no arquivo gradle
compile 'com.google.android.gms:play-services:9.0.2'
depois implemente as interfaces necessárias
public class MainActivity extends BaseActivitiy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener
declarar instâncias
private GoogleApiClient mGoogleApiClient;
private Location mLocation;
private LocationManager locationManager;
private LocationRequest mLocationRequest;
coloque isso onCreate()
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Por fim, substitua os métodos necessários
@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) {
}
Não se esqueça de iniciar o GPS no seu dispositivo antes de executar o aplicativo.
mLocation
sempre dá nulo. Tentei o mesmo como mencionado
compile 'com.google.android.gms:play-services-location:11.0.4'
vez de adicionar todos os serviços do Google Play ao seu aplicativo.
Como não gostei do código nas outras respostas, aqui está minha solução simples. Esta solução deve ser usada em uma Atividade ou Serviço para rastrear o local. Ele garante que nunca retorne dados muito antigos, a menos que você solicite explicitamente dados antigos. Ele pode ser executado no modo de retorno de chamada para obter atualizações à medida que as recebemos, ou no modo de pesquisa para pesquisar as informações mais recentes.
Interface genérica LocationTracker. Permite ter vários tipos de rastreadores de localização e conectar facilmente o apropriado:
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 - essa classe rastreará a localização do GPS ou da REDE.
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) {
}
}
O é o FallbackLocationTracker, que rastreará pelo GPS e pela REDE e usará qualquer local mais preciso.
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;
}
}
}
Como os dois implementam a interface LocationTracker, você pode facilmente mudar de idéia sobre qual usar. Para executar a classe no modo de pesquisa, basta chamar start (). Para executá-lo no modo de atualização, chame start (Listener).
Também dê uma olhada no meu post no código
FallbackLocationTracker fallbackLocationTracker = new FallbackLocationTracker(mContext); fallbackLocationTracker.start(); if (fallbackLocationTracker.hasLocation()) { return fallbackLocationTracker.getLocation(); }
Obter localização 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);
}
location.getSpeed()
retorna a velocidade em metros / s (não metros / min).
Você precisa usar as mais recentes / mais recentes
GoogleApiClient Api
Basicamente, o que você precisa fazer é:
private GoogleApiClient mGoogleApiClient;
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Então
@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 a localização mais precisa e confiável. Veja meu post aqui:
https://stackoverflow.com/a/33599228/2644905
Não use LocationListener que não é preciso e que atrasou a resposta. Para ser honesto, isso é mais fácil de implementar. Leia também a documentação: https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient
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);
}
}
Eu espero que isso te ajude...
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Agora que os serviços de localização do Google Play estão aqui, recomendo que os desenvolvedores comecem a usar o novo provedor de localização com fusão. Você achará mais fácil de usar e mais preciso. Assista ao vídeo do Google I / O além do ponto azul: novos recursos no local do Android pelos dois caras que criaram a nova API de serviços de localização do Google Play.
Eu tenho trabalhado com APIs de localização em várias plataformas móveis, e acho que o que esses dois caras fizeram foi realmente revolucionário. Ele se livrou de uma enorme quantidade de complexidades de usar os vários provedores. O Stack Overflow está repleto de perguntas sobre qual provedor usar, se deve usar o último local conhecido, como definir outras propriedades no LocationManager, etc. Essa nova API que eles criaram remove a maioria dessas incertezas e torna os serviços de localização um prazer para usar.
Escrevi um aplicativo para Android que periodicamente obtém o local usando os serviços de localização do Google Play e envia o local para um servidor da Web onde está armazenado em um banco de dados e pode ser visualizado no Google Maps . Escrevi o software cliente (para Android, iOS, Windows Phone e Java ME ) e o software servidor (para ASP.NET e SQL Server ou PHP e MySQL ). O software é escrito no idioma nativo em cada plataforma e funciona corretamente em segundo plano em cada uma. Por fim, o software possui a licença MIT . Você pode encontrar o cliente Android aqui:
https://github.com/nickfox/GpsTracker/tree/master/phoneClients/android
Mais simples que você pode 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");
}
}
LocationManager é uma classe que fornece métodos internos para obter o último local conhecido
PASSO 1: Crie um objeto LocationManager como abaixo
LocationManager locationManager = (LocationManager) context.getSystemService (Context.LOCATION_SERVICE);
PASSO 2: Adicionar critérios
*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);
}
PASSO 3: GET Provider disponível
Existem dois tipos de provedor de GPS e rede
String provider = locationManager.getBestProvider(criteria, true);
PASSO 4: Conheça a Última Localização
Location location = locationManager.getLastKnownLocation(provider);
PASSO 5: obtenha latitude e longitude
Se o objeto de localização for nulo, não tente chamar o método s abaixo
getLatitude and getLongitude is methods which returns double values
Para obter atualizações de local, é necessário muito código de bolierplate no Android. Você precisa cuidar de
Para facilitar todas essas etapas, criei o Android-EasyLocation (pequena biblioteca Android) que cuidará de tudo isso e você poderá se concentrar na lógica de negócios.
Tudo que você precisa é estender o EasyLocationActivity e isso
requestSingleLocationFix(easyLocationRequest);
ou
requestLocationUpdates(easyLocationRequest);
Aplicativo de exemplo do Google Checkout e etapas necessárias aqui em https://github.com/akhgupta/Android-EasyLocation
Fiz um projeto a partir do qual podemos obter a localização exata usando os serviços do Google Play, fornecedores de GPS e de rede. Este projeto pode ser encontrado aqui .
A estratégia para encontrar a melhor localização é que primeiro obtenha a localização nos serviços Google Play, se a localização for encontrada e verifique se o tempo está melhor ou não, se a localização encontrada for nula, reinicie os serviços Google Play e tente buscar a localização na API de localização do Android. Registre o local nos ouvintes de mudança e, sempre que encontrar um local melhor, a chamada de retorno o retornará à atividade principal.
É muito simples de usar e implementar em código apenas duas classes que precisamos para isto é incorporar LocationManagerInterface
e SmartLocationManager
, LocationActivity
está implementando a interface e usando SmartLocationManager para buscar localização.
/**
* 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);
}
aqui está a classe do gerenciador de localização
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 usá-lo com atividade ou um fragmento, aqui estou usando-o com atividade
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 ajude, se você puder sugerir alguma melhoria, por favor publique no git . Obrigado.
GoogleSamples tem um exemplo detalhado usando o FusedLocationProviderApi mais recente. Infelizmente, as respostas mais votadas estão desatualizadas.
Siga os exemplos abaixo para implementar os Serviços de Localização usando o FusedLocationProviderApi
https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates
Se você estiver criando novos projetos de localização para Android, use o novo Google Play serviços de localização do . É muito mais preciso e muito mais simples de usar.
Estou trabalhando em um projeto de rastreador GPS de código aberto , o GpsTracker, há vários anos. Eu o atualizei recentemente para lidar com atualizações periódicas de telefones celulares Android, iOS, Windows Phone e Java ME . É totalmente funcional e faz o que você precisa e possui a Licença MIT .
O projeto Android no GpsTracker usa os novos serviços do Google Play e também existem duas pilhas de servidores ( ASP.NET e PHP ) para permitir o rastreamento desses telefones.
Para apenas verificar a localização, você pode usar o seguinte código. Você pode colocá-lo no seu onStart () da atividade principal e exibir a caixa de diálogo de alerta se o retorno for 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;
}
Tenho uma localização muito precisa usando o FusedLocationProviderClient
( são necessários serviços do Google Play )
Permissões necessárias
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION
Dependência
'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)
}
A melhor maneira de buscar o local está abaixo
// 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);
}
});
}
Publiquei uma pequena biblioteca que pode facilitar a obtenção de dados de localização no Android, além de cuidar das permissões de tempo de execução do Android M.
Você pode conferir aqui: https://github.com/julioromano/RxLocation e usá-lo ou seu código-fonte como exemplos para sua implementação.
Localização simples Escreva código no método On Location
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);
}
Vou recomendar o uso da Biblioteca de Localização Inteligente
Muito simples de usar e envolve bem a lógica de localização.
Para iniciar o serviço de localização:
SmartLocation.with(context).location()
.start(new OnLocationUpdatedListener() { ... });
Se você deseja apenas obter um único local (não periódico), basta usar o modificador oneFix. Exemplo:
SmartLocation.with(context).location()
.oneFix()
.start(new OnLocationUpdatedListener() { ... });
Maneira simples e fácil,
Obtenha a localização usando https://github.com/sachinvarma/EasyLocation .
Etapa 1: basta ligar
new EasyLocationInit(MainActivity.this, timeInterval, fastestTimeInterval, runAsBackgroundService);
timeInterval -> setInterval (long) (inMilliSeconds) significa - defina o intervalo em que você deseja obter os locais.
rapidTimeInterval -> setFastestInterval (long) (inMilliSeconds) significa - se um local estiver disponível mais cedo, você poderá obtê-lo. (ou seja, outro aplicativo está usando os serviços de localização).
runAsBackgroundService = True -> (O serviço será executado em segundo plano e será atualizado com freqüência (de acordo com o timeInterval e o quickTimeInterval)) runAsBackgroundService = False -> (o serviço será getDestroyed após uma atualização de local bem-sucedida)
Etapa 2: Prepare assinantes do EventBus: declare e anote seu método de inscrição, opcionalmente, especifique um modo de encadeamento:
por exemplo:
@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());
}
}
}
Isso é tudo.
Espero que ajude alguém no futuro.
Abril 2020
Etapas completas para obter a localização atual e evitar a nulidade da Última Localização Conhecida.
De acordo com a documentação oficial , Last Known Location poderia ser Null no caso de:
Nesse caso, você deve solicitarLocationUpdates e receber o novo local no LocationCallback .
Nas etapas a seguir, seu último local conhecido nunca é nulo.
Pré-requisito: biblioteca EasyPermission
Etapa 1: no arquivo de manifesto, adicione esta permissão
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Passo 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()
}
}
Etapa 3: Crie as funções necessárias para serem chamadas no 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
)
}
Passo 4:
Manipule retornos de chamada em onActivityResult () depois de garantir que o local seja aberto ou que o usuário aceite abri-lo.
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()
}
}
}
Etapa 5: obter o último local conhecido do 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 isso ajude.
Feliz codificação 🤓