Полный список
— получаем данные о местоположении
Android устройства могут предоставить нам данные по нашему текущему местоположению. Это, конечно, очень удобно и вовсю используется для, например, пользования картой, получения актуальной для вашей местности информации (прогноз погоды), всевозможных чекинов и пр.
Реализация этого всего вполне проста. Мы вешаем слушателя на провайдера и получаем данные. На данный момент есть два провайдера: GPS и Network.
GPS – тут все понятно, это данные с GPS-спутников.
Network – это координаты, которые можно получить через сотовую связь или WiFi. Для этого провайдера нужен инет.
Напишем простое приложение, которое будет запрашивать и отображать координаты.
Project name: P1381_Location
Build Target: Android 2.3.3
Application name: Location
Package name: ru.startandroid.develop.p1381location
Create Activity: MainActivity
В strings.xml добавим строки:
Несколько TextView, в которые мы будем выводить данные, и кнопка для открытия настроек местоположения.
В onCreate определяем TextView-компоненты и получаем LocationManager, через который и будем работать.
В onResume вешаем слушателя с помощью метода requestLocationUpdates. На вход передаем:
— тип провайдера: GPS_PROVIDER или NETWORK_PROVIDER
— минимальное время (в миллисекундах) между получением данных. Я укажу здесь 10 секунд, мне этого вполне хватит. Если хотите получать координаты без задержек – передавайте 0. Но учитывайте, что это только минимальное время. Реальное ожидание может быть дольше.
— минимальное расстояние (в метрах). Т.е. если ваше местоположение изменилось на указанное кол-во метров, то вам придут новые координаты.
— слушатель, объект locationListener, который рассмотрим ниже
Также здесь обновляем на экране инфу о включенности провайдеров.
В onPause отключаем слушателя методом removeUpdates.
locationListener – слушатель, реализует интерфейс LocationListener с методами:
onLocationChanged – новые данные о местоположении, объект Location. Здесь мы вызываем свой метод showLocation, который на экране отобразит данные о местоположении.
onProviderDisabled – указанный провайдер был отключен юзером. В этом методе вызываем свой метод checkEnabled, который на экране обновит текущие статусы провайдеров.
onProviderEnabled – указанный провайдер был включен юзером. Тут также вызываем checkEnabled. Далее методом getLastKnownLocation (он может вернуть null) запрашиваем последнее доступное местоположение от включенного провайдера и отображаем его. Оно может быть вполне актуальным, если вы до этого использовали какое-либо приложение с определением местоположения.
onStatusChanged – изменился статус указанного провайдера. В поле status могут быть значения OUT_OF_SERVICE (данные будут недоступны долгое время), TEMPORARILY_UNAVAILABLE (данные временно недоступны), AVAILABLE (все ок, данные доступны). В этом методе мы просто выводим новый статус на экран.
Провайдеры включаются и отключаются в настройках системы. Тем самым, просто определяется доступен ли провайдер для получения от него координат. Чуть позже увидим, как можно отправить юзера в эти настройки. Программное включение/выключение провайдеров через стандартные методы недоступно.
Далее идут свои методы.
showLocation на вход берет Location, определяет его провайдера методом getProvider и отображает координаты в соответствующем текстовом поле.
formatLocation на вход берет Location, читает из него данные и форматирует из них строку. Какие данные он берет: getLatitude – широта, getLongitude – долгота, getTime – время определения.
checkEnabled определяет включены или выключены провайдеры методом isProviderEnabled и отображает эту инфу на экране.
Метод onClickLocationSettings срабатывает по нажатию кнопки Location settings и открывает настройки, чтобы пользователь мог включить или выключить провайдер. Для этого используется Intent с action = ACTION_LOCATION_SOURCE_SETTINGS.
Осталось в манифесте прописать разрешение на определение координат — ACCESS_FINE_LOCATION, которое позволит нам использовать и Network и GPS. Также существует разрешение ACCESS_COARSE_LOCATION, но оно дает доступ только к Network-провайдеру.
С кодом все, давайте смотреть, что получилось. Все сохраняем и запускаем приложение.
У меня на планшете сейчас выключен GPS, выключен WiFi, вставлена симка и выключен мобильный интернет.
Запускаю приложение и вижу такую картину:
GPS выключен, Network включен. Но инета нет, поэтому Network мне ничего не дает. Надо включить либо мобильный инет, либо WiFi.
Я включаю WiFi. Проходит секунд 15-20 и инфа с Network пошла
Видим широту, долготу и время.
Напомню, что мы ставили минимальную скорость обновления – 10 сек. Но у меня провайдер Network выдает данные не чаще, чем раз в минуту.
Теперь давайте включим GPS. Для этого мы специально повесили кнопку Location settings, которую надо будет нажать пользователю, чтобы перейти в настройки. Жмем кнопку.
Видим, что GPS выключен, а Network включен. Наше приложение показывало все верно.
Разумеется, GPS можно включать и выключать через быстрые настройки системы (справа сверху). Но не все пользователи об этом знают. А тут мы их точно направим.
Включаем GPS и жмем Назад, чтобы вернуться в приложение.
GPS теперь показывает что он включен, ждем координаты. Для этого имеет смысл подойти к окну, больше вероятности, что поймаем сигнал.
В итоге сигнал пойман и получен результат.
У GPS через какое-то время включился статус 2 (AVAILABLE).
А у Network тишина со статусом. Не знаю, нормально это или нет.
Если с GPS сигналом все ок, то каждые 10 сек вы будете получать инфу о вашем местоположении. Если убрать планшет от окна, получим плохой сигнал: данные могут приходить реже и статус у меня иногда меняется на 1 (TEMPORARILY_UNAVAILABLE).
Прочее
Есть еще третий тип провайдера — PASSIVE_PROVIDER. Сам по себе этот провайдер никакие данные не вернет. Но повесив на него слушателя, вы сможете получать данные о местоположении, когда кто-то еще в системе пытается определить местоположение через обычные провайдеры. Система будет дублировать результаты и вам.
Метод getAllProviders вернет вам список всех доступных провайдеров. Метод getProviders(boolean enabledOnly) вернет либо все, либо только включенные.
Объект Location кроме координат, времени и провайдера имеет еще несколько атрибутов, которые могут прийти и пустыми:
getAccuracy – точность показания в метрах
getAltitude – высота над уровнем моря в метрах
getSpeed – скорость движения в м/с
getBearing – насколько я понял, это угол, на который текущая траектория движения отклоняется от траектории на север. Он же азимут.
Местоположение можно протестировать и через AVD эмулятор. Для этого надо в Eclipse открыть DDMS (Window > Open Perspective > DDMS) и выбрать вкладку Emulator Control. Внизу будет вкладка Manual, на которой есть поля для ввода координат и кнопка отправки.
На следующем уроке:
— создаем приложение с картой
— настраиваем карту и обрабатываем ее события
— программно меняем положение камеры
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Находки программиста
Решения конкретных задач программирования. Java, Android, JavaScript, Flex и прочее. Настройка софта под Linux, методики разработки и просто размышления.
воскресенье, 13 мая 2012 г.
Работа с GPS и Google Maps в Android
Продолжаем осваивать аппаратные возможности Android-смартфонов. В предыдущих постах мы изучили, как использовать в наших приложениях микрофон и камеру. Теперь возьмёмся за более сложную тему: GPS. Сложность, конечно же, относительная. В сети есть масса примеров кода, с помощью которого можно получить координаты клиента, поэтому чтобы сделать наш пример интереснее, соединим получение координат с их использованием. В этой статье вы узнаете как получить доступ к Google Maps API, отобразить карту с различными её «плюшками» и вывести на неё наши координаты, полученные различными способами: по спутникам, данным мобильной сети или wifi.
Итак, приступим:
Получаем ключ к Google Maps API
Чтобы иметь возможность использовать Google Maps в своём Android-приложении, нужно получить ключ. Ключ приложения генерируется на этой странице на основании сертификата, которым будет в дальнейшем подписано ваше приложение. Обычно готовое приложение подписывается отдельным сертификатом, а в процессе разработки используется другой из хранилища debug.keystore, которое находится в каталоге .android вашей домашней директории. В этом случае вам потребуется сгенерировать два ключа и не забыть заменить отладочный ключ на «боевой», перед финальной сборкой приложения. Для генерации ключа вам потребуется получить «сertificate fingerprint» командой
keytool -list -keystore
/.android/debug.keystore
Пароль от debug.keystore обычно — пустая строка.
Доступы и библиотеки
Google Maps API в состав Android SDK входит как отдельная библиотека, поэтому её нужно отдельно подключить в AndroidManifest.xml вашего приложения командой
Эта строка должна находиться внутри тега «application».
Также не забудем попросить разрешения на получение координат и доступ в интернет:
android.permission.ACCESS_FINE_LOCATION
android.permission.INTERNET
android.permission.ACCESS_WIFI_STATE
Последнее из разрешений, нужно нам для отслеживания состояния wifi-подключения. Это позволит нам выбрать подходящий способ получения приблизительных координат, пока наше устройство будет искать спутники и получать от них точные координаты.
Рисуем гуглокарту
Карту нам нарисует MapView, в конструктор которого мы передаём ключ, полученный на первом шаге. Сразу после создания желательно установить zoom level карты (1 — весь мир на экране, больше — детальнее) , а также методом setCenter(new GeoPoint(latitude, longitude)) спозиционировать карту куда-нибудь. Обе операции выполняем при помощи MapController-а, который получаем из экземпляра MapView методом getController(). Чтобы показать кнопки изменения масштаба вызовем метод setBuiltInZoomControls(true). И, главное, не забудьте сделать карту кликабельной методом setClickable(true).
Далее «вставляем» MapView в RelativeLayout вместе с остальными компонентами. В нашем случае это будет панель с двумя элементами управления: переключателем режима спутниковых фотографий и пиктограммой для возврата карты к текущему местоположению.
В целом картинка должна быть примерно такой, как на иллюстрации слева.
Все картинки возьмём из android.R.drawable, чтобы не морочить себе голову подготовкой своей графики.
Получаем текущие координаты
Вот мы и подошли к самому интересному. Весь код нашего приложения помещается в одном файле главного Activity:
Координаты текущего местоположения тут мы получаем дважды: перед отрисовкой карты (последние известные с прошлого поиска) и после обновления.
Первое получение координат мы делаем в методе getLastCopords(). Эта операция выполняется достаточно быстро, чтобы не тормозить нам построение интерфейса. Она может завершиться неудачно, и в этом случае мы устанавливаем карту в точку new GeoPoint(0, 0). В случае успеха устанавливаем карту в нужное место и устанавливаем маркер текущего местоположения методом map.getOverlays().add(new MarkerOverlay(p)).
Важно учесть, что в нашем устройстве есть три источника получения координат.
Первый: GPS — даёт самые точные координаты, но работает медленнее всех и может ничего не найти. Второй: сеть wifi — отвечает быстро, относительно точно и всегда, когда wifi вообще есть в наличии. Третий: (с версии Android 2.2): PASSIVE_PROVIDER — сигнал соты оператора. Даёт координаты с точностью до нескольких кварталов, медленно, но практически всегда. Для получения данных с прошлого поиска скорость не имеет значения, поэтому опрашиваем провайдеров по очереди, начиная с самого точного.
Чтобы обновить координаты, подписываемся на результат обновления лучшего в данный момент провайдера в методе requestNewCoordinates(). При этом проверяем, разрешено ли использование спутников (может быть выключено пользователем ради экономии заряда батареи), есть ли сеть wifi и т.п.
При запуске обновления передаём выбранному провайдеру экземпляр LocationListener-а, в методе onLocationChanged которого мы получим новые координаты, передвинем на них карту и поставим маркер.
При выходе из приложения (в onPause()) нужно не забыть остановить обновление координат у выбранного ранее провайдера методом removeUpdates(listener), чтобы не разряжать пользователю батарею напрасно.
Несколько слов о отладке «координатного» приложения. Есть одна проблема, которая может попить кровушки у вас при отладке приложения на реальном устройстве. Различные провайдеры могут не давать события locationChanged очень долго или совсем. Например, PASSIVE_PROVIDER у меня вернул координаты только при отключении и повторном включении передачи данных. Спутники вообще могут быть недоступны в помещении. Поэтому мой совет: выполняйте отладку на эмуляторе, а событие locationChanged тут можно вызвать очень просто:
path/to/android-sdk/platform-tools/adb emu geo fix -121.45356 46.51119
Эта команда в консоли переместит вас в уютное заснеженое ущелье где-то в северной америке 🙂
Источник