Android: LocationManager vs Google Play Services

Я хочу создать приложение, которое сосредотачивается вокруг получения текущего местоположения пользователя, а затем найдет точки интереса (например, бары, рестораны и т. Д.), Которые находятся рядом с ним через API Google Places .

После поиска в Интернете места для начала я наткнулся на некоторые учебники, в которых используется класс LocationManager и некоторые другие, которые используют Службы Google Play , чтобы найти местоположение пользователей.

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

Каковы различия между этими двумя методами поиска мест (если они есть)?

Solutions Collecting From Web of "Android: LocationManager vs Google Play Services"

Расположение пользователя на Android

Получение местоположения пользователя на Android немного менее прямолинейно, чем на iOS. Чтобы начать путаницу, есть два совершенно разных способа, которыми вы можете это сделать. Первый использует Android API из android.location.LocationListener , а во втором – API-интерфейсы Google Play. com.google.android.gms.location.LocationListener . Давайте рассмотрим их обоих.

  1. API местоположения Android

    API-интерфейсы местоположения Android используют три разных провайдера для определения местоположения –

    • LocationManager.GPS_PROVIDER – этот провайдер определяет местоположение с использованием спутников. В зависимости от условий этот провайдер может занять некоторое время, чтобы вернуть исправление местоположения.
    • LocationManager.NETWORK_PROVIDER – Этот провайдер определяет местоположение на основе доступности точек сотовой связи и точек доступа WiFi. Результаты извлекаются с помощью сетевого поиска.
    • LocationManager.PASSIVE_PROVIDER – этот провайдер будет возвращать местоположения, созданные другими поставщиками. Вы пассивно получаете обновления местоположения, когда другие приложения или службы запрашивают их, даже не запрашивая их сами.

Суть его в том, что вы получаете объект LocationManager из системы, реализуете LocationListener и вызываете requestLocationUpdates в LocationManager .

Вот фрагмент кода:

  LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); // Define a listener that responds to location updates LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { // Called when a new location is found by the network location provider. makeUseOfNewLocation(location); } public void onStatusChanged(String provider, int status, Bundle extras) {} public void onProviderEnabled(String provider) {} public void onProviderDisabled(String provider) {} }; // Register the listener with the Location Manager to receive location updates locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); 

API API Google по стратегиям местоположения объясняет код довольно красиво. Но они также упоминают, что в большинстве случаев вы получите лучшую производительность батареи, а также более точную точность, используя вместо этого API-интерфейс Google Location Services . Теперь начинается путаница!

  1. API служб геолокации Google

API сервисов местоположения Google входит в состав APK сервисов Google Play ( вот как его настроить ). Они построены поверх API Android. Эти API предоставляют «Поставщик плавного доступа» вместо упомянутых выше поставщиков. Этот провайдер автоматически выбирает, какой базовый поставщик использовать, исходя из точности, использования батареи и т. Д. Это быстро, потому что вы получаете местоположение от общесистемной службы, которая постоянно обновляет ее. И вы можете использовать более сложные функции, такие как геообработка.

