Каков самый простой и надежный способ получить текущее местоположение пользователя на Android?

API LocationManager на Android кажется, что это немного больно использовать для приложения, которому требуется только случайное и грубое приближение местоположения пользователя.

Приложение, над которым я работаю, на самом деле не является приложением местоположения, но ему нужно получить местоположение пользователя, чтобы отобразить список ближайших предприятий. Не нужно беспокоиться о том, перемещается ли пользователь или что-то в этом роде.

Вот что я хотел бы сделать:

  1. Покажите пользователю список ближайших местоположений.
  2. Предварительно загрузите местоположение пользователя, чтобы к моменту, когда он мне понадобится в Activity X, он будет доступен.
  3. Я не особо забочусь о точности или частоте обновления. Достаточно хватать одно место, пока это не выход. Может быть, если я хочу быть фантазией, я обновляю местоположение каждые несколько минут или около того, но это не очень важный приоритет.
  4. Работайте на любом устройстве, если у него есть GPS или поставщик сетевого местоположения.

Похоже, это не должно быть так сложно, но мне кажется, что мне нужно развернуть два разных провайдера местоположения (GPS и NETWORK) и управлять каждым жизненным циклом. Не только это, но я должен дублировать один и тот же код в нескольких действиях, чтобы удовлетворить # 2. Я пытался использовать getBestProvider() в прошлом, чтобы сократить решение до простого использования одного провайдера местоположения, но это, по-видимому, дает вам лучший «теоретический» провайдер, а не поставщик, который действительно даст вам наилучшие результаты.

Есть ли более простой способ сделать это?

25 Solutions collect form web for “Каков самый простой и надежный способ получить текущее местоположение пользователя на Android?”

Вот что я делаю:

  1. Прежде всего, я проверяю, какие поставщики включены. Некоторые могут быть отключены на устройстве, некоторые могут быть отключены в манифесте приложения.
  2. Если какой-либо провайдер доступен, я запускаю приемников местоположения и таймер тайм-аута. Это 20 секунд в моем примере, может быть недостаточно для GPS, поэтому вы можете увеличить его.
  3. Если я получаю обновление из приемника местоположения, я использую предоставленное значение. Я останавливаю слушателей и таймер.
  4. Если я не получаю никаких обновлений и таймеров, я должен использовать последние известные значения.
  5. Я беру последние известные значения у доступных поставщиков и выбираю самые последние из них.

Вот как я использую свой class:

 LocationResult locationResult = new LocationResult(){ @Override public void gotLocation(Location location){ //Got the location! } }; MyLocation myLocation = new MyLocation(); myLocation.getLocation(this, locationResult); 

И вот class MyLocation:

 import java.util.Timer; import java.util.TimerTask; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; public 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 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(), 20000); 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); } } 

Кто-то может также захотеть изменить мою логику. Например, если вы получаете обновление от поставщика сети, не останавливайте слушателей, а продолжайте ждать. GPS дает более точные данные, поэтому стоит его ждать. Если таймер истекает, и у вас есть обновление от Сети, но не от GPS, вы можете использовать значение, предоставляемое из сети.

Еще один подход – использовать LocationClient http://developer.android.com/training/location/retrieve-current.html . Но для этого на устройстве пользователя необходимо установить apk Google Play Services.

