- Google MAPs API в android или как работать с картами быстрее
- Принцип работы Google MAPs API
- А как вообще работать с этой страшной штукой?
- Подключение библиотеки
- Встраиваем карту в приложение
- Пишем всякие интересности
- Работа с интерфейсом в Google Maps SDK для Android
- Полный список
- API ключ
- Google Play services
- Настройка проекта
- Карта
- Управление
- Камера
Google MAPs API в android или как работать с картами быстрее
Принцип работы Google MAPs API
Вся документация для работы с картами приведена на (логично) официальном сайте google maps api. Сегодня я рассматриваю только Directions API (документация). Для того что бы получить какую-либо информацию от большого числа, вам необходимо сделать запрос. Ответ прийдет в формате JSON.
Общий вид запроса:
Пример: https://maps.googleapis.com/maps/api/directions/json?origin=55.754724,%2037.621380&destination=55.728466,%2037.604155&key=»Your MAPs API key»
В качестве ответа нам (ожидаемо) пришел JSON с большим набором разных точек с координатами и названиями этих мест.
А как вообще работать с этой страшной штукой?
Если вы только начинаете работать с Android, то советую вам почитать про такую замечательную библиотеку Retrofit, которая превращает работу с запросами в код из 2 строк. Рассматривать сейчас я её не буду.
Но я сегодня хочу рассмотреть пример использования библиотеки Java Client for Google Maps Services. Библиотека как по мне замечательная, освобождает от необходимости писать (пусть даже очень короткие) запросы вручную и отлично подходит в случаях когда нужно писать очень быстро, как например на хакатоне. Я хочу показать живой пример использования данной библиотеки на примере работы с Directions API.
Подключение библиотеки
Для начала нам потребуется получить ключ для нашего приложения. Топаем на оф. сайт, находим сверху кнопку «получить ключ», создаем новый проект, нажимаем далее и готово!
UPD: теперь бесплатно получить нельзя. С лета 2018 года Google обновили план и необходимо ввести данные своей карты для получения 200$ для запросов каждый месяц бесплатно. Этого должно хватать, но конечно тенденция не радует.
Firebase
Для правильной работы приложения нам необходимо получить файл google-service.json. Идем на firebase выбираем наш проект и добавляем его. Далее нам нужно выбрать Android проект, ввести название пакета, регистрируем приложение. Скачиваем файл и перетаскиваем в папку app. К слову её не будет видно в дереве проекта, для этого надо в Android Studio поменять отображение с Android на Project или залезть в наш проект через файловый менеджер. Далее следуем инструкциям где какой код писать.
Включаем в консоли
Так же нам необходимо включить Directions API (или любую другую необходимую вам API) в консоли, для этого идем сюда, выбираем наше приложение и включаем Directions API.
Gradle
В Gradle файлы так же необходимо добавить еще пару строк. В итоге новые строки выглядят вот так:
Обязательно проверяйте, актуальная ли это сейчас версия!
Встраиваем карту в приложение
Google map в андроид реализовывается как фрагмент (или как MapView, но об этом в другой раз, нам сейчас особой разницы нет). Просто встраиваем его в наш layout. В нашем классе, который работает с картой, необходимо найти эту карту и заимплементить интерфейс.
Код для фрагмента выглядит вот так. Я буду работать с MainActivity, соответственно если вы используете другой класс вам необходимо поменять контекст.
Отлично, фрагмент встроили, Android Studio на нас не ругается, едем дальше. Переходим в MainActivity.class и имплементим интерфейс OnMapReadyCallback.
В onCreate пишем
Так же идем в Manifests и прописываем вот такие штуки внутри тэга application
Где вместо @string/google_maps_key должен подставиться ваш ключ для карт, который мы получили ранее. Соответственно вам нужно создать нужный ресурс в файле string.
Пишем всякие интересности
Отлично, карта у нас есть, давайте наконец напишем хоть что-нибудь интересное. Пусть нашей целью будет нарисовать маршрут по Москве через несколько точек:
- Гум (55.754724, 37.621380)
- Большой театр (55.760133, 37.618697)
- Патриаршие пруды (55.764753, 37.591313)
- Парк культуры (55.728466, 37.604155)
Кладу все наши места в List и делаю это как глобальную переменную.
Для начала создадим по маркеру на каждое место. Маркер это просто объект, которому передаются координаты, а затем они накладываются на карту. Код:
Далее мы пишем вот такой код все в том же методе onMapReady
При запуске приложения мы получили вот такую картину:
Хм, Москва, конечно, весьма запутанная, но не настолько же. Почему же такой странный маршрут нам вернул Google? Потому что он построил маршрут для автомобилей, который идет по умолчанию, но мы можем это изменить. Чтобы построить маршрут для пешеходов, меняем код на:
Теперь наш маршрут выглядит вот так
Существует еще множество настроек, о всех них можно прочитать в документации. Просто мы все параметры будем добавлять не в сырой запрос, а в код, поскольку методы библиотеки имеют те же названия что и просто в запросах.
Источник
Работа с интерфейсом в Google Maps SDK для Android
Данная статья будет полезна тем, кто ранее не использовал в своей работе Google Maps SDK.
Под катом описаны основные приемы работы с картой, такие как добавление и управление маркерами, способы перемещения камеры над картой, управление зумом, построение маршрута и геокодинг. А так же ограничения и способы их обхода.
Источник
На написание статьи меня сподвиг собственный опыт, который я извлек при написании приложения для курьеров использующего в своей работе гугл карты. Так что все скриншоты и возможное упоминание бизнес логики будут происходить в контексте построения интерфейса курьера.
К сожалению Google Maps SDK for Android не позволяет изменять положение кнопок управления, т.н. UI controls, к ним относятся: IndoorLevelPicker — показ поэтажного плана строений, Compass — компас, My Location button — перейти на карте к текущему местоположению, Map toolbar — кнопи построения маршрута и открытия карты, а так же ZoomControls — увеличения и уменьшения маштаба карты.
На примере Map toolbar и ZoomControls посмотрим какие сложности могут возникнуть из-за невозможности сменить положение контролов и как это обойти.
Проблемы с отображением UI controls из SDK (выделено оранжевым) и их кастомные аналоги (выделено зеленым)
В данном случае у нас в правом нижнем углу расположена кнопка (floating action button) перехода к списку адресов заказов на доставку, на картинке слева видно, что ZoomControls оказались под ней и практически недоступны для нажатия. На картинке справа, при нажатии на маркер, появляются кнопки из Map toolbar, они так же оказались под кнопкой перехода к списку заказов.
Первое что нам необходимо сделать — это скрыть отображение оригинальных кнопок. Сделать это можно переопределив метод onMapReady, он вызывается в тот момент, когда карта готова к использованию.
Добавляем в верстку фрагмента нужные кнопки, там где они должны быть в соответствии с нашим дизайном:
Расположение кастомных кнопок управления картой
Затем в методе onCreateView указываем действия, которые должны произойти при нажатии на наши кнопки:
Особенность метода animateCamera в том, что маштаб изменяется плавно, а не мгновенно и если нужно, например, отключить анимацию конкретной кнопки зума, по достижению максимального или минимального маштаба, то для этого нужно переопределить метод onCameraIdle, который вызывается в момент прекращения изменения маштаба карты.
Что бы выполнить какое либо действие с маркером(кроме перетаскивания), например, создать новый заказ, удалить случайно поставленный маркер, перейти в уже существующий заказ или позвонить по телефону казанному в заказе добавляем в верстку соответствующие кнопки управления и прописываем их обработчики.
Кнопки управления маркером
Еще одна особенность, это то что в SDK нет кнопки для удаления поставленного на карту маркера. Для этого тоже делаем свою кнопку:
При нажатии на маркер открывается его заголовок, нажатие на который так же можно использовать для совершения какого либо действия, я при нажатии на заголовок нового маркера создаю новый заказ на доставку курьеру, а на маркер уже существующего заказа — открываю подробную информацию о доставке, включающюю перечень товаров.
Процесс вывода нескольких маркеров (считай списка заказов) на карту ничем принципиально не отличается от вывода одного маркера. Маркер состоит из координат (position), заголовка (title), мелкого текста под заголовком (snippet) и тэга (setTag) — его можно использовать для идентификации множества маркеров на карте.
Несколько маркеров на карте
Пара слов о геокодере
Геокодер используется для получения адреса, на основании координат. Поставив маркер на карте и нажав кнопку добавить заказ, мы получаем географические координаты нужной точки, т.е. широту и долготу. Но для удобства пользователя неплохо будет показать адрес в человекочитаемом виде, т.е., например, страна, город, улица, дом.
Google Maps SDK содержит класс Geocoder, вызвав его метод getFromLocation можно получить массив адресов по указанным координатам.
Для того, что бы не блокировать UI thread долгими, особенно если медленный или недоступный интернет, вызовами — будем использовать RxJava:
Полученный адрес точки на карте на основании географических координат
Источник
Полный список
— создаем приложение с картой
— настраиваем карту и обрабатываем ее события
— программно меняем положение камеры
После темы получения координат вполне логично будет рассмотреть тему гуглокарт. Тема несложная и не особо большая, нам хватит пару уроков, чтобы ее рассмотреть.
Но перед тем, как начать творить и созидать, нам надо будет сделать две вещи.
1) В гугл-консоли включить службу карт и получить API-ключ для работы
2) Обеспечить доступ проекта к Google Play services
API ключ
Начнем с первого пункта. Для этого нам надо зайти в Google APIs Console.
Если у вас нет проекта, гугл предложит его создать.
Жмем Create project…
Проект создан. Слева выбираем Services и открывается список служб.
В этом списке ищем Google Maps Android API v2
Жмем на тумблер включения (OFF), принимаем соглашение и снова попадаем в список служб.
Но теперь служба должна быть включена
Все ок. Теперь идем за ключом.
Для этого слева сверху выбираем API Access и открывается такой экран.
На нем жмем кнопку Create new Android key и от нас требуют ввести SHA1-значение ключа, которым будет подписано приложение.
И даже дают инструкции, как это сделать с помощью утилиты keytool
Если вообще непонятно о чем речь, рекомендую прочесть Урок 123. Там я все подробно описал.
Но последние версии Eclipse позволяют получить SHA1 без всяких команд, достаточно зайти в настройки и там есть вся инфа
Берем содержимое поля SHA1 fingerprint
К нему через точку с запятой дописываем пакет приложения (в этом уроке это будет ru.startandroid.develop.p1391googlemaps), вставляем в поле и жмем Create.
Появился нужный нам ключ — строка API key.
Не закрывайте пока эту страницу, скоро этот созданный ключ нам понадобится при создании приложения.
Не забывайте проделать эти же манипуляции, когда будете подписывать приложение для публикации на маркете другим ключом.
Google Play services
Теперь второй пункт. Для работы с картой нам понадобится Google Play services.
Открываем SDK Manager и ищем там Extras > Google Play services (если планируете поддержку Android 2.2, то Google Play services for Froyo). Если еще не установлено, то устанавливайте.
Исходники из папки google-play-services_lib надо будет импортнуть в Workspace. Для этого в меню Eclipse жмем File > Import, выбираем Android > Existing Android Code into Workspace, находим google-play-services_lib папку, ставим галку, чтобы импорт был выполнен путем копирования (Copy projects into workspace) и жмем Finish.
Проект google-play-services_lib должен появиться в вашем Workspace
Предварительная подготовка завершена, можем создавать проект.
Project name: P1391_GoogleMaps
Build Target: Android 2.3.3
Application name: GoogleMaps
Package name: ru.startandroid.develop.p1391googlemaps
Create Activity: MainActivity
Настройка проекта
Теперь еще немного возни с проектом.
Заходим в свойства проекта и добавляем (кнопкой Add) ссылку на ранее импортированный google-play-services_lib проект.
В манифесте необходимо добавить следующее в тег application:
Первые данные, это наш ключ из гугл-консоли. Здесь вам надо в android:value поставить ваше значение API key, которое вы чуть ранее получили и оставили открытым в браузере. Этот ключ нужен, чтобы карта работала.
Вторые данные – это версия Google Play services. Думаю, что эта инфа о версии нужна, чтобы карта четко понимала, как и что ей доступно из этих сервисов.
Также, в манифесте в тег manifest нам надо добавить следующие разрешения:
Это доступ в инет, проверка доступности инета, сохранение кэша карт и доступ к гугл-веб-сервисам.
Если думаете работать с определением местоположения, то не забывайте про:
И туда же, в тег manifest такое требование:
Гугл-карты используют OpenGL ES версии 2. На девайсах, которые это не поддерживают, карта просто не отобразится. Поэтому ставим ограничение.
Теперь все. Далее продолжаем работу, как с обычным проектом.
В strings.xml добавим строки:
Кнопка и фрагмент-карта
В onCreate мы находим наш фрагмент с картой и получаем от него объект GoogleMap методом getMap. Учитывайте, что этот метод может вернуть null.
Кстати, в onCreate можно также повесить проверку, что на устройстве доступно Google Play services. Для этого надо вызвать метод isGooglePlayServicesAvailable() и он должен вернуть SUCCESS. Подробности в хелпе.
Метод init пока пустой.
В onClickTest мы устанавливаем тип карты методом setMapType
Всего существует 5 типов:
MAP_TYPE_NONE – карта не будет отображаться
MAP_TYPE_NORMAL – обычный режим, в нем карта стартует по умолчанию.
MAP_TYPE_TERRAIN – карта рельефа местности
MAP_TYPE_HYBRID – снимки со спутника + инфа о улицах и транспорте
Получить текущий тип можно методом getMapType.
Я буду проводить все тесты на реальном устройстве, т.к. эмуляторы по умолчанию не поддерживают Google Play services. Но если очень надо, то можно и на эмуляторе запустить после некоторых манипуляций. Об этом написано, например, здесь. Надо скачать два APK-файла и установить их на эмулятор.
Карта
Все сохраняем, запускаем приложение и видим карту в обычном режиме.
У меня при первом запуске карта была не видна, но были видны кнопки управления масштабом. В логах был такой текст: Failed to load map. Error contacting Google servers. This is probably an authentication issue (but could be due to network errors). В этом случае убедитесь, что все верно сделано с получением ключа. Если проблема остается, то удалите приложение с устройства, сделайте в Eclipse очистку проекта (меню Project > Clean) и снова установите приложение — мне помогло.
Теперь карта отображает снимки со спутника
Посмотрим, что еще можно сделать с картой.
В обычном режиме карта умеет показывать даже схему этажей здания, если очень приблизиться зумом к этому зданию.
Вот, например схема 0-го этажа аэропорта Барселоны. Справа видно переключатель этажей.
Мы можем отключить программно эту возможность методом setIndoorEnabled.
Метод setBuildingsEnabled управляет отображением 3D зданий.
Управление
Управление картой жестами и кнопками также поддается настройке. Для этого необходимо вызвать метод getUiSettings и мы получим объект настроек интерфейса UiSettings.
У него куча методов, которые что-либо включают/выключают:
setMyLocationButtonEnabled – кнопка текущего местоположения (необходимо включить определение, метод setMyLocationEnabled(true))
У этих методов есть аналоги, которые начинаются с is вместо set и позволяют получить текущие значения.
На карту можно вешать слушателей. Перепишем метод init:
setOnMapClickListener вешает слушателя OnMapClickListener. Его метод onMapClick сработает при клике на карту и вернет объект LatLng с координатами (latitude, longitude), где было нажатие.
setOnMapLongClickListener вешает слушателя OnMapLongClickListener. Его метод onMapLongClick сработает при длительном нажатии на карту и вернет объект LatLng с координатами (latitude, longitude), где было нажатие.
setOnCameraChangeListener вешает слушателя OnCameraChangeListener. Его метод onCameraChange сработает при смене позиции камеры, т.е. при пролистывании карты, и вернет объект CameraPosition, который содержит информацию о текущем положении камеры.
CameraPosition имеет атрибуты:
— target, тип LatLng с полями-координатами: latitude, longitude. Это точка, на которую смотрит камера.
— bearing, угол поворота камеры от севера по часовой
— tilt, угол наклона камеры
— zoom, текущий уровень зума
Все сохраним, запустим приложение. Попробуйте выполнять короткие и длинные нажатия, вращать карту, перемещать ее, менять угол наклона: в логах будет выводиться вся инфа по этим операциям.
Камера
Теперь рассмотрим возможности программного изменения положения камеры.
Для этого нам необходимо будет создавать объект CameraUpdate и передавать его в один из методов:
animateCamera(CameraUpdate update, GoogleMap.CancelableCallback callback) – плавное перемещение и возможность указать слушателя CancelableCallback, который оповестит, что перемещение завершено (метод onFinish), либо прервано (метод onCancel).
animateCamera(CameraUpdate update, int durationMs, GoogleMap.CancelableCallback callback) – плавное перемещение, слушатель CancelableCallback и возможность указать время длительности перемещения в миллисекундах
Остается узнать, как получить объект CameraUpdate, который будет содержать информацию о перемещении камеры. Для этого используется CameraUpdateFactory.
Пойдем по порядку методов в хелпе.
newCameraPosition (CameraPosition cameraPosition) – созданный объект CameraUpdate будет содержать данные по перемещению камеры в указанную позицию с указанными настройками.
Тут снова появляется объект CameraPosition, все параметры которого мы уже чуть ранее рассмотрели при разговоре о событии смены камеры и который содержит всю инфу о положении камеры
Чтобы создать CameraPosition, используем CameraPosition.Builder. Перепишем метод onClickTest:
Создаем CameraPosition, указываем координаты (-27,133), зум (5 уровень), поворот карты (45 градусов), угол наклона (20 градусов). И передаем полученный объект в метод newCameraPosition, получая CameraUpdate, который в свою очередь передаем в метод animateCamera.
Все сохраним, запустим, жмем Test и наблюдаем плавное перемещение к Австралии. В процессе перемещения меняется уровень зума, угол наклона и поворот камеры.
newLatLng (LatLng latLng) — перемещение камеры к указанной точке.
Тут все просто. Перепишем метод onClickTest:
По нажатию на Test камера переместится в указанную точку.
newLatLngBounds (LatLngBounds bounds, int padding) – камера покажет указанную область с учетом отступа
Перепишем метод onClickTest:
Для указания области используется объект LatLngBounds, который создается из двух точек LatLng. Эти две точки будут являться левой нижней (югозападной) и верхней правой (северовосточной) точками созданной области.
Параметр padding это отступ (в пикселах) от краев экрана. Т.е., если указать ненулевой padding, то камера покажет указанную область карты не в весь экран, а с учетом этого отступа.
По нажатию на Test камера покажет Австралию с отступом в 100 пикселов от краев экрана.
newLatLngBounds (LatLngBounds bounds, int width, int height, int padding) – аналогичен предыдущему, но можно указать размеры прямоугольника на экране, в который будет помещена показанная область и отступ будет действовать внутри этой области.
newLatLngZoom (LatLng latLng, float zoom) – переместит камеру в указанную точку с указанным уровнем зума
scrollBy (float xPixel, float yPixel) – перемещение камеры на указанное кол-во пикселов
zoomBy (float amount) – изменение текущего уровня зума на указанное кол-во (если положительное — то приближение, если отрицательное — удаление).
zoomBy (float amount, Point focus) – смена текущего зума на указанное кол-во уровней, и применение итогового уровня к указанной точке на экране
zoomIn/zoomOut – увеличение/уменьшение уровня зума на единицу
zoomTo (float zoom) – установка указанного уровня зума
Объект GoogleMap имеет метод setPadding. Он устанавливает отступы от краев экрана. Это влияет на положение стандартных элементов управления карты, а также камера теперь будет считать центром карты эту новую ограниченную область и позиционироваться там.
На следующем уроке:
— размещаем на карте свои объекты
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник