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

Опубликовано: 2022-03-11

Информация о местоположении вашего пользователя является полезной информацией во многих приложениях, которые мы разрабатываем и используем сегодня. Существует множество популярных приложений на основе определения местоположения, которые облегчают нашу жизнь, а также меняют способ использования этих услуг. Примером может служить чрезвычайно популярное приложение Foursquare, где пользователи, которые часто посещают заведения и «отмечаются», часто получают скидки. Uber, который поможет вам заказать поездку с мобильного телефона по более низкой цене, чем обычное такси. Список большой и продолжает расти.

API службы определения местоположения

В этой статье мы собираемся создать простое Android-приложение для определения широты и долготы пользователя с помощью Android-интерфейса Google Location Services. При разработке приложений для Android есть несколько способов узнать местоположение пользователя.

Пакет «android.location»

Пакет «android.location» доступен с момента появления Android и дает нам доступ к службам определения местоположения. Эти службы позволяют приложениям получать периодические обновления географического положения устройства.

Пакет предоставляет два способа получения данных о местоположении:

  • LocationManager.GPS_PROVIDER: определяет местоположение с помощью спутников. В зависимости от условий этому провайдеру может потребоваться некоторое время, чтобы вернуть исправление местоположения.

  • LocationManager.NETWORK_PROVIDER: определяет местоположение на основе наличия ближайших вышек сотовой связи и точек доступа Wi-Fi. Это быстрее, чем GPS_PROVIDER.

Когда вы ищете местоположение пользователя, вы должны играть с этими провайдерами и их доступностью. В идеале вы получаете первое местоположение, используя NETWORK_PROVIDER, который может быть не таким точным, но намного быстрее. Затем вы можете попытаться повысить точность, прослушивая более точное определение местоположения с помощью GPS_PROVIDER.

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

API службы определения местоположения Google

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

  • Простота: в отличие от предыдущего API, вам больше не нужно иметь дело с несколькими поставщиками. Вместо этого вы указываете потребности высокого уровня, такие как «высокая точность» или «низкое энергопотребление», и он примет подходящий подход.

  • Доступность: дает вашему приложению немедленный доступ к лучшему, самому последнему известному местоположению. Обычно эта информация легкодоступна, вам просто нужно ее запросить.

  • Энергоэффективность: сводит к минимуму энергопотребление вашего приложения.

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

Давайте создадим Android-приложение на основе местоположения, используя этот API. Для этого мы будем использовать предложенную Google IDE для разработки приложений Android — Android Studio. Начать работу с Android Studio довольно просто. Их веб-сайт очень подробно описывает процедуру установки и настройки Android Studio, в том числе то, как загрузить свое первое приложение Android для разработки.

Android Studio должна упростить нам задачу. Однако нам нужно начать с настройки сценария сборки и добавления сервисов Google Play в качестве зависимости для этого приложения. Это можно сделать, изменив файл build.gradle следующим образом:

 dependencies { compile 'com.android.support:appcompat-v7:21.0.3' compile 'com.google.android.gms:play-services:6.5.87' // Add this line }

На момент написания этой статьи последней доступной версией сервисов Google Play была 6.5.87. Убедитесь, что вы всегда проверяете наличие последней доступной версии, прежде чем начать. Если новые версии появятся позже, и вы решите обновить их для своих проектов, протестируйте все функции, связанные с определением местоположения, на всех поддерживаемых вами версиях Android.

На этом этапе мы должны быть в состоянии начать выполнять реальную работу для нашего приложения.

Запрос разрешения, настройка AndroidManifest.xml

Android имеет специальные функции безопасности, которые не позволяют любому произвольному приложению запрашивать точное местоположение пользователя. Чтобы решить эту проблему, нам нужно отредактировать «AndroidManifest.xml» и добавить разрешение, необходимое для этого приложения:

 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Пока мы это делаем, мы также должны определить версию сервисов Google Play, которые мы используем для этого приложения:

 <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

Проверка доступности сервисов Google Play

Прежде чем получить доступ к функциям, предоставляемым Сервисами Google Play, мы должны проверить, установлены ли на устройстве Сервисы Google Play и что версия соответствует той, которую мы собираемся использовать (6.5.87).

 private boolean checkGooglePlayServices(){ int checkGooglePlayServices = GooglePlayServicesUtil .isGooglePlayServicesAvailable(mContext); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { /* * Google Play Services is missing or update is required * return code could be * SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID. */ GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, mContext, REQUEST_CODE_RECOVER_PLAY_SERVICES).show(); return false; } return true; }

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

сервисы гугл плей

После того, как пользователь завершает разрешение, предоставленное «GooglePlayServicesUtil.getErrorDialog()», запускается метод обратного вызова «onActivityResult()», поэтому мы должны реализовать некоторую логику для обработки этого вызова:

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) { if (resultCode == RESULT_OK) { // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(mContext, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show(); finish(); } } }

Доступ к API Google

Чтобы получить доступ к Google API, нам просто нужно выполнить еще один шаг: создать экземпляр GoogleApiClient. Клиент Google API обеспечивает общую точку входа для всех служб Google Play и управляет сетевым подключением между устройством пользователя и каждой службой Google. Наш первый шаг здесь — инициировать соединение. Обычно я вызываю этот код из метода onCreate активности:

 protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); }

