Как я стал туалетным сомелье

История о том, как я стал туалетным сомелье Минска и создал карту всех местных уборных с расписанием, рейтингом и компасом.

Android, iOS, Windows Phone и прочие

История о том, как я стал туалетным сомелье Минска и создал карту всех местных уборных с расписанием, рейтингом и компасом.

Уже девять лет я делаю приложение с расписанием автобусов для посёлка Иртышский в Омской области. И почти всё это время сам там не живу - уехал через полгода после запуска, а приложение осталось, им до сих пор пользуются.
И сразу скажу: я не программист. Работаю в IT системным аналитиком, а код пишу для себя, как хобби. Захотел бы научиться программировать всерьёз - пошёл бы на курсы и научился. Но мне это никогда не было нужно. Нужно было получить желаемую утилиту, а программирование тут просто инструмент. Это - моё творчество.
А вспомнил я про эти девять лет сегодня вечером. Сегодня 18 июня 2026 года, и ровно семь лет назад, день в день, я научил приложение скачивать расписание из интернета — до этого оно лежало прямо в сборке. Сегодня этот способ убрал, расписание теперь приходит по‑другому. Провозился полвечера, а потом посчитал - приложению‑то уже девять лет.

На первый взгляд, медиалента в мобильном приложении выглядит как стандартная задача: список карточек, автоплей, предзагрузка соседних роликов, несколько состояний загрузки. На практике это оказался один из самых сложных iOS‑компонентов, с которыми мне доводилось работать.
Проблема в том, что медиалента — это не один виджет и не просто плеер внутри ячейки. Это система, которая живёт на пересечении сразу нескольких тяжёлых доменов: динамически собираемый интерфейс, сетевые ограничения, декодирование медиа, менеджмент памяти, жизненный цикл вложенных контейнеров, UX‑требования к мгновенному старту, интеграция в чужие экраны и такие сложные системы, как BDUI, рекомендации, пагинации, и при этом — высокий трафик на массовом сценарии.
Само собой, любая ошибка в этой конструкции редко проявляется как локальный баг. Обычно она масштабируется: фризы при скролле, чёрные экраны, нестабильный автоплей, рост памяти на длинных списках, нагрев устройства и трудноуловимые падения, которые воспроизводятся только на части устройств и только в условиях реального использования, а не эмуляции.
Самое интересное в таких задачах начинается не на этапе «как добавить медиаленту», а на этапе ограничений и деградаций. В статье я разберу именно эту сторону задачи на примере приложения Яндекс Еды: как мы проектировали медиаленту, какие архитектурные решения не сработали, какие баги всплыли только на реальных данных, как мы строили observability для дебага и какие компромиссы в итоге оказались эффективнее красивой реализации.

Всем привет! Я хочу поделиться историей о том, как обычная пользовательская боль заставила меня открыть Android Studio и сделать свой первый серьезный проект.
Я очень люблю читать с телефона (особенно ранобэ, новеллы и книги в оригинале). Но в последнее время индустрия мобильных читалок свернула куда-то не туда. Открывая популярные приложения, я чувствовал себя пилотом Боинга: десятки перегруженных меню, всплывающие баннеры, просьбы купить Premium-подписку и интерфейсы прямиком из 2012 года.
Но моей главной болью был перевод. Когда ты читаешь книгу на английском и встречаешь незнакомое слово, тебе приходится выделять его, копировать, открывать Google Переводчик, вставлять, читать, возвращаться в книгу… Погружение в историю рушится моментально.
Есть, конечно, Circle to Search или читалки с функцией перевода, но мне они показались максимально неудобными
Я искал минималистичную читалку со встроенным удобным переводчиком. Не нашел. И решил написать её сам.

Я полгода улучшал продукт и почти не зарабатывал. А потом поменял не сам продукт, а только путь пользователя до оплаты — и внезапно появились годовые подписки.
В этой статье рассказываю, почему в мобильных приложениях онбординг и пейволл часто важнее очередной фичи, и как я переработал их в своем приложении для изучения слов.

