Android: LocationManager против Google Play Services

151

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

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

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

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

SoCo
источник
1
Посетите здесь stackoverflow.com/questions/21397177/…
Мохаммад Таукир

Ответы:

320

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

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

  1. Android Location API

    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);

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

  1. API Google Location Services

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

Чтобы использовать Google Location Services, ваше приложение должно подключиться к 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()ноль?

locationClient.getLastLocation()Получает последнее известное местоположение от клиента. Однако провайдер локализованного местоположения будет поддерживать фоновое местоположение, только если к нему подключен хотя бы один клиент. Как только первый клиент подключится, он сразу попытается найти местоположение. Если ваша деятельность является первым клиентом для подключения и вы звоните 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!!!
    }

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

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

  • Пользователь отключил Службы определения местоположения

Во многих случаях у пользователя могут быть отключены службы определения местоположения (для экономии заряда аккумулятора или в целях конфиденциальности). В таком случае приведенный выше код все равно будет запрашивать обновления местоположения, но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;

И используйте locationEnabledфлаг в вашем 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);
}

ОБНОВИТЬ

Документ обновлен, LocationClient удален, и API поддерживает включение GPS одним щелчком мыши из диалогового окна:

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
    // All location settings are satisfied. The client can initialize
    // location requests here.
    // ...
}
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if (e instanceof ResolvableApiException) {
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                ResolvableApiException resolvable = (ResolvableApiException) e;
                resolvable.startResolutionForResult(MainActivity.this,
                        REQUEST_CHECK_SETTINGS);
            } catch (IntentSender.SendIntentException sendEx) {
                // Ignore the error.
            }
        }
    }
});

Ссылка на сайт https://developer.android.com/training/location/change-location-settings#prompt

Новый клиент местоположения: FusedLocationProviderClient

  private FusedLocationProviderClient fusedLocationClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}

Рекомендуется пройти через https://developer.android.com/training/location перед выполнением каких-либо задач определения местоположения.

pRaNaY
источник
9
Вы можете использовать, SettingsApi.checkLocationSettings()чтобы проверить, активировал ли пользователь Службы определения местоположения (см. Здесь: developers.google.com/android/reference/com/google/android/gms/… ).
kaolick
3
LocationClient больше не существует. Обновленное и понятное руководство по местоположению можно найти в этой статье: blog.teamtreehouse.com/beginners-guide-location-android
lm2a
1
И учебная страница с примером SettingsApi: developer.android.com/training/location/…
androidguy
2
Вы также можете создать геозону используя LocationManager! Работает ли API-интерфейс fused location на устройствах без сервисов Google Play?
Мухаммед Бабар
Это может быть еще один лучший способ проверить состояние включения / выключения GPS fun isLocationEnabled(context: Context): Boolean { val locationMode: Int try { locationMode = Settings.Secure.getInt( context.contentResolver, Settings.Secure.LOCATION_MODE ) } catch (e: SettingNotFoundException) { e.printStackTrace() return false } return locationMode != Settings.Secure.LOCATION_MODE_OFF }
Wahib Ul Haq
32

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

Комплект
источник
2
Да, по моему опыту, Сервисы Google Play иногда предоставляют неточное местоположение.
VY
2
Да, API сервисов определения местоположения в Google Play может вводить в заблуждение информацию о местоположении. Модемы WiFi перемещаются, модемы WiFi обновляются с неверной информацией о местоположении (то есть, если местоположение подделывается устройством Android, которое обновляет местоположение модема WiFi), и существует множество других обстоятельств, которые могут привести к неправильным данным местоположения из триангуляции модема WiFi. Во всех наших приложениях, где точное местоположение является обязательным, мы используем только GPS.
user1608385
27

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

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

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

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

NoChinDeluxe
источник
2
У вас есть ссылки на эту документацию, из которой взяты эти цитаты? Было бы интересно узнать, говорит ли Google сейчас что-то другое.
Эдвард Брей
3
Конечно, они говорят это, потому что они хотят ваши данные о местоположении!
Flyview
Когда вы добавляете сервисы Google Play в свое приложение, если пользователь устанавливает ваше приложение, ему будет предложено «обновить» сервисы Google Play, чтобы использовать ваше приложение. В случае, если его / ее телефон почти заполнен (с темами WhatsApp и прочим), или у пользователя нет данных, извините вас, мой друг
доктор Deo
2
@Flyview Да! Lol, как они говорят, это звучит как волшебное решение! Самый большой недостаток в том, что вам нужны Google Play Services на устройстве !!!
Варун
25

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

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

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

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

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

j3App
источник
7

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

Более подробно diffferences между двумя APIs Google Play Service Location API и Android Framework Расположение API можно найти здесь

Дхрувам Гупта
источник
Я использовал ваш ответ, чтобы ответить на свой вопрос, если это нормально. Большое спасибо! stackoverflow.com/questions/39852955/…
Leniaal
@ Leniaal, так ты не думаешь, что мой ответ заслуживает одобрения?
Дхрувам Гупта
Это 3-летний документ. Но вот плюс 1
Дрю
5

Да, API сервисов определения местоположения в Google Play может вводить в заблуждение информацию о местоположении. Модемы WiFi перемещаются, модемы WiFi обновляются с неверной информацией о местоположении (то есть, если местоположение подделывается устройством Android, которое обновляет местоположение модема WiFi), и существует множество других обстоятельств, которые могут привести к неправильным данным местоположения из триангуляции модема WiFi. Во всех наших приложениях, где точное местоположение является обязательным, мы используем только GPS.

user1608385
источник
3

Различия между двумя API API определения местоположения службы Google Play и API определения местоположения Android Framework на основе службы GPS

FusedLocationProviderClient

  1. Для 1-й выборки местоположение не должно быть нулевым (то есть: некоторым другим приложениям необходимо обновить последнее известное местоположение в базе данных GoogleplayService. Если оно пустое, необходимо обойти это)
  2. Для следующей последовательной requestLocationUpdates()выборки он использует метод для извлечения местоположения.
  3. Выборка местоположения основана только на, locationRequest.setInterval(milliseconds)а setFastestInterval(milliseconds)не на изменении местоположения пользователя
  4. Возвращенное значение LatLng содержит только 7 десятичных значений (например: 11.9557996, 79.8234599), не столь точное
  5. Рекомендуется, когда ваше приложение требует, чтобы расстояние от текущего местоположения было незначительным (точность 50 - 100 метров)
  6. Эффективно в использовании батареи.

LocationManager Api

  1. Выборка местоположения пользователя вызывается с помощью locationManager.requestLocationUpdates ()
  2. Выбор местоположения на основе изменения местоположения пользователя и временных интервалов locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, milliseconds, mindistance, Mylocationlistener)

  3. Возвращенное значение LatLng содержит 14 десятичных значений (например: 11.94574594963342 79.81166719458997) точных значений местоположения

  4. Рекомендуется для приложения на основе определения местоположения, когда требуется большая точность даже в метрах.
  5. Использование батареи основано на интервале выборки и расстоянии выборки.
Sackurise
источник
Привет! 1 ° не более 111_111 метров (20_000_000 / 180). Так, 0,0000001 ° - это 0,011 м = 1 см. Я не знаю, где вам нужно лучшее разрешение GPS. И я даже не знаю, как вы можете добиться лучшего разрешения GPS.
Babay