Чтобы использовать службы GooglePlayServicesClient Google, ваше приложение должно подключиться к GooglePlayServicesClient . Чтобы подключиться к клиенту, ваша деятельность (или фрагмент или так) должна реализовать интерфейсы GooglePlayServicesClient.ConnectionCallbacks и GooglePlayServicesClient.OnConnectionFailedListener . Вот пример кода:

  public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener { LocationClient locationClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); locationClient = new LocationClient(this, this, this); } @Override public void onConnected(Bundle bundle) { Location location = locationClient.getLastLocation() ; Toast.makeText(this, "Connected to Google Play Services", Toast.LENGTH_SHORT).show(); } @Override public void onDisconnected() { Toast.makeText(this, "Connected from Google Play Services.", Toast.LENGTH_SHORT).show(); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { // code to handle failed connection // this code can be found here — http://developer.android.com/training/location/retrieve-current.html } 
  • Почему locationClient.getLastLocation() null?

locationClient.getLastLocation() получает последнее известное местоположение от клиента. Однако поставщик Fused Location Provider будет поддерживать только фоновое местоположение, если к нему подключен хотя бы один клиент. Как только первый клиент подключится, он немедленно попытается получить местоположение. Если ваша деятельность является первым клиентом для подключения, и вы вызываете getLastLocation() сразу в onConnected() , для этого может оказаться недостаточно времени для первого местоположения. Это приведет к тому, что location будет null .

Чтобы решить эту проблему, вам нужно подождать (неопределенно), пока провайдер не получит местоположение, а затем вызовет getLastLocation() , чего невозможно узнать. Другой (лучший) вариант – реализовать интерфейс com.google.android.gms.location.LocationListener для получения периодических обновлений местоположения (и отключить его, как только вы получите первое обновление).

  public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener { // . . . . . . . . more stuff here LocationRequest locationRequest; LocationClient locationClient; @Override protected void onCreate(Bundle savedInstanceState) { // . . . . other initialization code locationClient = new LocationClient(this, this, this); locationRequest = new LocationRequest(); // Use high accuracy locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // Set the update interval to 5 seconds locationRequest.setInterval(UPDATE_INTERVAL); // Set the fastest update interval to 1 second locationRequest.setFastestInterval(FASTEST_INTERVAL); } // . . . . . . . . other methods @Override public void onConnected(Bundle bundle) { Location location = locationClient.getLastLocation(); if (location == null) locationClient.requestLocationUpdates(locationRequest, this); else Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show(); } // . . . . . . . . other methods @Override public void onLocationChanged(Location location) { locationClient.removeLocationUpdates(this); // Use the location here!!! } 

В этом коде вы проверяете, имеет ли клиент последнее местоположение (в onConnected ). Если нет, вы запрашиваете обновления местоположения и отключите запросы (в onLocationChanged() ), как только получите обновление.

Обратите внимание, что locationClient.requestLocationUpdates(locationRequest, this); onConnected быть внутри обратного вызова onConnected , иначе вы получите IllegalStateException потому что вы будете пытаться запрашивать места, не подключенные к клиенту служб Google Play.

  • Пользователь отключен

Много раз у пользователя были бы отключены службы определения местоположения (для экономии заряда аккумулятора или соображений конфиденциальности). В этом случае указанный выше код будет по-прежнему запрашивать обновления местоположения, но onLocationChanged никогда не будет вызван. Вы можете остановить запросы, проверив, отключил ли пользователь службы определения местоположения.

Если ваше приложение требует, чтобы они включали службы определения местоположения, вы хотели бы показать сообщение или тост. К сожалению, нет способа проверить, отключил ли пользователь службы определения местоположения в API сервисов геолокации Google. Для этого вам придется вернуться к API Android.

В методе onCreate :

  LocationManager manager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE); if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { locationEnabled = false; Toast.makeText(getActivity(), "Enable location services for accurate data", Toast.LENGTH_SHORT).show(); } else locationEnabled = true; 

И используйте флаг onConnected методе onConnected следующим образом:

  if (location != null) { Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show(); } else if (location == null && locationEnabled) { locationClient.requestLocationUpdates(locationRequest, this); } 

Благодаря Рахулу Джиресалу

Вы должны использовать местоположение Google Play Services api вместо LocationManager. Согласно документам:

API-интерфейсы местоположения сервисов Google Play предпочтительнее, чем API-интерфейсы местоположения Android (android.location) в качестве способа добавления информации о местоположении в приложение. Если вы используете API-интерфейсы местоположения Android, вам настоятельно рекомендуется как можно скорее переключиться на API местоположения сервисов Google Play.

Что касается того, зачем переключаться, Google говорит следующее:

API Google Location Services API, входящий в состав Google Play Services, предоставляет более мощную инфраструктуру высокого уровня, которая автоматически обрабатывает поставщиков местоположения, пользовательское перемещение и точность определения местоположения. Он также обрабатывает планирование обновления местоположения на основе параметров энергопотребления, которые вы предоставляете. В большинстве случаев вы получите более высокую производительность батареи, а также более соответствующую точность, используя API служб местоположения.

По моему опыту, «более подходящая точность» вовсе не означает лучшего. Если я чего-то не упускаю, если вы хотите убедиться, что GPS используется, LocationManager – единственный способ пойти. Мы отслеживаем транспортные средства с нашим приложением, и, опять же, если у меня что-то не хватает, службы Google Play очень часто делают некоторые неточности.

API Google Location Services API , входящий в состав Google Play Services, предоставляет более мощную инфраструктуру высокого уровня, которая автоматически обрабатывает поставщиков местоположения , пользовательское перемещение и точность определения местоположения . Он также обрабатывает планирование обновления местоположения на основе параметров энергопотребления, которые вы предоставляете. В большинстве случаев вы получите более высокую производительность батареи , а также более соответствующую точность, используя API служб местоположения.

Более подробные различия между двумя API-интерфейсами API Google Play и API Android Framework можно найти здесь

Я довольно давно пользуюсь Google Location Services API. У этого есть преимущества, поскольку он инкапсулирует сложность наличия нескольких источников для определения позиций. Однако он инкапсулируется слишком сильно , так что, когда вы получаете странную позицию, вы не можете определить, откуда взялась эта странная позиция.

В реальной жизни у меня появилось несколько уродов, которые находятся на расстоянии 10-ти километров от фактической позиции. Единственное объяснение заключается в том, что эти сумасшедшие местоположения связаны с ошибками в базе данных Googles Wi-Fi или NWK – ошибки, которые всегда будут присутствовать, поскольку изменения в сети Wi-Fi и сети каждый день меняются. Но, к сожалению, (и удивительно) API не дает вам никакой информации о том, как была создана отдельная позиция.

Это оставляет проблемы с необходимостью отфильтровывать урожайные значения, основанные на проверке правдоподобия на скорость, аксессуар, подшипник и т. Д.

… или вернуться к старым старым API-интерфейсам и использовать только GPS, что я, вероятно, сделаю до тех пор, пока Google не улучшит плавный API.