После поиска лучшей реализации, как получить лучшее точное местоположение пользователя, мне удалось объединить все лучшие методы и предложить следующий class:

 /** * Retrieve accurate location from GPS or network services. * * * Class usage example: * * public void onCreate(Bundle savedInstanceState) { * ... * my_location = new MyLocation(); * my_location.init(main.this, locationResult); * } * * * public LocationResult locationResult = new LocationResult(){ * @Override * public void gotLocation(final Location location){ * // do something * location.getLongitude(); * location.getLatitude(); * } * }; */ class MyLocation{ /** * If GPS is enabled. * Use minimal connected satellites count. */ private static final int min_gps_sat_count = 5; /** * Iteration step time. */ private static final int iteration_timeout_step = 500; LocationResult locationResult; private Location bestLocation = null; private Handler handler = new Handler(); private LocationManager myLocationManager; public Context context; private boolean gps_enabled = false; private int counts = 0; private int sat_count = 0; private Runnable showTime = new Runnable() { public void run() { boolean stop = false; counts++; System.println("counts=" + counts); //if timeout (1 min) exceeded, stop tying if(counts > 120){ stop = true; } //update last best location bestLocation = getLocation(context); //if location is not ready or don`t exists, try again if(bestLocation == null && gps_enabled){ System.println("BestLocation not ready, continue to wait"); handler.postDelayed(this, iteration_timeout_step); }else{ //if best location is known, calculate if we need to continue to look for better location //if gps is enabled and min satellites count has not been connected or min check count is smaller then 4 (2 sec) if(stop == false && !needToStop()){ System.println("Connected " + sat_count + " sattelites. continue waiting.."); handler.postDelayed(this, iteration_timeout_step); }else{ System.println("#########################################"); System.println("BestLocation finded return result to main. sat_count=" + sat_count); System.println("#########################################"); // removing all updates and listeners myLocationManager.removeUpdates(gpsLocationListener); myLocationManager.removeUpdates(networkLocationListener); myLocationManager.removeGpsStatusListener(gpsStatusListener); sat_count = 0; // send best location to locationResult locationResult.gotLocation(bestLocation); } } } }; /** * Determine if continue to try to find best location */ private Boolean needToStop(){ if(!gps_enabled){ return true; } else if(counts < = 4){ return false; } if(sat_count < min_gps_sat_count){ //if 20-25 sec and 3 satellites found then stop if(counts >= 40 && sat_count >= 3){ return true; } return false; } } return true; } /** * Best location abstract result class */ public static abstract class LocationResult{ public abstract void gotLocation(Location location); } /** * Initialize starting values and starting best location listeners * * @param Context ctx * @param LocationResult result */ public void init(Context ctx, LocationResult result){ context = ctx; locationResult = result; myLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); gps_enabled = (Boolean) myLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); bestLocation = null; counts = 0; // turning on location updates myLocationManager.requestLocationUpdates("network", 0, 0, networkLocationListener); myLocationManager.requestLocationUpdates("gps", 0, 0, gpsLocationListener); myLocationManager.addGpsStatusListener(gpsStatusListener); // starting best location finder loop handler.postDelayed(showTime, iteration_timeout_step); } /** * GpsStatus listener. OnChainged counts connected satellites count. */ public final GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() { public void onGpsStatusChanged(int event) { if(event == GpsStatus.GPS_EVENT_SATELLITE_STATUS){ try { // Check number of satellites in list to determine fix state GpsStatus status = myLocationManager.getGpsStatus(null); Iterablesatellites = status.getSatellites(); sat_count = 0; IteratorsatI = satellites.iterator(); while(satI.hasNext()) { GpsSatellite satellite = satI.next(); System.println("Satellite: snr=" + satellite.getSnr() + ", elevation=" + satellite.getElevation()); sat_count++; } } catch (Exception e) { e.printStackTrace(); sat_count = min_gps_sat_count + 1; } System.println("#### sat_count = " + sat_count); } } }; /** * Gps location listener. */ public final LocationListener gpsLocationListener = new LocationListener(){ @Override public void onLocationChanged(Location location){ } public void onProviderDisabled(String provider){} public void onProviderEnabled(String provider){} public void onStatusChanged(String provider, int status, Bundle extras){} }; /** * Network location listener. */ public final LocationListener networkLocationListener = new LocationListener(){ @Override public void onLocationChanged(Location location){ } public void onProviderDisabled(String provider){} public void onProviderEnabled(String provider){} public void onStatusChanged(String provider, int status, Bundle extras){} }; /** * Returns best location using LocationManager.getBestProvider() * * @param context * @return Location|null */ public static Location getLocation(Context context){ System.println("getLocation()"); // fetch last known location and update it try { LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setAltitudeRequired(false); criteria.setBearingRequired(false); criteria.setCostAllowed(true); String strLocationProvider = lm.getBestProvider(criteria, true); System.println("strLocationProvider=" + strLocationProvider); Location location = lm.getLastKnownLocation(strLocationProvider); if(location != null){ return location; } return null; } catch (Exception e) { e.printStackTrace(); return null; } } } 

Этот class пытается подключиться к спутникам min_gps_sat_count если включен GPS. Else возвращает LocationManager.getBestProvider() . Проверьте код!

С решением Fedor я испытал многократное выполнение callback gotLocation . По-видимому, это связано с состоянием гонки в переопределенном методе LocationListener.onLocationChanged , когда метод gotLocation «достаточно длинный» . Я не уверен, но я думаю, что removeUpdates предотвращает появление очередных сообщений в очереди Looper, но не удаляет те, которые уже установлены в очередь, но еще не используются. Следовательно, состояние гонки.

Чтобы уменьшить вероятность этого неправильного поведения, вы можете вызвать removeUpdates перед запуском события onLocationChanged, но все же у нас есть условие гонки.

Лучшее решение, которое я нашел, это заменить requestLocationUpdates на requestLocationUpdates .

Это моя версия, основанная на решении Fedor, используя обработчик для отправки сообщения в stream петлителя:

 public class LocationResolver { private Timer timer; private LocationManager locationManager; private LocationResult locationResult; private boolean gpsEnabled = false; private boolean networkEnabled = false; private Handler locationTimeoutHandler; private final Callback locationTimeoutCallback = new Callback() { public boolean handleMessage(Message msg) { locationTimeoutFunc(); return true; } private void locationTimeoutFunc() { locationManager.removeUpdates(locationListenerGps); locationManager.removeUpdates(locationListenerNetwork); Location networkLocation = null, gpsLocation = null; if (gpsEnabled) gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (networkEnabled) networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); // if there are both values use the latest one if (gpsLocation != null && networkLocation != null) { if (gpsLocation.getTime() > networkLocation.getTime()) locationResult.gotLocation(gpsLocation); else locationResult.gotLocation(networkLocation); return; } if (gpsLocation != null) { locationResult.gotLocation(gpsLocation); return; } if (networkLocation != null) { locationResult.gotLocation(networkLocation); return; } locationResult.gotLocation(null); } }; private final LocationListener locationListenerGps = new LocationListener() { public void onLocationChanged(Location location) { timer.cancel(); locationResult.gotLocation(location); locationManager.removeUpdates(this); locationManager.removeUpdates(locationListenerNetwork); } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } }; private final LocationListener locationListenerNetwork = new LocationListener() { public void onLocationChanged(Location location) { timer.cancel(); locationResult.gotLocation(location); locationManager.removeUpdates(this); locationManager.removeUpdates(locationListenerGps); } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } }; public void prepare() { locationTimeoutHandler = new Handler(locationTimeoutCallback); } public synchronized boolean getLocation(Context context, LocationResult result, int maxMillisToWait) { locationResult = result; if (locationManager == null) locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); // exceptions will be thrown if provider is not permitted. try { gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); } catch (Exception ex) { } try { networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); } catch (Exception ex) { } // don't start listeners if no provider is enabled if (!gpsEnabled && !networkEnabled) return false; if (gpsEnabled) locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, locationListenerGps, Looper.myLooper()); //locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps); if (networkEnabled) locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, locationListenerNetwork, Looper.myLooper()); //locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork); timer = new Timer(); timer.schedule(new GetLastLocationTask(), maxMillisToWait); return true; } private class GetLastLocationTask extends TimerTask { @Override public void run() { locationTimeoutHandler.sendEmptyMessage(0); } } public static abstract class LocationResult { public abstract void gotLocation(Location location); } } 

Я использую этот class из настраиваемого streamа петлителя, например, следующего:

 public class LocationGetter { private final Context context; private Location location = null; private final Object gotLocationLock = new Object(); private final LocationResult locationResult = new LocationResult() { @Override public void gotLocation(Location location) { synchronized (gotLocationLock) { LocationGetter.this.location = location; gotLocationLock.notifyAll(); Looper.myLooper().quit(); } } }; public LocationGetter(Context context) { if (context == null) throw new IllegalArgumentException("context == null"); this.context = context; } public synchronized Coordinates getLocation(int maxWaitingTime, int updateTimeout) { try { final int updateTimeoutPar = updateTimeout; synchronized (gotLocationLock) { new Thread() { public void run() { Looper.prepare(); LocationResolver locationResolver = new LocationResolver(); locationResolver.prepare(); locationResolver.getLocation(context, locationResult, updateTimeoutPar); Looper.loop(); } }.start(); gotLocationLock.wait(maxWaitingTime); } } catch (InterruptedException e1) { e1.printStackTrace(); } if (location != null) coordinates = new Coordinates(location.getLatitude(), location.getLongitude()); else coordinates = Coordinates.UNDEFINED; return coordinates; } } 

где Координаты – это простой class с двумя свойствами: широта и долгота.

Я создал небольшое приложение с пошаговым описанием, чтобы получить текущие координаты GPS.

введите описание изображения здесь

Полный пример исходного кода в следующем URL:


Получить текущие координаты местоположения, название города – на Android


Посмотри, как это работает :

  • Все, что нам нужно сделать, это добавить это разрешение в файл манифеста

       
  • и создайте экземпляр LocationManager следующим образом

     LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
  • Проверка GPS включена или нет

  • затем реализовать LocationListener и Get Coordinates

     LocationListener locationListener = new MyLocationListener(); locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 5000, 10, locationListener); 
  • здесь приведен пример кода


 /*----------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
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) {} }

Вы всегда можете просто использовать LocationManager.getLastKnownLocation (), но, как он говорит, он может быть устаревшим.

И простой способ получить общее местоположение можно зарегистрировать для сети (обычно довольно быстро).

 LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 1000, 1000, this); 

и затем

 locationManager.removeUpdates(this); 

в onLocationChanged() слушателя.

Я написал подробный учебник, посвященный текущему местоположению здесь, на demonuts.com . Здесь вы можете найти более подробное описание, а также вы можете загрузить весь демо-исходный код для лучшего понимания.

Там уже много ответов, но я хочу показать последний способ получить местоположение с помощью API Google, поэтому новые программисты могут использовать новый метод:

Прежде всего, поставьте это в файле gradle

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

затем реализовать необходимые интерфейсы

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

объявлять экземпляры

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

поместите это в onCreate()

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

Наконец, переопределите необходимые методы

  @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; } 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) { } 

Не забудьте запустить GPS на своем устройстве перед запуском приложения.

Я не уверен, могут ли службы на основе местоположения получить местоположение от других инфраструктур, отличных от GPS, но, согласно этой статье, это кажется возможным:

Приложения могут использовать любой из нескольких типов методов позиционирования.

Использование сети мобильного телефона: текущий идентификатор ячейки можно использовать для идентификации базовой приемопередающей станции (BTS), с которой устройство взаимодействует, и местоположения этой BTS. Ясно, что точность этого метода зависит от размера ячейки и может быть довольно неточной. Кабель GSM может быть от 2 до 20 километров в диаметре. Другие методы, используемые вместе с идентификатором ячейки, могут достичь точности в пределах 150 метров.

Использование спутников: Глобальная система позиционирования (GPS), контролируемая Министерством обороны США, использует созвездие из 24 спутников, вращающихся вокруг Земли. GPS определяет положение устройства, вычисляя разницу в сигналах времени от разных спутников, чтобы добраться до приемника. Сигналы GPS кодируются, поэтому мобильное устройство должно быть оборудовано GPS-приемником. GPS является потенциально наиболее точным методом (от 4 до 40 метров, если GPS-приемник имеет четкое представление о небе), но он имеет некоторые недостатки: дополнительное оборудование может быть дорогостоящим, потребляет батарею во время использования и требует некоторого тепло- после холодного старта, чтобы получить первоначальное исправление на видимых спутниках. Он также страдает от «каньонных эффектов» в городах, где видимость спутников является прерывистой.

Использование малогабаритных маяков позиционирования: на относительно небольших участках, таких как одно здание, локальная сеть может предоставлять места вместе с другими службами. Например, соответствующие устройства могут использовать Bluetooth для ближнего позиционирования.

Используйте приведенный ниже код, он предоставит лучший ansible провайдер:

 String locCtx = Context.LOCATION_SERVICE; LocationManager locationMgr = (LocationManager) ctx.getSystemService(locCtx); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setAltitudeRequired(false); criteria.setBearingRequired(false); criteria.setCostAllowed(true); criteria.setPowerRequirement(Criteria.POWER_LOW); String provider = locationMgr.getBestProvider(criteria, true); System.out.println("Best Available provider::::"+provider); 

Рекомендуемый способ сделать это – использовать LocationClient :

Сначала определите значения интервала обновления местоположения. Отрегулируйте это для ваших нужд.

 private static final int MILLISECONDS_PER_SECOND = 1000; private static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS; private static final int FASTEST_INTERVAL_IN_SECONDS = 1; private static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS; 

Внесите свою Activity GooglePlayServicesClient.ConnectionCallbacks , GooglePlayServicesClient.OnConnectionFailedListener и LocationListener .

 public class LocationActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {} 

Затем настройте LocationClient в onCreate() вашей Activity :

 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLocationClient = new LocationClient(this, this, this); mLocationRequest = LocationRequest.create(); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); mLocationRequest.setInterval(UPDATE_INTERVAL); mLocationRequest.setFastestInterval(FASTEST_INTERVAL); } 

Добавьте необходимые методы в свою Activity ; onConnected() – это метод, который вызывается при подключении LocationClient . onLocationChanged() is where you’ll retrieve the most up-to-date location.

 @Override public void onConnectionFailed(ConnectionResult connectionResult) { Log.w(TAG, "Location client connection failed"); } @Override public void onConnected(Bundle dataBundle) { Log.d(TAG, "Location client connected"); mLocationClient.requestLocationUpdates(mLocationRequest, this); } @Override public void onDisconnected() { Log.d(TAG, "Location client disconnected"); } @Override public void onLocationChanged(Location location) { if (location != null) { Log.d(TAG, "Updated Location: " + Double.toString(location.getLatitude()) + "," + Double.toString(location.getLongitude())); } else { Log.d(TAG, "Updated location NULL"); } } 

Be sure to connect/disconnect the LocationClient so it’s only using extra battery when absolutely necessary and so the GPS doesn’t run indefinitely. The LocationClient must be connected in order to get data from it.

 public void onResume() { super.onResume(); mLocationClient.connect(); } public void onStop() { if (mLocationClient.isConnected()) { mLocationClient.removeLocationUpdates(this); } mLocationClient.disconnect(); super.onStop(); } 

Get the user’s location. First try using the LocationClient ; if that fails, fall back to the LocationManager .

 public Location getLocation() { if (mLocationClient != null && mLocationClient.isConnected()) { return mLocationClient.getLastLocation(); } else { LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); if (locationManager != null) { Location lastKnownLocationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (lastKnownLocationGPS != null) { return lastKnownLocationGPS; } else { return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); } } else { return null; } } } 

Actualy we can use the two providers both. And they just share a public listener:

 locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10 * 1000, (float) 10.0, listener); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 90 * 1000, (float) 10.0, listener); 

This is necessary because the OnLocationChanged() method always need to be called in time.

This is the code that provides user current location

create Maps Activty:

 public class Maps extends MapActivity { public static final String TAG = "MapActivity"; private MapView mapView; private LocationManager locationManager; Geocoder geocoder; Location location; LocationListener locationListener; CountDownTimer locationtimer; MapController mapController; MapOverlay mapOverlay = new MapOverlay(); @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); initComponents(); mapView.setBuiltInZoomControls(true); mapView.setSatellite(true); mapView.setTraffic(true); mapView.setStreetView(true); mapController = mapView.getController(); mapController.setZoom(16); locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); if (locationManager == null) { Toast.makeText(Maps.this, "Location Manager Not Available", Toast.LENGTH_SHORT).show(); return; } location = locationManager .getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location == null) location = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != null) { double lat = location.getLatitude(); double lng = location.getLongitude(); Toast.makeText(Maps.this, "Location Are" + lat + ":" + lng, Toast.LENGTH_SHORT).show(); GeoPoint point = new GeoPoint((int) (lat * 1E6), (int) (lng * 1E6)); mapController.animateTo(point, new Message()); mapOverlay.setPointToDraw(point); List listOfOverlays = mapView.getOverlays(); listOfOverlays.clear(); listOfOverlays.add(mapOverlay); } locationListener = new LocationListener() { public void onStatusChanged(String arg0, int arg1, Bundle arg2) {} public void onProviderEnabled(String arg0) {} public void onProviderDisabled(String arg0) {} public void onLocationChanged(Location l) { location = l; locationManager.removeUpdates(this); if (l.getLatitude() == 0 || l.getLongitude() == 0) { } else { double lat = l.getLatitude(); double lng = l.getLongitude(); Toast.makeText(Maps.this, "Location Are" + lat + ":" + lng, Toast.LENGTH_SHORT).show(); } } }; if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 1000, 10f, locationListener); locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 1000, 10f, locationListener); locationtimer = new CountDownTimer(30000, 5000) { @Override public void onTick(long millisUntilFinished) { if (location != null) locationtimer.cancel(); } @Override public void onFinish() { if (location == null) { } } }; locationtimer.start(); } public MapView getMapView() { return this.mapView; } private void initComponents() { mapView = (MapView) findViewById(R.id.map_container); ImageView ivhome = (ImageView) this.findViewById(R.id.imageView_home); ivhome.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { // TODO Auto-generated method stub Intent intent = new Intent(Maps.this, GridViewContainer.class); startActivity(intent); finish(); } }); } @Override protected boolean isRouteDisplayed() { return false; } class MapOverlay extends Overlay { private GeoPoint pointToDraw; public void setPointToDraw(GeoPoint point) { pointToDraw = point; } public GeoPoint getPointToDraw() { return pointToDraw; } @Override public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) { super.draw(canvas, mapView, shadow); Point screenPts = new Point(); mapView.getProjection().toPixels(pointToDraw, screenPts); Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.select_map); canvas.drawBitmap(bmp, screenPts.x, screenPts.y - 24, null); return true; } } } 

main.xml:

  < ?xml version="1.0" encoding="utf-8"?>    

and define following permission in manifest:

    

To get and show the user’s current location, you could also use MyLocationOverlay . Suppose you have a mapView field in your activity. All you would need to do to show the user location is the following:

 myLocationOverlay = new MyLocationOverlay(this, mapView); myLocationOverlay.enableMyLocation(); mapView.getOverlays().add(myLocationOverlay); 

This gets the current location from either the GPS or the network. If both fail, enableMyLocation() will return false .

As for the locations of things around the area, an ItemizedOverlay should do the trick.

I hope I haven’t misunderstood your question. Удачи.

EDIT: Updated with the latest Location Service API from Google Play Services library (July 2014)

I would recommend you to use the new Location Service API , available from the Google Play Services library, which provides a more powerful, high-level framework that automates tasks such as location provider choice and power management. According to the official documentation: “… Location API make it easy for you to build location-aware applications, without needing to focus on the details of the underlying location technology. They also let you minimize power consumption by using all of the capabilities of the device hardware.”

For further information visit: Making Your App Location-Aware

To see a full example using the latest Location Service API visit: Android LocationClient class is deprecated but used in documentation

Even though the answer is already given here. I just wanted to share this to the world incase the come across such scenario.

My requirement was that i needed to get a user’s current location within 30 to 35 seconds at max so here is the solution i made following Nirav Ranpara’s Answer .

1. I made MyLocationManager.java class which handles all the GPS and Network stuff

 import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import com.app.callbacks.OnLocationDetectectionListener; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.provider.Settings; import android.util.Log; import android.widget.Toast; public class MyLocationManager { /** The minimum distance to GPS change Updates in meters **/ private final long MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_GPS = 2; // 2 // meters /** The minimum time between GPS updates in milliseconds **/ private final long MIN_TIME_BW_UPDATES_OF_GPS = 1000 * 5 * 1; // 5 // seconds /** The minimum distance to NETWORK change Updates in meters **/ private final long MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_NETWORK = 5; // 5 // meters /** The minimum time between NETWORK updates in milliseconds **/ private final long MIN_TIME_BW_UPDATES_OF_NETWORK = 1000 * 10 * 1; // 10 // seconds /** * Lets just say i don't trust the first location that the is found. This is * to avoid that **/ private int NetworkLocationCount = 0, GPSLocationCount = 0; private boolean isGPSEnabled; private boolean isNetworkEnabled; /** * Don't do anything if location is being updated by Network or by GPS */ private boolean isLocationManagerBusy; private LocationManager locationManager; private Location currentLocation; private Context mContext; private OnLocationDetectectionListener mListener; public MyLocationManager(Context mContext, OnLocationDetectectionListener mListener) { this.mContext = mContext; this.mListener = mListener; } /** * Start the location manager to find my location */ public void startLocating() { try { locationManager = (LocationManager) mContext .getSystemService(Context.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 showSettingsAlertDialog(); } else { // If GPS enabled, get latitude/longitude using GPS Services if (isGPSEnabled) { locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES_OF_GPS, MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_GPS, gpsLocationListener); } if (isNetworkEnabled) { locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES_OF_NETWORK, MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_NETWORK, networkLocationListener); } } /** * My 30 seconds plan to get myself a location */ ScheduledExecutorService se = Executors .newSingleThreadScheduledExecutor(); se.schedule(new Runnable() { @Override public void run() { if (currentLocation == null) { if (isGPSEnabled) { currentLocation = locationManager .getLastKnownLocation(LocationManager.GPS_PROVIDER); } else if (isNetworkEnabled) { currentLocation = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); } if (currentLocation != null && mListener != null) { locationManager.removeUpdates(gpsLocationListener); locationManager .removeUpdates(networkLocationListener); mListener.onLocationDetected(currentLocation); } } } }, 30, TimeUnit.SECONDS); } catch (Exception e) { Log.e("Error Fetching Location", e.getMessage()); Toast.makeText(mContext, "Error Fetching Location" + e.getMessage(), Toast.LENGTH_SHORT).show(); } } /** * Handle GPS location listener callbacks */ private LocationListener gpsLocationListener = 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) { if (GPSLocationCount != 0 && !isLocationManagerBusy) { Log.d("GPS Enabled", "GPS Enabled"); isLocationManagerBusy = true; currentLocation = location; locationManager.removeUpdates(gpsLocationListener); locationManager.removeUpdates(networkLocationListener); isLocationManagerBusy = false; if (currentLocation != null && mListener != null) { mListener.onLocationDetected(currentLocation); } } GPSLocationCount++; } }; /** * Handle Network location listener callbacks */ private LocationListener networkLocationListener = 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) { if (NetworkLocationCount != 0 && !isLocationManagerBusy) { Log.d("Network", "Network"); isLocationManagerBusy = true; currentLocation = location; locationManager.removeUpdates(gpsLocationListener); locationManager.removeUpdates(networkLocationListener); isLocationManagerBusy = false; if (currentLocation != null && mListener != null) { mListener.onLocationDetected(currentLocation); } } NetworkLocationCount++; } }; /** * Function to show settings alert dialog. On pressing the Settings button * it will launch Settings Options. * */ public void showSettingsAlertDialog() { 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() { @Override 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() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); // Showing Alert Message alertDialog.show(); } } 

2. I made an Interface (callback) OnLocationDetectectionListener.java in order to communicate the results back to the calling fragment or activity

 import android.location.Location; public interface OnLocationDetectectionListener { public void onLocationDetected(Location mLocation); } 

3. Then i made an MainAppActivty.java Activity that implements OnLocationDetectectionListener interface and here is how i receive my location in it

 public class MainAppActivty extends Activity implements OnLocationDetectectionListener { private Location currentLocation; private MyLocationManager mLocationManager; @Override protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_home); super.onCreate(savedInstanceState); mLocationManager = new MyLocationManager(this, this); mLocationManager.startLocating(); } @Override public void onLocationDetected(Location mLocation) { //Your new Location is received here currentLocation = mLocation; } 

4. Add the following permissions to your manifest file

   

Hope this is helpful to others 🙂

 public static Location getBestLocation(Context ctxt) { Location gpslocation = getLocationByProvider( LocationManager.GPS_PROVIDER, ctxt); Location networkLocation = getLocationByProvider( LocationManager.NETWORK_PROVIDER, ctxt); Location fetchedlocation = null; // if we have only one location available, the choice is easy if (gpslocation != null) { Log.i("New Location Receiver", "GPS Location available."); fetchedlocation = gpslocation; } else { Log.i("New Location Receiver", "No GPS Location available. Fetching Network location lat=" + networkLocation.getLatitude() + " lon =" + networkLocation.getLongitude()); fetchedlocation = networkLocation; } return fetchedlocation; } /** * get the last known location from a specific provider (network/gps) */ private static Location getLocationByProvider(String provider, Context ctxt) { Location location = null; // if (!isProviderSupported(provider)) { // return null; // } LocationManager locationManager = (LocationManager) ctxt .getSystemService(Context.LOCATION_SERVICE); try { if (locationManager.isProviderEnabled(provider)) { location = locationManager.getLastKnownLocation(provider); } } catch (IllegalArgumentException e) { Log.i("New Location Receiver", "Cannot access Provider " + provider); } return location; } 

Simple and best way for GeoLocation.

 LocationManager lm = null; boolean network_enabled; if (lm == null) lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE); network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER); dialog = ProgressDialog.show(Kikit.this, "", "Fetching location...", true); final Handler handler = new Handler(); timer = new Timer(); TimerTask doAsynchronousTask = new TimerTask() { @Override public void run() { handler.post(new Runnable() { @Override public void run() { Log.e("counter value","value "+counter); if(counter< =8) { try { counter++; if (network_enabled) { lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE); Log.e("in network_enabled..","in network_enabled"); // Define a listener that responds to location updates LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { if(attempt == false) { attempt = true; Log.e("in location listener..","in location listener.."); longi = location.getLongitude(); lati = location.getLatitude(); Data.longi = "" + longi; Data.lati = "" + lati; Log.e("longitude : ",""+longi); Log.e("latitude : ",""+lati); if(faceboo_name.equals("")) { if(dialog!=null){ dialog.cancel();} timer.cancel(); timer.purge(); Data.homepage_resume = true; lm = null; Intent intent = new Intent(); intent.setClass(Kikit.this,MainActivity.class); startActivity(intent); finish(); } else { isInternetPresent = cd.isConnectingToInternet(); if (isInternetPresent) { if(dialog!=null) dialog.cancel(); Showdata(); } else { error_view.setText(Data.internet_error_msg); error_view.setVisibility(0); error_gone(); } } } } public void onStatusChanged(String provider, int status, Bundle extras) { } public void onProviderEnabled(String provider) { //Toast.makeText(getApplicationContext(), "Location enabled", Toast.LENGTH_LONG).show(); } public void onProviderDisabled(String provider) { } }; // Register the listener with the Location Manager to receive // location updates lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100000, 10,locationListener); } else{ //Toast.makeText(getApplicationContext(), "No Internet Connection.", 2000).show(); buildAlertMessageNoGps(); } } catch (Exception e) { // TODO // Auto-generated // catch // block } } else { timer.purge(); timer.cancel(); if(attempt == false) { attempt = true; String locationProvider = LocationManager.NETWORK_PROVIDER; // Or use LocationManager.GPS_PROVIDER try { Location lastKnownLocation = lm.getLastKnownLocation(locationProvider); longi = lastKnownLocation.getLongitude(); lati = lastKnownLocation.getLatitude(); Data.longi = "" + longi; Data.lati = "" + lati; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); Log.i("exception in loc fetch", e.toString()); } Log.e("longitude of last known location : ",""+longi); Log.e("latitude of last known location : ",""+lati); if(Data.fb_access_token == "") { if(dialog!=null){ dialog.cancel();} timer.cancel(); timer.purge(); Data.homepage_resume = true; Intent intent = new Intent(); intent.setClass(Kikit.this,MainActivity.class); startActivity(intent); finish(); } else { isInternetPresent = cd.isConnectingToInternet(); if (isInternetPresent) { if(dialog!=null){ dialog.cancel();} Showdata(); } else { error_view.setText(Data.internet_error_msg); error_view.setVisibility(0); error_gone(); } } } } } }); } }; timer.schedule(doAsynchronousTask, 0, 2000); private void buildAlertMessageNoGps() { final AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Your WiFi & mobile network location is disabled , do you want to enable it?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) { startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); setting_page = true; } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) { dialog.cancel(); finish(); } }); final AlertDialog alert = builder.create(); alert.show(); } 

A bit late here but what I would in such a situation is to use Google Maps API and mark the nearby locations using lat and long API of google maps. Plus user experience is better if you can show his/her location on a map. No need to bother about the updation of user location or frisking with android api. Let google maps handle the internals for you.

@emmby may have got it resolved in his app but for future reference a look at Google maps API for location specific stuff is what I recommend to fellow developers.

Edit: Link for displaying user location in google maps

It requires lots of things in place to get location updates in android, requires lots of bolierplate code.

You need to take care of

  • Google Play services availablity Check,
  • Update Google play Service if it is old or not available
  • Dialog Creation of GoogleApiClient and its callbacks connected,disconnected etc.
  • Stopping and releasing resources for location updates
  • Handling Location permission scenarios
  • Checking Location services are On or Off
  • Getting lastknown location is not so easy either
  • Fallback to last known location if not getting location after certain duration

I have created Android-EasyLocation (small android library) which will take care all this stuff and you can focus on business logic.

All you need is extend EasyLocationActivity and this

 requestSingleLocationFix(easyLocationRequest); 

или

 requestLocationUpdates(easyLocationRequest); 

Checkout sample app and steps needed here at https://github.com/akhgupta/Android-EasyLocation

This is the way I am requesting User Permissions.

Outside your application tag in AndroidManifest.xml add these permission requests.

    

Then add Google’s Location dependencies in the App Gradle file.

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

Now declare some Global variables.

 private lateinit var mFusedLocationProvider:FusedLocationProviderClient private lateinit var mLocationCallback: LocationCallback private lateinit var mLocationRequest: LocationRequest private var mLocationPermissionGranted:Boolean = false 

In OnCreate method of your Activity (I was not able to Format the Code Properly, Apology for that)

 mFusedLocationProvider = LocationServices.getFusedLocationProviderClient(this) //Location Callback mLocationCallback = object: LocationCallback(){ override fun onLocationResult(p0: LocationResult?) { if(p0==null){ //todo(request user to enable location from settings then remove return) return }else{ getDeviceLocation() } } } //Location Request mLocationRequest = LocationRequest.create() mLocationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY //Set the Interval for Latest Interval Update mLocationRequest.interval = 5000 //Set How Many Location Updated you Want mLocationRequest.numUpdates = 1 getLocationPermission() getDeviceLocation() 

Now create both the functions.

  private fun getLocationPermission() { val permission:Array = arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION,android.Manifest.permission.ACCESS_COARSE_LOCATION) if(ContextCompat.checkSelfPermission(applicationContext,Constant.FINE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){ if(ContextCompat.checkSelfPermission(applicationContext,Constant.COARSE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){ mLocationPermissionGranted = true } }else{ ActivityCompat.requestPermissions(this,permission,Constant.LOCATION_REQUEST_CODE) } } 

Second Method

 private fun getDeviceLocation() { try{ if(mLocationPermissionGranted){ mFusedLocationProvider.lastLocation.addOnCompleteListener(this,{task: Task -> if(task.isSuccessful){ var currentLocation: Location? = task.result if(currentLocation!=null){ Log.i("Location","Latitude is ${currentLocation.latitude} and Longitude" + "${currentLocation.longitude}") } else mFusedLocationProvider.requestLocationUpdates(mLocationRequest,mLocationCallback,null) } }) } }catch (e:SecurityException){ Log.e("Error", "Security Exception ${e.message}") } } 

For Constant.kt

 class Constant{ companion object { //Location Request Settings const val SET_INTERVAL:Long = 2000 const val NUM_UPDATES:Int = 1 //Location Permission const val FINE_LOCATION:String = android.Manifest.permission.ACCESS_FINE_LOCATION const val COARSE_LOCATION:String = android.Manifest.permission.ACCESS_COARSE_LOCATION } } 

By using FusedLocationProviderApi which is the latest API and the best among the available possibilities to get location in Android. add this in build.gradle file

 dependencies { compile 'com.google.android.gms:play-services:6.5.87' } 

you can get full source code by this url http://javapapers.com/android/android-location-fused-provider/

Here’s what I do:

  1. First of all I check whether NETWORK or GPS providers are enabled. Some may be disabled on the device, some may be disabled in application manifest. If any provider is enabled, I fetch cached last location for this provider and start location update listeners for this provider.
  2. There is a method to determine whether a location is better than last received location as mentioned in link :- https://developer.android.com/guide/topics/location/strategies.html#BestEstimate
  3. If I get update from location listener I check whether this location is better than previously received location. and If it is better than replace this location to previous best location( mFinalLocation ).
  4. There is also a handler(timer) for two minutes, which eventually stops the service and in onDestroy() method of service, stop listening for location updates for each of the provider.

Below is the code for service. You can run it based upon frequency of location update you need.

 import android.app.Service; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.support.annotation.Nullable; import android.util.Log; public class RecordLocationService extends Service { private final String TAG = RecordLocationService.class.getSimpleName(); private final int TWO_MINUTES = 1000 * 60 * 2; private LocationManager mLocationManager; private MyLocationListener mLocationListeners[] = new MyLocationListener[]{ new MyLocationListener(LocationManager.NETWORK_PROVIDER), new MyLocationListener(LocationManager.GPS_PROVIDER) }; private Location mFinalLocation; private class MyLocationListener implements LocationListener { private String mProvider; public MyLocationListener(String provider) { Log.d(TAG, "LocationListener : " + provider); mProvider = provider; } public String getProvider() { return mProvider; } @Override public void onLocationChanged(Location location) { Log.d(TAG, "onLocationChanged : " + location); if (isBetterLocation(location, mFinalLocation)) { Log.d(TAG, "Setting current Final Location to recent most Location for Provider : " + location.getProvider()); Log.d(TAG, "Setting current Final Location to : " + location); mFinalLocation = location; } else { Log.d(TAG, "Keeping current Final Location to previous Final Location"); } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { Log.d(TAG, "onStatusChanged provider " + provider); } @Override public void onProviderEnabled(String provider) { Log.d(TAG, "onProviderEnabled provider " + provider); } @Override public void onProviderDisabled(String provider) { Log.d(TAG, "onProviderDisabled provider " + provider); } } private Handler mStopServiceHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: { stopSelf(); } break; } } }; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); Log.d(TAG, "onStartCommand"); return START_STICKY; } @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate"); requestLocation(); mStopServiceHandler.sendEmptyMessageDelayed(1, TWO_MINUTES); } private void requestLocation() { // Acquire a reference to the system Location Manager if (mLocationManager == null) { mLocationManager = (LocationManager) this.getApplicationContext().getSystemService(Context.LOCATION_SERVICE); } try { if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER) && mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { Log.d(TAG, "Fetching Cached Location for Provider : " + LocationManager.NETWORK_PROVIDER); Location cachedNetworkLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (cachedNetworkLocation != null) { Log.d(TAG, "Setting Final Location to Cached Location for Provider : " + LocationManager.NETWORK_PROVIDER); Log.d(TAG, "Setting Final Location to : " + cachedNetworkLocation); mFinalLocation = cachedNetworkLocation; } else { Log.d(TAG, "Cached Location for Provider : " + LocationManager.NETWORK_PROVIDER + " is NULL"); } Log.d(TAG, "Requesting Location Update for Provider : " + LocationManager.NETWORK_PROVIDER); mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocationListeners[0]); } } catch (SecurityException se) { Log.e(TAG, se.getMessage(), se); } catch (IllegalArgumentException iae) { Log.e(TAG, iae.getMessage(), iae); } try { if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER) && mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { Log.d(TAG, "Fetching Cached Location for Provider : " + LocationManager.GPS_PROVIDER); Location cachedGPSLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (cachedGPSLocation != null) { if (isBetterLocation(cachedGPSLocation, mFinalLocation)) { Log.d(TAG, "Setting Final Location to Cached Location for Provider : " + LocationManager.GPS_PROVIDER); Log.d(TAG, "Setting Final Location to : " + cachedGPSLocation); mFinalLocation = cachedGPSLocation; } } else { Log.d(TAG, "Cached Location for Provider : " + LocationManager.GPS_PROVIDER + " is NULL"); } Log.d(TAG, "Requesting Location Update for Provider : " + LocationManager.GPS_PROVIDER); mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListeners[1]); } } catch (SecurityException se) { Log.e(TAG, se.getMessage(), se); } catch (IllegalArgumentException iae) { Log.e(TAG, iae.getMessage(), iae); } } /** * 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); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); if (mLocationManager != null) { for (int i = 0; i < mLocationListeners.length; i++) { try { Log.d(TAG, "Removing Location Update for Provider : " + mLocationListeners[i].getProvider()); mLocationManager.removeUpdates(mLocationListeners[i]); } catch (Exception ex) { Log.e(TAG, "fail to remove location listeners, ignore", ex); } } } } } 

Recently refactored to obtain the location of the code, learn some good ideas, and finally achieved a relatively perfect library and Demo.

 //request all valid provider(network/gps) private boolean requestAllProviderUpdates() { checkRuntimeEnvironment(); checkPermission(); if (isRequesting) { EasyLog.d("Request location update is busy"); return false; } long minTime = getCheckTimeInterval(); float minDistance = getCheckMinDistance(); if (mMapLocationListeners == null) { mMapLocationListeners = new HashMap<>(); } mValidProviders = getValidProviders(); if (mValidProviders == null || mValidProviders.isEmpty()) { throw new IllegalArgumentException("Not available provider."); } for (String provider : mValidProviders) { LocationListener locationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { if (location == null) { EasyLog.e("LocationListener callback location is null."); return; } printf(location); mLastProviderTimestamp = location.getTime(); if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) { finishResult(location); } else { doLocationResult(location); } removeProvider(location.getProvider()); if (isEmptyValidProviders()) { requestTimeoutMsgInit(); removeUpdates(); } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } }; getLocationManager().requestLocationUpdates(provider, minTime, minDistance, locationListener); mMapLocationListeners.put(provider, locationListener); EasyLog.d("Location request %s provider update.", provider); } isRequesting = true; return true; } //remove request update public void removeUpdates() { checkRuntimeEnvironment(); LocationManager locationManager = getLocationManager(); if (mMapLocationListeners != null) { Set keys = mMapLocationListeners.keySet(); for (String key : keys) { LocationListener locationListener = mMapLocationListeners.get(key); if (locationListener != null) { locationManager.removeUpdates(locationListener); EasyLog.d("Remove location update, provider is " + key); } } mMapLocationListeners.clear(); isRequesting = false; } } //Compared with the last successful position, to determine whether you need to filter private boolean isNeedFilter(Location location) { checkLocation(location); if (mLastLocation != null) { float distance = location.distanceTo(mLastLocation); if (distance < getCheckMinDistance()) { return true; } if (location.getAccuracy() >= mLastLocation.getAccuracy() && distance < location.getAccuracy()) { return true; } if (location.getTime() <= mLastProviderTimestamp) { return true; } } return false; } private void doLocationResult(Location location) { checkLocation(location); if (isNeedFilter(location)) { EasyLog.d("location need to filtered out, timestamp is " + location.getTime()); finishResult(mLastLocation); } else { finishResult(location); } } //Return to the finished position private void finishResult(Location location) { checkLocation(location); double latitude = location.getLatitude(); double longitude = location.getLongitude(); float accuracy = location.getAccuracy(); long time = location.getTime(); String provider = location.getProvider(); if (mLocationResultListeners != null && !mLocationResultListeners.isEmpty()) { String format = "Location result:<%f, %f> Accuracy:%f Time:%d Provider:%s"; EasyLog.i(String.format(format, latitude, longitude, accuracy, time, provider)); mLastLocation = location; synchronized (this) { Iterator iterator = mLocationResultListeners.iterator(); while (iterator.hasNext()) { LocationResultListener listener = iterator.next(); if (listener != null) { listener.onResult(location); } iterator.remove(); } } } } 

Complete code: https://github.com/bingerz/FastLocation/blob/master/fastlocationlib/src/main/java/cn/bingerz/fastlocation/FastLocation.java

*Each request to complete the location, it is best to removeUpdates, otherwise the phone status bar will always display the positioning icon.

After seeing all the answers, and question ( Simplest and Robust ). I got clicked about only library Android-ReactiveLocation .

When i made an location tracking app. Then i realized that its very typical to handle location tracking with optimised with battery.

So i want tell freshers and also developers who don’t want to maintain their location code with future optimisations. Use this library.

 ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(context); locationProvider.getLastKnownLocation() .subscribe(new Consumer() { @Override public void call(Location location) { doSthImportantWithObtainedLocation(location); } }); 

Dependencies to put in app level build.gradle

 dependencies { ... compile 'pl.charmas.android:android-reactive-location2:2.1@aar' compile 'com.google.android.gms:play-services-location:11.0.4' //you can use newer GMS version if you need compile 'com.google.android.gms:play-services-places:11.0.4' compile 'io.reactivex:rxjava:2.0.5' //you can override RxJava version if you need } 

Pros to use this lib:

  • This lib is and will be actively maintained.
  • You dont worry about battery optimisation. As developers have done their best.
  • Easy installation, put dependency and play.
  • easily connect to Play Services API
  • obtain last known location
  • subscribe for location updates use
  • location settings API
  • manage geofences
  • geocode location to list of addresses
  • activity recognition
  • use current place API fetch place
  • autocomplete suggestions

From last more than one year, I was using the combination of GPS_PROVIDER and NETWORK_PROVIDER to get the current location and it was working good, but from last few months I’m getting location after a long delay, so I switched to latest API FusedLocationProviderClient and it is working pretty good.

Here is the class which I wrote to get current location by using FusedLocationProviderClient. In below code, I used a timer to wait for while to get the current location, I scheduled timer 15 seconds delay, you can change it according to you.

 private static FusedLocationService ourInstance; private final LocationRequest locationRequest; private FusedLocationProviderClient mFusedLocationClient; private Location mLastLocation; private Context context; private FindOutLocation findOutLocation; private boolean callbackTriggered = false; private Timer timer; public static FusedLocationService getInstance(Context pContext) { if (null == ourInstance) ourInstance = new FusedLocationService(pContext); return ourInstance; } private FusedLocationService(Context pContext) { context = pContext; mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context); locationRequest = getLocationRequest(); requestLocation(context); } public Location getLastKnownLocation() { return mLastLocation; } private void requestLocation(Context context) { if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, null); mFusedLocationClient.getLastLocation().addOnSuccessListener(location -> { if (location != null) { mLastLocation = location; triggerCallback(mLastLocation); } }); } private LocationRequest getLocationRequest() { LocationRequest locationRequest = new LocationRequest(); long INTERVAL = 10 * 1000; long FASTEST_INTERVAL = 5 * 1000; locationRequest.setInterval(INTERVAL); locationRequest.setFastestInterval(FASTEST_INTERVAL); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); return locationRequest; } private LocationCallback mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { for (Location location : locationResult.getLocations()) { if (location != null) mLastLocation = location; } if (null != mLastLocation) triggerCallback(mLastLocation); } }; public static abstract class FindOutLocation { public abstract void gotLocation(Location location); } @SuppressLint("MissingPermission") public void findLocation(FindOutLocation findOutLocation) { long TIMER_TIME_OUT = 15 * 1000; this.findOutLocation = findOutLocation; callbackTriggered = false; try { requestLocation(context); timer = new Timer(); timer.schedule(new GetLastLocation(context), TIMER_TIME_OUT); } catch (Exception e) { e.printStackTrace(); } } private class GetLastLocation extends TimerTask { Context context; GetLastLocation(Context context) { this.context = context; } @Override public void run() { triggerCallback(mLastLocation); } } private void triggerCallback(Location location) { if (null != location) mLastLocation = location; if (!callbackTriggered && null != findOutLocation) { callbackTriggered = true; removeLocationUpdates(); findOutLocation.gotLocation(location); findOutLocation = null; } } private void removeLocationUpdates() { if (null != timer) timer.cancel(); if (null != mFusedLocationClient) mFusedLocationClient.removeLocationUpdates(mLocationCallback); } } 

And called this from activity, here is the code

  FusedLocationService.FindOutLocation findOutLocation = new FusedLocationService.FindOutLocation() { @Override public void gotLocation(Location currentLocation) { if (currentLocation != null) { /*TODO DO SOMETHING WITH CURRENT LOCATION*/ } } }; FusedLocationService.getInstance(this).findLocation(findOutLocation); 

Add following entries in the AndroidManifest.xml

     

Before I answer, I just want to be upfront about the fact that I’m affiliated with Neura. Now to your question. So, instead of wasting your time behind coding to get your user’s location, you can use our SDK. It takes less than 30 mins to integrate. Neura provides you with your user’s location/activity,and you can configure your application accordingly to perform certain tasks after you receive the data. Here’s a few reasons to use Neura over other Activity recognition API’s:

  1. No need to code tons of lines to understand your user.
  2. Gives you accurate results.
  3. Consumes less than 1% of your battery.
Interesting Posts

Выполнить обновление (пересканирование) беспроводных сетей из командной строки?

Как добавить комбобокс в Word?

ExpressCache против технологий быстрого хранения Intel и интеллектуальных ответных технологий

Доступ запрещен на mklink

Непрерывные номера страниц в документе Word 2007 с разрывами разделов

Выделите выделенные строки в окно в irssi

Почему мой ArrayList содержит N копий последнего элемента, добавленного в список?

Автономный установщик Office 2013

Chrome: как остановить перенаправление с http: // на https: //

Свяжите новую запись с существующей формой

Как может соответствовать размеру страницы чертежу в Microsoft Visio 2013?

Имеет ли профиль Firefox в Dropbox хорошую комбинацию?

Как скопировать ссылку на сообщение Mail.app без использования перетаскивания?

Как устранить проблемы с оборудованием, связанные с зависанием компьютера / сбоем?

Получение через EFS (зашифрованная файловая система)

Давайте будем гением компьютера.