Документация TomTom
Технический контент из документации TomTom для разработчиков, создающих решения с использованием API, SDK и картографических технологий TomTom
09 сентября 2026 г.
мин чтения
Кейс по созданию панели инструкций по маршруту с использованием TomTom Maps and Navigation SDK для Android и Claude Code.
Предполагается базовое знакомство с Claude Code. Если вы новичок, начните с документации Anthropic по Claude Code.
Расширение чужого примера приложения может вызывать разочарование. Вы клонируете его, тратите часы на изучение кода, чтобы понять его недокументированные соглашения, разбираетесь, как он работает, и только потом можете приступить к добавлению собственной функции и расширению приложения.
Мы хотели выяснить, насколько сложно и сколько усилий требуется для добавления функции в пример приложения TomTom для Android, когда реализацией занимается ИИ-агент (пример приложения можно найти здесь: ссылка). Поэтому мы поручили Claude Code создать нашу собственную функцию, фиксируя каждую ловушку, с которой он сталкивался, в файле навыков (skill file).
Чтобы сделать этот эксперимент воспроизводимым, мы опубликовали промпт, CLAUDE.md и навык в этом репозитории. Мы запустили его с плагином Claude Code Superpowers от Джесси Винсента, который добавляет набор рабочих навыков поверх Claude Code. Все артефакты привязаны к конкретному коммиту приложения и версии SDK, использовавшимся во время разработки.
Кейс
Функция, которую мы пытаемся добавить, — это панель инструкций по маршруту (Route Instructions Panel), перетаскиваемая нижняя панель на экране предварительного просмотра маршрута, в которой перечислены все маневры, необходимые на запланированном пути. Нажмите на один из них, и камера карты переместится к месту, где требуется этот маневр, и установит булавку. Чтобы создать ее, агент должен: считать данные о маршруте из SDK, сопоставить каждую инструкцию с иконкой и фразой на естественном языке, а также создать пользовательскую нижнюю панель Compose для размещения и отображения всего этого.
Мы начали с написанного вручную prompt.md и сгенерированного CLAUDE.md. Мы уточнили промпт за несколько итераций, чтобы прояснить область применения и ожидаемый результат, а затем позволили Claude Code сделать первую попытку реализации. Мы не получили успешную сборку с первого раза, и потребовалось несколько проходов, чтобы добиться этого. После каждого прохода мы тестировали функцию вручную: перетаскивали панель, нажимали на маневры в списке, поворачивали устройство, выходили и снова заходили в предварительный просмотр маршрута.
Поскольку мы хотели сделать эксперимент воспроизводимым, мы дали указание агенту сохранять полученные знания и выявленные ловушки в навыке. Навык, который мы создали, аккумулировал то, на что мы тратили время: от ошибок компиляции и линтинга до проблем во время выполнения. Например, неожиданные типы данных в SDK, экспериментальные API Compose, которые компилируются, а затем вызывают сбой, пустые строки в списке маневров. Подробнее об этом ниже.
Панель инструкций по маршруту развернута в полноэкранный режим, отображая каждый маневр на выбранном маршруте. Выбор маневра центрирует карту на его местоположении и отображает маркер.
Интеграция SDK - Получение инструкций по маршруту и их сопоставление
Что изменил ИИ: панель инструкций по маршруту считывает четыре свойства из каждой инструкции и сопоставляет девять подтипов инструкций слоя маршрутизации — отправления, повороты, развилки, слияния, круговые развязки, съезды с шоссе, пункты оплаты, прибытия — с иконкой и фразой на естественном языке.
Что прошло гладко: получение данных из объекта маршрута SDK.
Это почти вся модель данных для панели: маршрут, его этапы, их инструкции. Тип маневра не является частью этой модели, он берется из подтипа инструкции. Преобразование каждого подтипа в иконку и фразу потребовало больше кода — специального файла сопоставления, — но ничего сложного в этом не было: поля каждого подтипа имеют строгую типизацию, и гадать не пришлось. Девять подтипов инструкций также не случайны: панель повторно использует существующее перечисление ManeuverType и иконки приложения, поэтому она охватывает именно те маневры, которые уже обрабатывались экраном навигации. Остальные подтипы используют нейтральную иконку и общую фразу.
Что было сложнее: несколько ловушек все же были связаны с SDK, в основном это были неожиданные типы данных. Road.name в маршрутизации возвращается как TextWithPhonetics?, а не String?. Пара типов маршрутизации находятся в пакетах, которые расположены не там, где вы ожидаете: пакет одного подтипа инструкции не совпадает с именем его класса, а вспомогательный тип данных находится вне пакета инструкций, вместе с которым он используется. Все это стало очевидным после идентификации, и теперь каждая такая проблема занесена в таблицу «подводных камней» в файле навыка.
Изменения в UI - Внедрение нижней панели Compose
Что изменил ИИ: каждый сценарий в приложении связывает держатель состояния с его UI на Compose, и все изменяемое состояние находится в одном общем MapScreenViewModel. Панель добавила три новых файла в существующий пакет routepreview и переписала файл UI этого пакета в пользовательскую нижнюю панель с возможностью перетаскивания и вложенной прокруткой, заменив нижнюю панель, которая была там раньше. Остальное было интегрировано через общие точки взаимодействия приложения: список инструкций как новый StateFlow в MapScreenViewModel, одно новое поле в MapScreenUiState для выбранной инструкции, отрисовка булавки этой инструкции в MapViewComponents и связка между ними в ScenarioHoldersFactory. Единственным изменением вне application/map стали два десятка новых строковых ресурсов для меток и описаний контента панели — согласно соглашению проекта, каждая видимая пользователю строка находится в strings.xml, ничего не захардкожено в Kotlin.
Это соглашение соблюдается для литералов, но не для грамматики: панель собирает каждую метку, вставляя название дороги в формат-обертку (route_instruction_onto — это «%1$s onto %2$s»), что закрепляет порядок слов английского языка. Промышленный код потребовал бы целых предложений для каждого маневра или форматов сообщений ICU, а также переводов, которые не включены в пример приложения. Это не относилось к тому, что мы тестировали, поэтому мы остановились на этом этапе.
Что прошло гладко: большая часть связки. Правило линтинга, обнаружившее неиспользуемый строковый ресурс, модификатор видимости, расширенный с private до internal для повторного использования сопоставления иконок маневров экрана навигации, отступы безопасной зоны, z-порядок для плавающих кнопок, которые перекрывает панель — обычная гигиена Android, никакой нестабильности SDK или Compose.
Что было сложнее: самый тяжелый узел трения пришелся на один аспект Compose. Чтобы создать нижнюю панель с перетаскиванием, Claude Code обратился к AnchoredDraggableState и anchoredDraggable — все еще ограниченным @OptIn(ExperimentalFoundationApi::class). Большинство сложных ловушек возникло именно там, включая ту, которая проявляется только во время выполнения: settle(velocity) компилируется чисто, только с предупреждением об устаревании, а затем вызывает сбой, как только его активирует жест прокрутки, что является частью изменений, описанных в собственном руководстве по миграции Android. В итоге панель также получила экспериментальный opt-in Material3 для своего маркера перетаскивания, а ближайшая стабильная альтернатива, BottomSheetScaffold от Material3, все еще не дает такого же сворачивания на частичную ширину и передачи вложенной прокрутки без дополнительных усилий. Поэтому мы все равно оставили экспериментальный API.
Эти подводные камни теперь отражены в таблице «Ловушки» (Gotchas) навыка: безопасная перегрузка settle и переименованные методы доступа к anchor. Это также содержит общий урок: проверяйте структуру экспериментального API на соответствие зафиксированной версии зависимости перед написанием кода, вместо того чтобы доверять фрагменту документации. Именно поэтому в последующих сессиях сбой не повторяется.
Хотя нам приходилось управлять Claude Code, большая часть наших вмешательств сегодня не потребовалась бы: Claude Code может самостоятельно обрабатывать результаты сборки и линтинга, а файл CLAUDE.md уже предписывает ему записывать каждую новую ловушку в навык перед завершением сессии. Тестирование на устройстве, где и проявились сбой и строки без иконок, потребовало нашего участия только потому, что мы не добавили инструментальные тесты для этого упражнения. При наличии UI-тестов или проверки скриншотов цикл замыкается без нашего участия.
Заключение
Панель инструкций по маршруту (Route Instructions Panel) стала полезным тестовым примером, поскольку большая часть работы заключалась не в интеграции SDK, а в адаптации новой функции к уже существующей архитектуре, потокам состояний, Compose UI и взаимодействиям в примере приложения — именно та часть расширения чужого приложения, которая занимает часы. Что сделало новую итерацию быстрее, так это не лучший промпт, а накопленный навык.
Выводы из этого тематического исследования также были использованы при формировании нашего подхода к ускорению разработки приложений с помощью ИИ. Следите за обновлениями.
Попробуйте сами
Промпт, файл CLAUDE.md и навык находятся по адресу todo-repo-url — клонируйте этот репозиторий и следуйте инструкциям в его README, чтобы установить их в свою копию примера приложения.
В нашем запуске использовался плагин Superpowers, поэтому ваш опыт может отличаться при стандартной настройке Claude Code.
Вам также потребуется ключ TomTom API в файле gradle.properties перед сборкой приложения — его можно бесплатно получить на сайте my.tomtom.com в разделе Maps and Navigation SDK for Android.
После установки откройте репозиторий в Claude Code и передайте ему промпт.
Ожидайте, что Claude Code будет прорабатывать контрольный список жестких правил навыка по ходу работы — его собственная инструкция состоит в том, чтобы отслеживать каждое правило как задачу и подтверждать его выполнение перед завершением сессии, что максимально приближено к этапу проверки (review gate).
Сравните полученный результат с нашим тематическим исследованием: где он совпадает, где SDK или Compose с тех пор изменились, и с какими дополнительными уроками или ловушками вы столкнетесь во время своей сессии.
Дайте нам знать о своих успехах, нам интересно услышать, что вы обнаружите.
Для получения дополнительной информации обратитесь к:
- Документации TomTom Maps and Navigation SDK for Android
- Примеру приложения на GitHub
- Документации Anthropic по Claude Code
- Claude Code Superpowers от Jesse Vincent
Claude Code Superpowers от Jesse Vincent
#developer