Представляем AdaEngine 0.1.0
После долгого пути я рад представить AdaEngine 0.1.0: бесплатный игровой движок и фреймворк для приложений с открытым исходным кодом, написанный на Swift.

Привет, я Павел Семенищев, сетевой инженер в Yandex Infrastructure. В команде Network Operations Center (NOC) мы отвечаем не только за магистральные и дата‑центровые сети, но и за офисные, а также сети складов и дарксторов Яндекс Лавки. А это ОЧЕНЬ много удалённых точек присутствия, и при проблемах с Wi‑Fi на каждую сетевика не отправишь.
Для быстрого сканирования параметров сети на местах я создал WiProber под Android и WiFi Prober под iOS — получился сетевой «комбайн» для инженера, который сначала был нашим внутренним инструментом, а теперь есть и в общем доступе. Под катом расскажу, что умеют эти приложения, и какие ограничения операционных систем удалось обойти при их создании.

Вместе с растущей AI-индустрией приходят и её побочки. Я мейнтейнер библиотеки react-native-tdlib и довольно быстро заметил: все больше PR выглядят как чистый вывод агента. Сначала я честно реагировал — писал в каждый такой PR вопросы: тестировали ли вы это, что именно меняет ваш код, зачем вот эта строчка. В какой-то момент понял, что трачу время на переписку с людьми, которые сами не знают, что написали.
Первая мысль была — написать большой README или CONTRIBUTING и прямым текстом сказать: «сгенерированный код не принимаю». Но тут же упёрся в вопрос: а как доказать, что код сгенерирован? Аргумент «чую, тут пахнет Claude Code» — так себе позиция для публичного спора в комментариях к PR.
Решение оказалось довольно простым — AGENTS.md. Он конечно не доказывает, что PR сгенерирован, но отлично ловит самые очевидные автоматические PR, где автор, кажется, вообще не участвовал в процессе.

Короткий пост про текущий статус по развитию мессенджера.
Последние два месяца мы занимались бумажной работой. Той самой, которую стартапы обычно откладывают до последнего, а потом делают в пожарном режиме. Мы решили пойти иначе: сначала закрыть все юридические вопросы, потом запускать пользователей. В итоге получили официальный ответ Роскомнадзора, подали уведомление об обработке персональных данных, открыли whitelist-доступ для первых тестеров. Обо всём по порядку.

Меня зовут Родион, и я уже около 2,5 лет работаю в VK Android-разработчиком в крупном многомодульном проекте с сотнями экранов и довольно большой аудиторией. Когда я попал на проект, стек был классическим и проверенным: XML-вёрстка, навигация через Cicerone, Dagger 2 для DI, Coroutines и Flow для асинхронщины, а в качестве архитектурного паттерна — MVVM.
Рано или поздно любая растущая кодовая база упирается в потолок своих архитектурных решений. У нас этот момент настал, когда количество экранов выросло до нескольких сотен и команда начала тратить больше времени на борьбу с неконсистентным состоянием UI. Классическая связка XML + ViewBinding + MVVM работала, но с каждым новым экраном мы всё острее чувствовали её ограничения: разрозненные StateFlow, дублирование кода во фрагментах, сложность переиспользования компонентов.
Нужно было что-то менять — пересмотреть сам подход к построению UI. Так мы начали миграцию на Jetpack Compose (который на момент начала перехода уже был стабильным и самодостаточным). Полтора года спустя, пройдя через рефакторинг базовых классов, переход с MVVM на MVI и постепенную замену содержимого всех фрагментов, мы получили стек, на котором разработка ускорилась, а баги, связанные с состоянием экрана, практически исчезли.
Полный переход на Jetpack Compose мы разделили на три больших этапа:
- переписываем содержимое всех фрагментов на ComposeView;
- переходим с Dagger2 на Koin;
- меняем навигацию с Cicerone на Compose-навигацию.
О втором и третьем этапах кратко расскажу ниже — в главе стратегии перехода, а на первом этапе остановлюсь подробнее.
В этой статье не будет разбора плюсов и минусов Jetpack Compose, скорее она будет полезна тем, кто уже знаком с технологией, хочет её использовать, но боится нести в проект. Я расскажу, как мы шаг за шагом выполняли первый этап, и к чему в итоге пришли.

