Недавно довелось перевести приложение с использования Google Maps API v1 на Yandex MapKit.
По субъективному мнению большинства Yandex карты для России имеют более высокую детализацию, и поэтому, если ваше приложение ориентировано только на Росиию или ex-USSR и Турцию (в общем на те страны где Yandex есть), то имеет смысл рассмотреть возможность использования MapKit'а.
Приложение имеет следующую функциональность: карта с точками объектов на ней и возможностью поиска этих точек по адресу, отображением текущего местоположения и зумом. По каждой точке можно тапнуть и увидеть всплывающий баллун, содержащий дополнительную информацию о точке. При тапе на отдельном баллуне открывается новая активити с детальной информацией о данной точке и куском карты, отображающим только одну эту единственную точку.
Начнем… Идем на github и забираем оттуда библиотеку. Если вы подумали, что раз библиотека распространяется через GitHub, то она OpenSource, то тут вас ждет разочарование. Библиотека распространяется как Android Library Project + jar-файл
с кучей обфусцированных классов, который лежит в папочке libs
. Исходников нет, таким образом, заглянуть внутрь и понять что как работает мы не можем, а порой очень хочется, т.к. документация (в папке с библиотекой есть javadoc
) мягко говоря плохая: описание существующего API минимально, а многие методы не документированы вообще. Поэтому лежащий по соседсвту с библиотекой sample проект очень пригодится.
Кстати не пугайтесь обилия открытых задач на гитхабе. Это не обязательно баги — это такой способ задать вопрос в комьюнити по использованию библиотеки. Какого-нибдуь форума или отдельно выделенного места для подобных вопросов не существует. Есть вопрос? Создай issue!
Для получения ключа необходимо отправить запрос в тех. поддержку яндекса, а до тех пор пока его нам не выдали, в качестве debug
-ключа можно использовать ключ вида 1234567890
(Спасибо sample-проекту, в документации об этом ни слова). К слову о ключах — здесь нас ожидает первый сюрприз: MapView
не читает ключ из файла ресурсов, поэтому если у вас есть несколько лейаутов, содержащих внутри MapView
, то ключ придется копировать в каждый из MapView
, вынести его в файл конфигурации и доступаться к нему через @string/api_key
не удастся. Эта загадка отняла у меня кучу времени, соответствующая задача была создана давным давно, но как видите за 3 месяца ситуация не изменилась. В общем, скорость реакции поддержки Yandex'а пугает.
Итак, после получения либы, первым делом решено было собрать sample-project и поиграть с ним. В репозитории лежат файлики Eclipse проекта, я же использую IntelliJ IDEA, поэтому первым делом необходимо было создать и настроить проект из существующих исходников. Здесь поджидал сюрприз — я досих пор так и не понял до конца в чем было дело, но ситуация была следующая: проект нормально компилировался и упаковывался в apk
, но затем в рантайме при попытке перехода на любую из активитей падал с ошибкой string resource not found
(дословный текст ошибки сейчас не помню). В файлах библиотеки лежит пустой R
-файл заглушка, рискну предпложить, что проблема была в том, что IDEA по каким-то причинам в финальный apk
-файл запаковывала именно его, что и приводило к дальнейшим ошибкам. Проблема решилась удалением из зависимостей sample-project модуля библиотеки и его повторным добавлением.
Казалось бы, обе библиотеки имеют схожее API и переход не должен отнять слишком много времени: и там и там MapView
, и там и там MapController
, и там и там GeoPoint
… Но на этом сходства заканчиваются. Несмотря на одинаковые имена классов методы называются по разному и не для каждого метода из Google API существует его прямой аналог из MapKit. Например, в MapKit'е остутствует метод, позволяющий получить координаты ViewPort
'а (видимой области карты), поэтому его придется реализовывать самостоятельно — через преобразование экранных (ScreenPoint
) координат в глобальные (GeoPoint
) — тыц. Экранные координаты нужно отсчитывать не относительно экрана, а относительно самого MapView
.
В Google Maps баллун (сплывающее вью при тапе по точке) один элемент вместе с самой точкой, в MapKit'е — это отдельный объект. Поэтому логику работы баллунами придется переписать почти полностью.
В Google API GeoPoint
хранит координаты в виде пары int
'ов — это longitude / latutude * 1E6
, у Yandex'а это double
longitude и latitude. С одной стороны, использование int
'ов вместо double
'ов позволяет сэкономить пару байт памяти и ускорить вычисления связанные с координатами (целочисленные операции всегда быстрее операций с плавающей точкой). С дургой стороны, это наводняет код конструкциями вида: *1E6
, /1E6
. В общем, здесь я ставлю плюсик Yandex'у, без постоянных умножений/делений на 1E6
с API работать удобнее, а соотношение удобства к выигришу в производительности, по-моему, в данной ситуации не велико.
Еще одной сложностью стало непредсказуемое поведение Balloon
'ов. Дело в том, что время от времени открываемые баллуны отображаются под другими OverlayItem
'ами и оказываются перекрытыми. При этом метод setPriority
, который есть у всех отображаемых на карте элементах никакого влияния не оказывает. Как выяснилось позже причина не правильного переопределения метода compareTo
. Данный метод используется при показе баллуна для сортировки объектов в z-плоскости. Ни документация, ни пример не содержат никакой информации о данной проблеме, данная зависимость вообще была установлена совершенно случайно в ходе экспериментов.
Ну и напоследок еще одно значительное отличие Yandex MapKit от Google Maps это то, что MapKit не поддерживает прямой геокодинг, только обратный. Т.е. библиотека предоставляет способ преобразовать географичиеские координаты (lat/long) в адрес или название места (см. класс GeoCode
). А вот в обратную сторону — улицу или город в координаты не умеет, поэтому прямой геокодинг придется реализовывать самостоятельно, например, с использованием того же Yandex Maps Web API. Google же умеет это делать сразу в обе стороны.
В заключение хотелось бы сказать, что в целом, впечатление от использования Yandex Maps положительные, API достаточно удобное, возможностей для моих задач оказалось достаточно, но основной минус — документация. Будем надеятся, что Яндекс все-таки приведет все в порядок.
Автор: TheDimasig