Документация TomTom
Технический контент из документации TomTom для разработчиков, использующих API, SDK и картографические технологии TomTom
Кейс по созданию панели инструкций маршрута с использованием TomTom Maps and Navigation SDK для Android и Claude Code.
Предполагается базовое знакомство с Claude Code. Если вы новичок, начните с документации Anthropic по Claude Code.
Расширение чужого примера приложения может быть утомительным. Вы клонируете его, тратите часы на изучение кода, чтобы понять его недокументированные соглашения, разбираетесь, как он работает, и только после этого можете начать добавлять свои функции и расширять приложение.
Мы хотели выяснить, насколько сложно и сколько усилий требуется для добавления функции в пример приложения TomTom для Android, когда реализацией занимается ИИ-агент (пример приложения можно найти здесь: link). Поэтому мы поручили Claude Code создать нашу собственную функцию, фиксируя каждую возникшую проблему в файле навыков (skill file) по мере продвижения.
Чтобы сделать этот эксперимент воспроизводимым, мы опубликовали промпт, CLAUDE.md и навык в этом repo. Мы запустили его с плагином Джесси Винсента 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?. Пара типов маршрутизации находятся в пакетах, которые расположены не там, где вы ожидаете: пакет одного подтипа инструкции не совпадает с именем его класса, а вспомогательный тип данных находится вне пакета инструкций, с которым он используется. Всё стало понятно после идентификации, и теперь каждая такая проблема — это строка в таблице «Подводные камни» (Gotchas) навыка.
Изменения в пользовательском интерфейсе — внедрение нижней панели Compose
Что изменил ИИ: каждый сценарий в приложении связывает держатель состояния (state holder) с его UI на Compose, и всё изменяемое состояние находится в одном общем MapScreenViewModel. Панель добавила три новых файла в существующий пакет routepreview и переписала UI-файл этого пакета в пользовательскую нижнюю панель с возможностью перетаскивания и вложенной прокруткой, заменив нижнюю панель, которая была там раньше. Остальное было интегрировано через общие точки взаимодействия приложения: список инструкций как новый StateFlow в MapScreenViewModel, одно новое поле в MapScreenUiState для выбранной инструкции, отрисовка булавки этой инструкции в MapViewComponents и связь между ними в ScenarioHoldersFactory. Единственным изменением вне application/map стали два десятка новых строковых ресурсов для меток и описаний контента панели — согласно соглашению проекта, каждая видимая пользователю строка находится в strings.xml, ничего не зашито в Kotlin.
Это соглашение соблюдается для литералов, но не для грамматики: панель собирает каждую метку, вставляя название дороги в шаблон (route_instruction_onto — это «%1$s на %2$s»), что закрепляет порядок слов английского языка. Для производственного кода потребовались бы целые предложения для каждого маневра или форматы сообщений ICU, а также переводы, которые не включены в пример приложения. Это не относилось к тому, что мы тестировали здесь, поэтому мы остановились на этом этапе.
Что прошло гладко: большая часть связей. Правило линтинга, обнаруживающее неиспользуемый строковый ресурс, модификатор видимости, расширенный с private до internal для повторного использования сопоставления значков маневров экрана навигации, отступы безопасной области (safe-area insets), z-порядок для плавающих кнопок, которые перекрывает панель — обычная гигиена Android, никакой нестабильности SDK или Compose.
Что было сложнее: самая большая группа проблем была связана с одним аспектом Compose. Чтобы создать нижнюю панель с возможностью перетаскивания, Claude Code обратился к AnchoredDraggableState и anchoredDraggable — всё еще ограниченным @OptIn(ExperimentalFoundationApi::class). Большинство сложных проблем возникло именно там, включая ту, которая проявляется только во время выполнения: settle(velocity) компилируется без ошибок, только с предупреждением об устаревании, а затем вызывает сбой, как только его активирует fling, что является частью изменений, описанных в собственном руководстве по миграции Android. В итоге панель также получила экспериментальный opt-in Material3 для своего маркера перетаскивания, а ближайшая стабильная альтернатива, BottomSheetScaffold от Material3, всё еще не дает такого же сворачивания на частичную ширину и передачи вложенной прокрутки без дополнительных усилий. Поэтому мы всё равно оставили экспериментальный API.
Эти подводные камни теперь отражены в таблице «Ловушки» (Gotchas) навыка: безопасная перегрузка settle и переименованные методы доступа к anchor. Это также отражает общий урок: перед написанием кода проверяйте структуру экспериментального API на соответствие закрепленной версии зависимости, а не доверяйте фрагменту документации. Именно поэтому в последующих сессиях сбой не повторяется.
Хотя нам приходилось управлять Claude Code, большая часть нашего вмешательства сегодня не потребовалась бы: Claude Code может самостоятельно итерировать вывод сборки и линтера, а CLAUDE.md уже требует от него записывать каждый новый подводный камень в навык до завершения сессии. Тестирование на устройстве, где и проявились сбой и строки без иконок, потребовало нашего участия только потому, что мы не добавили инструментальные тесты для этого упражнения. При наличии UI-тестов или проверки скриншотов цикл замыкается без нашего участия.
Заключение
Панель инструкций по маршруту стала полезным тестовым примером, поскольку большая часть работы заключалась не в интеграции 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 будет прорабатывать контрольный список жестких правил навыка по ходу работы — его собственная инструкция заключается в том, чтобы отслеживать каждое правило как задачу и подтверждать его перед завершением сессии, что максимально приближает этот рабочий процесс к этапу проверки.
Сравните полученный результат с тематическим исследованием: где он совпадает, где SDK или Compose с тех пор изменились, и какие дополнительные уроки или подводные камни вы встретите во время своей сессии.
Дайте нам знать о своих успехах, нам интересно узнать, что вы обнаружите.
Для получения дополнительной информации обратитесь к:
- Документация TomTom Maps and Navigation SDK for Android
- Пример приложения на GitHub
- Документация Anthropic по Claude Code
- Claude Code Superpowers от Джесси Винсента
Claude Code Superpowers от Джесси Винсента









