Переходим с Google Maps на Yandex MapKit

в 11:23, , рубрики: android, google maps api, Yandex Map Kit, метки: , ,

Недавно довелось перевести приложение с использования 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

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js