Типичный прохладный вечер в начале сентября. Я сижу за рабочим столом в гостиной, жена укладывает ребёнка. Со стороны кажется, что я занимаюсь чем-то важным, ведь мой взгляд сосредоточен на экране макбука. Но на самом деле я думаю о том, как бы организовать себе хоть какой-то альтернативный доход на случай сокращения.
В какой-то момент я натыкаюсь на статью Миши Жирнова, где он хвастается тем, что вышел на доход в 176 тысяч рублей в RuStore. Я тут же вдохновляюсь опытом Миши и твёрдо решаю, что тоже хочу 176 тысяч. Так начинается эта история.

Всем привет! Меня зовут Амир Утеуов, я ML-инженер из Авито.
В первой части статьи я поделился тем, что пришлось сделать и учесть для создания собственной игры для разработчиков — DevRush. Суть игры заключается в том, что нужно на время находить иконки языков программирования. Я прошёл путь от создания геймплея и векторной анимации до сборки под Android и iOS. Главная неожиданность ждала в App Store — модераторы отклонили игру из-за иконки Android, посчитав это рекламой конкурента. Но по итогу Авито взял мою игру на стенд Code Fest 2025.
В этой части будет о том, как создавался редизайн и что нужно было доработать, чтобы игру можно было использовать на стенде Авито.

Навигация во Flutter — это постоянные компромиссы. Сначала кажется всё просто: push и pop. А потом проект растёт, появляются табы, вложенные модули, диплинки — и выясняется, что каждый следующий экран открывается по‑разному, а pop() в одном месте ведёт себя не так, как в другом.
Navigator 1.0 прост и понятен, но при масштабировании рассыпается. Navigator 2.0 даёт полный контроль, но требует столько бойлерплейта, что проще изобрести свой фреймворк. Сообщество это поняло — и появились пакеты поверх Navigator 2.0. go_router упрощает жизнь, но недавно перешёл в режим поддержки: только баг‑фиксы, никаких новых фич. auto_route даёт type‑safety, но тянет за собой кодогенерацию.
Мы прошли через все эти варианты в процессе разработки Яндекс Про — приложения для водителей и курьеров, где навигация включает сотни фич, несколько команд, вложенные модули, табы, диплинки и legacy‑код на Navigator 1.0. А ещё — сложную логику переходов, где точный контроль над состоянием навигации не просто желателен, а критичен: экран закрывается там, где не должен, стек оказывается в неожиданном состоянии, и разобраться в причинах через стандартный API почти невозможно.
Так появился yx_navigation — новый пакет в нашей экосистеме архитектурных решений для Flutter, после yx_scope (DI) и yx_state (управление состоянием). Дальше расскажу, с какими трудностями мы столкнулись, какие требования сформулировали, как устроен yx_navigation сегодня и как именно он решает проблемы крупных приложений.

Всем привет! Меня зовут Амир Утеуов — я ML-инженер из Авито.
В этой статье поделюсь своей историей создания мобильной игры DevRush, пет-проекта, который перерос в игру на стенде IT-конференции CodeFest 2025.
Однажды у меня под рукой оказался датасет из иконок различных фреймворков и языков программирования. Так я решил разработать приложение, где нужно как можно быстрее находить и выбирать иконки языков программирования среди случайных иконок. До этого я не занимался разработкой и публикацией мобильных игр и приложений, но решил пройти весь путь с нуля.
Статью разделим на две части: в первой расскажу как создавал первую версию игры и с какими трудностями столкнулся, а во второй — как мы готовили игру к конференции.