Объединяя серию вызовов методов, мы указываем реализацию интерфейса обратного вызова и API службы определения местоположения, которые мы хотим использовать. Реализация интерфейса, в данном случае «это», получит ответ на асинхронный метод «connect ()», когда соединение с сервисами Google Play будет успешным, неудачным или будет приостановлено. После добавления этого кода наша «MainActivity» должна выглядеть так:

 package com.bitwoo.userlocation; import android.content.Intent; import android.location.Location; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationServices; public class MainActivity extends ActionBarActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private static int REQUEST_CODE_RECOVER_PLAY_SERVICES = 200; private GoogleApiClient mGoogleApiClient; private Location mLastLocation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (checkGooglePlayServices()) { buildGoogleApiClient(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } private boolean checkGooglePlayServices() { int checkGooglePlayServices = GooglePlayServicesUtil .isGooglePlayServicesAvailable(this); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { /* * google play services is missing or update is required * return code could be * SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID. */ GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, this, REQUEST_CODE_RECOVER_PLAY_SERVICES).show(); return false; } return true; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) { if (resultCode == RESULT_OK) { // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(this, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show(); finish(); } } } protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } @Override public void onConnected(Bundle bundle) { } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(ConnectionResult connectionResult) { } }

Затем в нашем методе «onStart» мы вызываем метод «connect» и ждем вызова метода обратного вызова «onConnected»:

 @Override protected void onStart() { super.onStart(); if (mGoogleApiClient != null) { mGoogleApiClient.connect(); } }

Метод onConnected будет выглядеть так:

 @Override public void onConnected(Bundle bundle) { mLastLocation = LocationServices.FusedLocationApi.getLastLocation( mGoogleApiClient); if (mLastLocation != null) { Toast.makeText(this, "Latitude:" + mLastLocation.getLatitude()+", Longitude:"+mLastLocation.getLongitude(),Toast.LENGTH_LONG).show(); } }

Этот обратный вызов запускается при подключении сервисов Google Play, что означает, что к тому времени у нас должно быть последнее известное местоположение. Однако это местоположение может быть нулевым (это редко, но не невозможно). В этом случае я рекомендую следить за обновлениями местоположения, которые будут рассмотрены далее.

Прослушивание обновлений местоположения

После того, как вы вызовете «getLastLocation», вы можете запросить периодические обновления от провайдера Fused Location. В зависимости от вашего приложения этот период может быть коротким или длинным. Например, если вы создаете приложение, которое отслеживает местоположение пользователя во время вождения, вам нужно будет прослушивать обновления через короткие промежутки времени. С другой стороны, если ваше приложение предназначено для обмена местоположением пользователя с его другом, вам, возможно, просто нужно время от времени запрашивать местоположение.

Создать запрос довольно просто — вы можете вызвать этот метод внутри метода «onCreate»:

 protected void createLocationRequest() { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(20000); mLocationRequest.setFastestInterval(5000); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); }

Мы создаем новый объект LocationRequest. Установите интервал на 20 секунд (20000 миллисекунд). Кроме того, мы установили частоту обновления с дросселированием на 5 секунд. Это говорит API предоставлять обновления каждые 20 секунд (предпочтительно), но если есть изменение, доступное в течение 5-секундного периода, он также должен предоставить это. Наконец, мы устанавливаем приоритет «PRIORITY_HIGH_ACCURACY», среди других доступных вариантов приоритета: PRIORITY_BALANCED_POWER_ACCURACY, PRIORITY_LOW_POWER, PRIORITY_NO_POWER.

После того, как вы создали запрос, вы готовы начать прослушивание обновлений местоположения после запуска метода «onConnected()»:

 protected void startLocationUpdates() { LocationServices.FusedLocationApi.requestLocationUpdates( mGoogleApiClient, mLocationRequest, this); }

Теперь осталось только реализовать метод обратного вызова для удовлетворения интерфейса LocationListener:

 public class MainActivity extends ActionBarActivity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener { // ... @Override public void onLocationChanged(Location location) { mLastLocation = location; Toast.makeText(this, "Latitude:" + mLastLocation.getLatitude()+", Longitude:"+mLastLocation.getLongitude(),Toast.LENGTH_LONG).show(); } } 

перестать слушать обновления

Прекратите слушать обновления

Важно явным образом прекратить прослушивание обновлений, когда они вам больше не нужны или если пользователь покидает ваше приложение. Следующий метод следует вызывать из обратного вызова «onPause»:

 protected void stopLocationUpdates() { if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates( mGoogleApiClient, this); } }

… и отключив Google API:

 @Override protected void onStop() { super.onStop(); if (mGoogleApiClient != null) { mGoogleApiClient.disconnect(); } }

Подведение итогов

Как видите, фундаментальные идеи реализации приложений с учетом местоположения в Android очень просты. Более того, с доступными API-интерфейсами, которые просты в использовании и понятны, создание базовых приложений на основе определения местоположения для Android не составит труда. Небольшой образец приложения, который мы создали здесь, предназначен именно для демонстрации этого. Вы можете найти полный исходный код для этого на GitHub. Обратите внимание, что для простоты приложение не обрабатывает метод обратного вызова onConnectionFailed.

Надеемся, что это руководство поможет вам начать работу с Google Location Services API.