- Глубокое погружение в определение местоположения
- Покажи мне код!
- Что оно делает на самом деле?
- Теперь у вас есть код, давайте подробнее рассмотрим его
- Свежесть — значит никогда не ждать
- Используйте Intent’ы для получения обновлений местоположения
- Получение данных во время автономной работы
- Оптимизация времени работы аккумулятора: умные сервисы и использование состояния устройства для переключения ресиверов
- Мониторинг состояния аккумулятора для уменьшения функциональности и экономии энергии
- Службы расположения в Android
- Принципы определения расположения
- Поставщики сведений о расположении
- Разрешения расположения
- Использование Fused Location Provider
- Проверка установки Сервисов Google Play
- FusedLocationProviderClient
- Получение последнего известного расположения
- Подписка на данные об изменении расположения
- Использование API службы расположения Android
- Диспетчер расположения
- Запрос данных об изменении расположения из LocationManager
- Реагирование на данные об изменении расположения из LocationManager
- Отмена подписки на данные об изменении из LocationManager
- Определение лучшего поставщика сведений о расположении для LocationManager
- Сводка
Глубокое погружение в определение местоположения
Этот пост является переводом топика из блога android-developers. Далее повествование ведется от Рето Майера, автора книги Professional Android 2 Application Development. Он пишет о том, как можно улучшить приложения, использующие местоположение, в смысле кэширования результатов, скорости работы и так далее.
Без разницы, ищете ли вы место, где бы поесть, или ближайшее место велосипедов Boris Bike, всегда есть задержка при получении данных местоположения от GPS и заполнении абстрактного списка результатов в вакууме. Когда вы находитесь в месте, где хотели бы получить контекстную информацию, то часто вы сталкиваетесь с отсутствием подключения к данным.
Вместо того, чтобы грозить кулаком в небо, я написал open-source приложение, которое включает в себя советы и рекомендации по сокращению времени между открытием приложения и просмотром актуальной информации о близлежащих местах, вкупе с разумным обеспечением offline режима работы. И всё это, сохраняя использование аккумулятора на возможном минимуме.
Покажи мне код!
Вы можете проверить мой проект Android Protips for Location. Не забудьте прочесть Readme.txt, чтобы успешно скомпилировать и запустить приложение.
Что оно делает на самом деле?
Оно использует Google Places API для реализации базовой функциональности приложений, которые которые используют местоположение для определения списка близлежащих достопримечательностей (точек на карте), позволяют просмотреть их детали, а также проверить или оценить.
Код реализует многие из лучших практик, о которых я подробно рассказал на своей сессии на Google I/O 2011, Android Protips: Advanced Topics for Expert Android Developers (видео). В том числе использование Intent’ов для получения обновлений о местоположении, используя Passive Location Provider, наблюдение за состоянием устройства для изменения частоты обновлений, переключение Receiver’ов во время исполнения приложения, и также используя Cursor Loader.
Приложение написано для Honeycomb, но также может работать и на версия 1.6 и выше.
Теперь у вас есть код, давайте подробнее рассмотрим его
Мой главный приоритет — свежесть: минимизация задержек между открытием приложения и возможностью проверить нужные места, и в то же время минимизировать использование аккумулятора.
Требования:
- Текущее местоположение должно находиться так быстро, как это возможно
- Список мест должен обновляться при изменение местоположения
- Список близлежащих мест должен быть доступен (в деталях) в автономном режиме
- Отметки также должны быть доступны в автономном режиме
- Данные о местоположении и другие данные пользователя должны быть правильно обработаны (см. более ранний пост с лучшими практиками )
Свежесть — значит никогда не ждать
Можно значительно сократить время ожидания получения первого приближения к местоположению, путём выбора последнего известного из Location Manager’a каждый раз, когда приложение переходит в активный режим.
В этом примере из GingerbreadLastLocationFinder, мы перебираем все провайдеры местоположения на устройстве, даже те, которые на данный момент недоступны, чтобы найти наиболее точное последнее местоположение.
Если есть координаты одного или более местоположений, то выбирается самое точное. Иначе, просто возвращается самый недавний результат.
Во втором случае (когда определено, что последнее обновление местоположения недостаточно недавнее), значение так или иначе возвращается, но мы запрашиваем одно обновление местоположения, используя самый быстрый провайдер.
К сожалению, мы не можем определить наибыстрейших провайдеров, но, на практике, понятно, что определение местоположения при помощи сети возвращает результаты быстрее.
Отметим также, что этот фрагмент кода показывает GingerbreadLastLocationFinder, который использует метод requestSingleUpdate для получения единоразового обновления местоположения. Эта функциональность не была доступна до Gingerbread — проверьте LegacyLastLocationFinder, посмотрите как я реализовал такую же функциональность для более ранних версий Android.
singleUpdateReceiver передает полученное обновление назад к вызывающему классу через слушателя Location Listener.
Используйте Intent’ы для получения обновлений местоположения
Получив наиболее точную/своевременную оценку текущей позиции, мы также хотим получать её обновления.
Класс PlacesConstants включает в себя набор значений, которые определяют частоту обновления местоположения. Настройте их, чтобы убедиться, что обновления приходят так часто, как это требуется.
Следующий шаг — запросить обновление местоположения от Location Manager. В следующем фрагменте кода, взятом из GingerbreadLocationUpdateRequester мы можем передать критерии, используемые для определения — какой Location Manager будет запрашивать обновления напрямую в вызове метода requestLocationUpdates.
Обратите внимание, что мы передаём Pending Intent, а не Location Listener.
Вообще, я предпочитаю использовать Location Listener’ов, потому что они предоставляют гибкость в регистрации приёмников в нескольких Activity или Сервисах, или напрямую в манифесте.
В этом приложении, новое местоположение означает обновленный список близлежащих мест. Это происходит через сервисы, которые отправляют запросы к серверу и обновляют Контент-провайдер, который заполняет список мест.
Так как изменение местоположения напрямую не обновляет UI, то имеет смысл создавать и регистрировать связанный LocationChangedReceiver в манифесте, а не в Activity.
LocationChangedReceiver извлекает местоположение из каждого обновления и запускает сервис PlaceUpdateService, чтобы обновить базу близлежащих мест.
Получение данных во время автономной работы
Чтобы добавить поддержку режима offline, мы начнём с кэширования результатов поиска по PlacesContentProvider и PlaceDetailsContentProvider.
Также, при определенный обстоятельствах нужно проводить выборку сведений о местоположении. Этот фрагмент кода из сервиса PlacesUpdateService демонстрирует, как предварительная выборка включается для ограниченного количества мест.
Обратите внимание на то, что предварительная выборка данных потенциально выключается при низком заряде аккумулятора.
Похожая техника используется для реализации offline отметок.
Оптимизация времени работы аккумулятора: умные сервисы и использование состояния устройства для переключения ресиверов
Нет смысла запускать сервис обновления, когда устройство находится в автономном режиме. Сервис PlaceUpdateService проверяет возможность соединения, прежде чем пытаться получить обновление.
Если соединения нет, то ActiveLocationChangedReceiver и PassiveLocationChangedReceiver выключаются, а ConnectivityChangedReceiver включается.
ConnectivityChangedReceiver прослушивает все изменения сетевого соединения. Когда производится новое подключение, то он просто выключает себя и включает слушателей местоположения.
Мониторинг состояния аккумулятора для уменьшения функциональности и экономии энергии
Когда телефон на последних 15%, то большинство приложений не работает, для того чтобы сохранить заряд. Мы можем зарегистрировать ресиверов в манифесте, чтобы выдавать предупреждение, когда устройство входит или выходит из состояния низкой батареи.
Этот фрагмент из PowerStateChangedReceiver выключает PassiveLocationChangedReceiver всякий раз, когда устройство переходит в состояние низкого аккумулятора и включает его, когда заряд в порядке.
Можно расширить эту логику, отключив все упреждающие выборки или уменьшив частоту обновления в условиях низкого заряда аккумулятора.
Источник
Службы расположения в Android
В этом руководстве рассматривается отслеживание расположения в приложениях Android и описывается, как узнать расположение пользователя с помощью API службы расположения Android, а также Fused Location Provider, доступного в API служб расположения Google.
Android предоставляет доступ к различным технологиям определения расположения, например расположения вышек сотовой связи, Wi-Fi и GPS. Сведения о каждой технологии определения расположения абстрагированы от поставщиков сведений о расположении. Это позволяет приложениям получать расположения одинаковым способом независимо от используемого поставщика. В этом руководстве рассматривается Fused Location Provider — компонент Сервисов Google Play, который интеллектуально определяет лучший метод получения расположения устройств в зависимости от доступных поставщиков и способа использования устройства. Мы рассмотрим API службы расположения Android и узнаем, как взаимодействовать с системной службой расположения с помощью LocationManager . Во второй части этого руководством рассматривается использование API служб расположения Android с помощью LocationManager .
Как правило, в приложениях следует использовать Fused Location Provider вместо устаревшего API службы расположения Android, только если это необходимо.
Принципы определения расположения
Независимо от того, какой API вы выбрали для работы с данными расположения, некоторые принципы в Android неизменны. В этом разделе описываются поставщики сведений о расположении и разрешения, связанные с расположением.
Поставщики сведений о расположении
Для определения расположения пользователя используется несколько технологий. Используемое оборудование зависит от типа поставщика сведений о расположении, выбранного для сбора данных. Android использует три поставщика сведений о расположении.
Поставщик GPS — GPS предоставляет наиболее точное расположение, использует максимальную мощь и лучше всего туризм. Этот поставщик использует сочетание технологии GPS и технологии aGPS, которая возвращает данные GPS, собранные вышками сотовой связи.
Поставщик сети — предоставляет сочетание Wi-Fi и сотовой связи, включая данные агпс, собираемые ячейкой Towers. Он использует меньше электроэнергии, чем поставщик данных GPS, но возвращает данные о расположении переменной точности.
Пассивный поставщик — параметр «проникновения», использующий поставщики, запрашиваемые другими приложениями или службами для создания данных расположения в приложении. Это менее надежный, но более энергосберегающий вариант, который идеально подходит для приложений, для работы которых не требуется постоянное обновление данных расположения.
Поставщики сведений о расположении доступны не всегда. Например, может потребоваться использовать GPS для приложения, но функция GPS может быть отключена в параметрах или устройство может вообще не поддерживать технологию GPS. Если конкретный поставщик недоступен, при выборе этого поставщика может быть возвращено значение null .
Разрешения расположения
Приложению с поддержкой расположения требуется доступ к аппаратным датчикам устройства для получения данных GPS, Wi-Fi и сотовой сети. Управление доступом осуществляется с помощью соответствующих разрешений в манифесте приложения Android. Доступно два разрешения — в зависимости от требований вашего приложения и выбора API, необходимо разрешить одно из следующих действий:
ACCESS_FINE_LOCATION — Разрешает приложению доступ к GPS. Требуется для использования поставщика данных GPS и пассивного поставщика (пассивному поставщику требуется разрешение на доступ к данным GPS, собираемым другим приложением или службой). Необязательное разрешение для поставщика данных сети.
ACCESS_COARSE_LOCATION — Разрешает приложению доступ к сотовой сети и расположению Wi-Fi. Требуется для поставщика сети , если не задано.
Для приложений, нацеленных на API версии 21 (Android 5.0 Lollipop) или более поздней версии, можно включить ACCESS_FINE_LOCATION и запускать их на устройствах, на которых отсутствует оборудование GPS. Если приложению требуется оборудование GPS, необходимо явно добавить android.hardware.location.gps uses-feature элемент в манифест Android. Дополнительные сведения доступны в справочных материалах по элементу uses-feature Android.
Чтобы задать разрешения, на Панели решения разверните папку Свойства и дважды щелкните файл AndroidManifest.xml. Разрешения будут перечислены в разделе Необходимые разрешения.
Установка любого из этих разрешений укажет Android, что приложению требуется разрешение пользователя для доступа к поставщикам сведений о расположении. Устройства, использующие уровень API 22 (Android 5.1) или ниже, будут предлагать пользователю предоставить эти разрешения при каждой установке приложения. На устройствах с уровнем API 23 (Android 6.0) или выше приложение должно будет выполнить проверку разрешений во время выполнения, прежде чем отправить запрос к поставщику сведений о расположении.
Примечание. Установка ACCESS_FINE_LOCATION подразумевает доступ к примерным и точным данным расположения. Не нужно задавать оба разрешения. Задайте только минимальное разрешение, достаточное для работы приложения.
В этом фрагменте кода приведен пример того, как проверить, имеет ли приложение разрешение для ACCESS_FINE_LOCATION .
Приложения должны быть устойчивы к ситуациям, когда пользователь не предоставил разрешение (или отменил его), и продолжать работу. Дополнительные сведения о реализации проверок разрешений во время выполнения в Xamarin.Android приведены в руководстве по управлению разрешениями.
Использование Fused Location Provider
Поставщик Fused Location Provider предпочтителен для приложений Android, которые получают данные об изменении расположения от устройства, так как он эффективно выбирает поставщик сведений о расположении во время выполнения, чтобы обеспечить оптимальную информацию о расположении и экономить заряд аккумулятора. Например, пользователь, гуляющий на открытом воздухе, получает лучшие координаты расположения с помощью GPS. Если он затем зайдет в здание, где сигнал GPS слабый (или отсутствует), Fused Location Provider может автоматически переключиться на Wi-Fi, который лучше работает в помещениях.
API Fused Location Provider предоставляет множество других инструментов для расширения возможностей определения расположения, включая геозоны и мониторинг активности. В этом разделе описываются основы настройки LocationClient , установка поставщиков и получение данных о расположении пользователя.
Fused Location Provider является компонентом Сервисов Google Play. Для работы API Fused Location Provider в приложении должен быть правильно установлен и настроен пакет Сервисов Google Play, а на устройстве должен быть установлен APK Сервисов Google Play.
Прежде чем приложение Xamarin.Android сможет использовать Fused Location Provider, в проект нужно добавить пакет Xamarin.GooglePlayServices.Location. Кроме того, во все файлы исходного кода, которые ссылаются на классы, описанные ниже, должны быть добавлены следующие инструкции using .
Проверка установки Сервисов Google Play
Работа Xamarin.Android завершится аварийно, если при попытке использовать Fused Location Provider не будут установлены Сервисы Google Play (или этот они окажутся устаревшими). В этом случае возникнет исключение времени выполнения. Если Сервисы Google Play не установлены, приложение должно вернуться к использованию службы расположения Android, о которой говорилось выше. Если Сервисы Google Play устарели, приложение может отобразить для пользователя сообщение с просьбой обновить установленную версию Сервисов Google Play.
В этом фрагменте кода приведен пример того, как действие Android может программно проверить, установлены ли Сервисы Google Play.
FusedLocationProviderClient
Для взаимодействия с Fused Location Provider приложению Xamarin.Android нужен экземпляр FusedLocationProviderClient . Этот класс предоставляет необходимые методы для подписки на данные об изменении расположения и получения последнего известного расположения устройства.
Метод OnCreate действия подходит для получения ссылки на FusedLocationProviderClient , как показано в следующем фрагменте кода.
Получение последнего известного расположения
Метод FusedLocationProviderClient.GetLastLocationAsync() предоставляет простой и неблокирующий способ, позволяющий приложению Xamarin.Android быстро получить последнее известное расположение устройства с минимальными затратами на написание кода.
В этом фрагменте кода показано, как использовать метод GetLastLocationAsync для получения данных о расположении устройства.
Подписка на данные об изменении расположения
Приложение Xamarin. Android также может подписываться на обновления расположения из поставщика расположений с плавким предохранителем с помощью FusedLocationProviderClient.RequestLocationUpdatesAsync метода, как показано в следующем фрагменте кода:
Этот метод принимает два параметра.
Android.Gms.Location.LocationRequest — LocationRequest Объект — это то, как приложение Xamarin. Android передает параметры, как именно должен работать поставщик расположения с плавким предохранителем. LocationRequest содержит такие сведения, как часто следует отправлять запросы или какова важность точности данных об изменении расположения. Например, важный запрос данных о расположении приведет к тому, что при определении расположения устройство будет использовать GPS и, следовательно, его энергопотребление возрастет. В этом фрагменте кода показано, как создать LocationRequest для расположения с высокой точностью и примерно каждые пять минут проверять наличие изменений расположения, отправляя запросы не чаще чем раз в две минуты. Fused Location Provider будет использовать LocationRequest , чтобы определять, какой поставщик сведений о расположении использовать при попытке определить расположение устройства.
Android.Gms.Location.LocationCallback — Для получения обновлений местоположения приложение Xamarin. Android должно подделать подкласс LocationProvider абстрактному классу. Этот класс предоставлял два метода, которые могут быть вызваны Fused Location Provider для передачи в приложение обновленных сведений о расположении. Это будет подробнее рассмотрено ниже.
Чтобы уведомить приложение Xamarin.Android об изменении расположения, Fused Location Provider вызовет LocationCallBack.OnLocationResult(LocationResult result) . Параметр Android.Gms.Location.LocationResult будет содержать сведения об изменении расположения.
Когда Fused Location Provider обнаруживает изменение доступности данных о расположении, он вызывает метод LocationProvider.OnLocationAvailability(LocationAvailability locationAvailability) . Если свойство LocationAvailability.IsLocationAvailable возвращает true , то можно предположить, что результаты обнаружения расположения устройства, переданные OnLocationResult , являются точными и актуальными, что соответствует требованиям LocationRequest . Если IsLocationAvailable имеет значение false, то OnLocationResult не будет возвращать результаты поиска.
Этот фрагмент кода является примером реализации объекта LocationCallback .
Использование API службы расположения Android
Служба расположения Android — это более старый API для работы со сведениями о расположении в Android. Данные о расположении собираются аппаратными датчиками и передаются в системную службу, к которой можно обращаться в приложении с помощью класса LocationManager и интерфейса ILocationListener .
Служба расположения лучше всего подходит для приложений, работающих на устройствах, на которых не установлены Сервисы Google Play.
Служба расположения — это особый тип службы, управляемой системой. Системная служба взаимодействует с оборудованием устройства и работает непрерывно. Чтобы использовать данные об изменении расположения в нашем приложении, мы подпишемся на эти данные из системной службы расположения, используя LocationManager и вызов RequestLocationUpdates .
Чтобы получить расположение пользователя с помощью службы расположения Android, требуется выполнить несколько действий.
- Получите ссылку на службу LocationManager .
- Реализуйте интерфейс ILocationListener и обрабатывайте события при изменении расположения.
- Используйте LocationManager , чтобы запрашивать данные об изменении расположения для указанного поставщика. ILocationListener из предыдущего шага будет использоваться для получения обратных вызовов от LocationManager .
- Прекратите получение данных об изменении расположения, когда они перестанут быть нужны приложению.
Диспетчер расположения
Можно получить доступ к системной службе расположения с помощью экземпляра класса LocationManager . LocationManager — это специальный класс, который позволяет взаимодействовать с системной службой расположения и вызывать методы для нее. Приложение может получить ссылку на LocationManager , вызвав GetSystemService и передав тип службы, как показано ниже.
OnCreate удобно использовать для получения ссылки на LocationManager . Рекомендуется задать LocationManager в качестве переменной класса, чтобы мы могли вызвать ее в различных точках жизненного цикла действия.
Запрос данных об изменении расположения из LocationManager
Когда приложение получит ссылку на LocationManager , ему нужно указать LocationManager требуемый тип сведений о расположении и частоту обновления данных. Для этого вызовите RequestLocationUpdates для объекта LocationManager и передайте в него какие-либо критерии для данных об изменении и обратный вызов для получения данных об изменении расположения. Этот обратный вызов является типом, который должен реализовывать интерфейс ILocationListener (более подробно это описывается далее в этом разделе).
Метод RequestLocationUpdates сообщает системной службе расположения, что приложение должно начать получать данные об изменении расположения. Этот метод позволяет указать поставщик, а также пороги времени и расстояния для управления частотой обновления. Например, приведенный ниже метод запрашивает данные об изменении расположения от поставщика сведений о расположении GPS каждые 2000 миллисекунд и только при изменении расположения более чем на 1 метр.
Приложение должно запрашивать данные об изменении расположения только так часто, как это необходимо для его эффективной работы. Это увеличивает время работы аккумулятора и повышает удобство работы пользователя.
Реагирование на данные об изменении расположения из LocationManager
После того как приложение запросило данные об изменении из LocationManager , оно может получить сведения от службы, реализовав интерфейс ILocationListener . Этот интерфейс предоставляет четыре метода для ожидания передачи данных службы расположения и поставщика сведений о расположении, OnLocationChanged . Система будет вызывать OnLocationChanged , когда расположение пользователя изменится настолько, чтобы соответствовать критериям изменения, заданным при запросе данных об изменении расположения.
В следующем коде показаны методы в ILocationListener интерфейсе:
Отмена подписки на данные об изменении из LocationManager
Чтобы обеспечить экономию системных ресурсов, приложение должно как можно скорее отменить подписку на данные об изменении расположения. Метод RemoveUpdates указывает LocationManager остановить отправку данных об изменении в наше приложение. Например, действие может вызвать RemoveUpdates в OnPause методе, чтобы мы смогли экономить электроэнергию, если приложение не нуждается в обновлениях расположения, пока его действие не находится на экране.
Если приложению необходимо получать данные об изменении расположения в фоновом режиме, необходимо создать пользовательскую службу, которая подписывается на системную службу расположения. Дополнительные сведения см. в руководстве по использованию фонового режима для служб Android.
Определение лучшего поставщика сведений о расположении для LocationManager
Приведенное выше приложение задает поставщик сведений о расположении GPS. Однако использовать GPS не всегда возможно. Например, устройство может находиться в помещении или не обладать приемником GPS. В этом случае при запросе поставщика возвращается значение null .
Чтобы приложение работало, когда использование GPS невозможно, добавьте метод GetBestProvider , чтобы при запуске приложения запросить наилучший доступный поставщик сведений о расположении (поддерживаемый устройством и подходящий для пользователя). Вместо передачи конкретного поставщика с помощью объекта GetBestProvider можно указать GetBestProvider требования к поставщику, такие как точность и энергопотребление. GetBestProvider возвращает наиболее подходящий поставщик для заданных критериев.
В следующем коде показано, как получить наилучший доступный поставщик и использовать его при запросе данных об изменении расположения.
Если пользователь отключил все поставщики сведений о расположении, GetBestProvider вернет значение null . чтобы увидеть, как этот код работает на реальном устройстве, обязательно включите GPS, Wi-Fi и сотовые сети в > режиме расположения Google Параметры , как показано на следующем снимке экрана:
На следующем снимке экрана показано приложение определения расположения, использующее GetBestProvider .
Помните, что GetBestProvider не изменяет поставщик динамически. Вместо этого он один раз за жизненный цикл действия определяет наилучший доступный поставщик. Если состояние поставщика изменяется после его установки, приложению потребуется дополнительный код в ILocationListener методах — OnProviderEnabled , OnProviderDisabled и OnStatusChanged – для всех возможных вариантов, связанных с переключателем поставщика.
Сводка
В этом разделе описано получение расположения пользователя с помощью службы расположения Android и Fused Location Provider из API служб расположения Google.
Источник