Недавно довелось перевести приложение с использования Google Maps API v1 на Yandex MapKit.
По субъективному мнению большинства Yandex карты для России имеют более высокую детализацию, и поэтому, если ваше приложение ориентировано только на Росиию или ex-USSR и Турцию (в общем на те страны где Yandex есть), то имеет смысл рассмотреть возможность использования MapKit'а.
Приложение имеет следующую функциональность: карта с точками объектов на ней и возможностью поиска этих точек по адресу, отображением текущего местоположения и зумом. По каждой точке можно тапнуть и увидеть всплывающий баллун, содержащий дополнительную информацию о точке. При тапе на отдельном баллуне открывается новая активити с детальной информацией о данной точке и куском карты, отображающим только одну эту единственную точку.
Начнем… Идем на github и забираем оттуда библиотеку. Если вы подумали, что раз библиотека распространяется через GitHub, то она OpenSource, то тут вас ждет разочарование. Библиотека распространяется как
Кстати не пугайтесь обилия открытых задач на гитхабе. Это не обязательно баги — это такой способ задать вопрос в комьюнити по использованию библиотеки. Какого-нибдуь форума или отдельно выделенного места для подобных вопросов не существует. Есть вопрос? Создай issue!
Для получения ключа необходимо отправить запрос в тех. поддержку яндекса, а до тех пор пока его нам не выдали, в качестве
Итак, после получения либы, первым делом решено было собрать sample-project и поиграть с ним. В репозитории лежат файлики Eclipse проекта, я же использую IntelliJ IDEA, поэтому первым делом необходимо было создать и настроить проект из существующих исходников. Здесь поджидал сюрприз — я досих пор так и не понял до конца в чем было дело, но ситуация была следующая: проект нормально компилировался и упаковывался в
Казалось бы, обе библиотеки имеют схожее API и переход не должен отнять слишком много времени: и там и там
В Google Maps баллун (сплывающее вью при тапе по точке) один элемент вместе с самой точкой, в MapKit'е — это отдельный объект. Поэтому логику работы баллунами придется переписать почти полностью.
В Google API
Еще одной сложностью стало непредсказуемое поведение
Ну и напоследок еще одно значительное отличие Yandex MapKit от Google Maps это то, что MapKit не поддерживает прямой геокодинг, только обратный. Т.е. библиотека предоставляет способ преобразовать географичиеские координаты (lat/long) в адрес или название места (см. класс
В заключение хотелось бы сказать, что в целом, впечатление от использования Yandex Maps положительные, API достаточно удобное, возможностей для моих задач оказалось достаточно, но основной минус — документация. Будем надеятся, что Яндекс все-таки приведет все в порядок.
По субъективному мнению большинства 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 достаточно удобное, возможностей для моих задач оказалось достаточно, но основной минус — документация. Будем надеятся, что Яндекс все-таки приведет все в порядок.