В первой части мы рассказали о пилоте и первых версиях системы Smart Timber для измерения и учета объемов древесины, внедрении продукта у клиента и переходе от технического наполнения к продуктовой составляющей решения.
Сегодня в блоге ЛАНИТ мы подробно остановимся именно на технических решениях, которые сделали возможной работу системы в полевых условиях.

Миграция большого iOS-проекта с Objective-C на Swift кажется понятной задачей ровно до тех пор, пока не начинаешь считать объём. В нашем случае это были 10 тысяч файлов, сотни тысяч строк кода и постоянная необходимость не останавливать развитие продукта. Ручной подход работал слишком медленно, поэтому мы начали автоматизировать миграцию с помощью LLM — и в итоге превратили её из бесконечного техдолга в воспроизводимый процесс.
Из этой статьи вы узнаете, как мы пять лет закрывали этот техдолг и за это время переписали лишь половину. И как в итоге пришли к решению на базе LLM, которое помогло завершить работу кратно быстрее и высвободило время разработчиков для более интересных задач, чем рефакторинг кода.
Меня зовут Андрей Сикерин, я руковожу одной из групп iOS-разработки Яндекс Браузера. Вместе со мной статью писала Елизавета Мазулова, разработчица из нашей же команды. Она создала систему промптов для миграции, ревью, рефакторинга и автоматизации тестирования. Вместе мы расскажем, как устроен весь процесс изнутри: от выбора порядка миграции модулей до контроля качества через тесты.
Все промпты, конфигурационные шаблоны и вспомогательные скрипты выложили в открытый доступ — забирайте и адаптируйте под свой проект. Мы уже проверили, что подход работает не только у нас: взяли открытый репозиторий приложения Wikipedia для iOS и без существенных изменений промптов мигрировали один из его пакетов и поделились результатом с сообществом в виде открытого PR.

Сегодня в блоге ЛАНИТ мы бы хотели поделиться, как продукт для лесной отрасли на основе алгоритмов компьютерного зрения прошел путь от пилотной версии до гибкой бизнес-системы и выжил в условиях, когда у сотрудников клиента нет связи, а поставщики не всегда добросовестно измеряют объемы древесины.

Всё началось чисто по приколу. Недавно в сети поднялась шумиха вокруг уязвимости VLESS-клиентов: оказалось, что даже при использовании сплит-туннелирования (когда VPN включен только для избранных приложений), любое «шпионское» приложение на телефоне может узнать IP-адрес вашего VPN-сервера.
Уязвимость была тривиальной — ядро клиента открывает локальный SOCKS-прокси, который никак не защищен. Любая софтина на устройстве может постучаться в этот локальный порт и отправить пакет наружу. Ради академического интереса я написал Android-приложение TeapodStream, под капотом которого связал xray-core и tun2socks. Локальный прокси я посадил на случайный порт и закрыл динамическим паролем (подробнее об этом писал в прошлой статье).
Пост получил огромный отклик у комьюнити, породил живое обсуждение и разлетелся по закладкам. Я думал, что на этом мой эксперимент закончен.
Но... я сам не заметил, как меня затянуло.

За полгода я сделал мобильное приложение, получил 2000 установок и… 8 платных подписок по $6. Причем одна из подписок — моя.

Привет, Хабр!
Ну вот вы ставите Яндекс Go, жмёте «Разрешить» на всё подряд — микрофон, контакты, местоположение. Такси же, надо. А потом выясняется, что приложение лезет в буфер обмена. 16 раз в разных местах кода. Зачем такси буфер обмена — я так и не понял.
Короче, я взял семь популярных Android-приложений и разобрал их по косточкам. SAST, реверс-инжиниринг, декомпиляция DEX, разбор манифестов, ковыряние в нативных библиотеках. Под раздачу попали: Яндекс Go, Карты, Музыка, Пэй, Телемост, Mir Pay и мессенджер МАКС (бывший ICQ New / VK Messenger).
Спойлер: один мессенджер умеет распознавать ключевые слова прямо в аудиопотоке звонков. Не метаданные, не «кто кому звонил» — а именно слова.
<cut/>