Forwarded from Dolgo.polo Dev | Денис Долгополов
технически VPN на андроид — это сервис
внутри можно получить
inputStream с байтами трафика всех приложенияclass MyVpnService : VpnService() {
fun startService() {
val tunFd = Builder()
.setSession("MyVPN")
.addAddress("10.0.0.2", 24)
.addRoute("0.0.0.0", 0)
.establish()
Thread {
val input = FileInputStream(tunFd.fileDescriptor)
}.start()
}VPN работает на уровне IP/TCP/UDP пакетов
Ему плевать, какой тип трафика в этих байтах — данные внутри могут быть упакованы по протоколу http/https или вообще gRPC/GraphQL/SIP/MQTT...
Он получает сырой набор байт, которые надо зашифровать/переупаковать любым алгоритмом и доставить на сервер
💡 А может ли приложение VPN расшифровать https трафик?
Может, но только если пользователь добавит SSL-сертификат, созданный самим VPN-клиентом, в список доверенных
Получится классическая man-in-the-middle, в которой VPN сможет расшифровывать трафик
Оказывается, существуют даже мобильные версии снифферов вроде Proxyman. Они как раз поднимают VPN-сервис и просят установить кастомный сертификат
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Compose Broadcast
Камера в CMP это всегда возня с
expect/actual и тремя платформенными бэкендами. Kamera (бывшая CameraK) закрывает это одним Compose-first слоем: один @Composable-вход, под капотом CameraX на Android, AVFoundation на iOS и JavaCV на Desktop.API реактивный, через состояние. Заводишь
rememberCameraKState(), получаешь StateFlow<CameraKState> c ветками Initializing, Ready(controller, uiState) и Error, и рисуешь превью, когда камера готова:val cameraState by rememberCameraKState(
config = CameraConfiguration(
cameraLens = CameraLens.BACK,
aspectRatio = AspectRatio.RATIO_16_9,
),
)
when (val state = cameraState) {
is CameraKState.Ready -> CameraPreviewView(state.controller)
is CameraKState.Initializing -> CircularProgressIndicator()
is CameraKState.Error -> Text(state.message)
}
Из коробки: зум, вспышка, фонарь, переключение линз (ultra-wide/telephoto на iOS),
takePictureToFile() для прямого сохранения в файл. Сверху плагины, которые сами активируются на Ready: сохранение фото, QR/штрихкоды, OCR, запись видео с pause/resume и лимитом длительности, анализ кадров через analyzer.Главное в 1.0: починили то, что мешало брать в прод. На iOS фронталка отдавала тёмные кадры из-за бага в
MemoryManager, хотя превью выглядело нормально. На Android фото оказывалось кропом вместо настроенного аспекта, теперь что видишь, то и снимаешь. Плюс вычистили утечки корутин в плагинах при ре-ините камеры.‼️ Это молодая 1.0 и по сути проект одного мейнтейнера под Apache-2.0. Блокеры выше жили буквально до вчера, так что 1.0 это точка, где их закрыли, а не годы шлифовки. Desktop тянет JavaCV с нативными либами, это тяжело. Но если нужна камера в CMP без трёх реализаций руками, смотреть стоит.
#Compose #ComposeMultiplatform #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Compose Broadcast
This media is not supported in your browser
VIEW IN TELEGRAM
v1 умел одно — применять изменения значений без rebuild: цвет, padding, текст, размеры — результат за секунду, приложение живёт. Добавить composable, переставить layout, поменять control flow — всё это шло в полный rebuild.
v2 убирает эту границу. Без рестарта приложения: добавляем и удаляем composable-функции, меняем структуру layout, переписываем conditional UI. И главное — заменяем целый экран на совершенно другой код. Навигационный стек и
remember-состояние сохраняются.Технически v2 запускает изменения через собственный интерпретатор, обходя ограничения ART на переопределение классов — тот же подход, что у Flutter. При слишком глубоких изменениях деградирует плавно: сбрасывает composition с сохранением
rememberSaveable и ViewModel, в крайнем случае рестартит Activity. Полный rebuild нужен только при изменении сигнатур функций, иерархии классов и inline-функций.В v2 также MCP-сервер: AI-агент триггерит reload, снимает скриншот с устройства, итерирует по вариантам. Claude Code и Cursor работают из коробки через file watcher.
Поставить: IDE-плагин вручную с бета-канала Marketplace + Gradle-плагин
2.0.0-beta01:[plugins]
hotswan-compiler = { id = "com.github.skydoves.compose.hotswan.compiler", version = "2.0.0-beta01" }
Инструмент платный инструмент, лицензия и цены на hotswan.dev/pricing.
Такого охвата hot reload в нативном Compose ещё не было. Аргумент Flutter про быстрый feedback loop заметно слабеет.
#Compose #JetpackCompose #AndroidDev
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
С 16 июня появятся предупреждения про превышение бесплатных лимитов на месяц, с 11 августа 2026 начнётся реальное ограничение бесплатных публикаций.
Пороги у 90 перцентиля: 1 167 файлов в месяц, 78 МБ суммарно, 7 релизов. Большинство open source разработчиков не заметят. Кто публикует много и часто — проверьте Usage Center уже сейчас.
Лично мне интересно, как это ляжет на KMP-проекты. Один multi-target релиз — это десятки файлов на каждую платформу: sources, javadoc, pom, подписи. Sonatype говорит, что работает с JetBrains над смягчением. Посмотрим.
🔗 Официальная документация о лимитах
#Maven
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
Решил обновить compileSdk до Android 37, а там, оказывается, удалили старый Fingerprint API, который был до BiometricPrompt. Чем он им помешал? Ведь теперь обеспечивать поддержку старых версий Android сложнее, но это отдельный разговор.
В ходе миграции я узнал, что обновления библиотеки androidx.biometric — сущий хаос:
👉 Самая свежая версия — 1.4.0, и она только в альфе.
👉 Версия 1.3.0 вообще не делалась.
👉 Версия 1.2.0 не получила стабильного релиза, остановившись на альфе.
👉 Самая свежая стабильная версия — 1.1.0, которая вышла в 2021 году!
#Android #AndroidDev #Security
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
Google выпустила финальный Android 17. Исходники открылись в AOSP, обновление катится на поддерживаемые Pixel-устройства.
Главный сигнал релиза: Android официально Compose-first. Все новые API, библиотеки, инструменты и документация будут создаваться только для Jetpack Compose. View (
android.widget), Fragments, RecyclerView, ViewPager переходят в maintenance mode: только критические баги, никаких новых фич. Вопрос «когда View умрёт» закрыт — она уже в maintenance.Breaking changes при таргете SDK 37:
👉
resizeableActivity=false, screenOrientation, minAspectRatio / maxAspectRatio игнорируются системой на large screen (sw > 600 dp). Игры освобождены, остальные нет.👉
static final поля нельзя менять через reflection: IllegalAccessException. Через JNI — краш.👉 Native-библиотеки через
System.load() должны быть read-only, иначе UnsatisfiedLinkError.👉 Доступ к локальной сети заблокирован по умолчанию: нужен
ACCESS_LOCAL_NETWORK.👉 Lock-Free
MessageQueue быстрее, но ломает код с reflection на приватных полях.‼️ ВАЖНО CameraX: обновитесь до
1.5.2 или 1.6.0+ — краш на Android 17 из-за нового режима dynamic range.Из остального: Generational GC в ART, жёсткие лимиты памяти с принудительным завершением процессов, Post-Quantum Cryptography (ML-DSA), AppFunctions как on-device MCP API для AI-агентов (alpha, Gemini в private preview).
#Android #Android17
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
Media is too big
VIEW IN TELEGRAM
XREAL официально представил Aura (бывший Project Aura): лёгкие проводные очки с прозрачным дисплеем, вычисления вынесены в карманный блок на новом Snapdragon Reality Elite, Gemini в системе. Финальной цены нет, но база «не дороже $1500», резерв открыли за $99.
Google показал что на этом строить. Демка XR Geospatial Tour: надеваешь очки, поверх города висят 3D-подсказки, голосовой гид рассказывает про здания перед тобой. Внутри Geospatial API (VPS от Google в ARCore for Jetpack XR, субметровая точность и направление взгляда, точнее GPS), Gemini с Google Maps Grounding для маршрутов, Gemini TTS для озвучки и Compose for XR для 3D.
Если смотреть на рынок: смартфоны выезжены вдоль и поперёк, складные остались нишей, а лёгкие очки это правда новое место, где игра ещё не сыграна. Aura важна именно этим: форм-фактор наконец похож на то, что хочется носить, а не на шлем на полдня.
#Android #AndroidXR #XR #Gemini
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
📃 Сравнение скорости работы Metro DI vs Dagger/Hilt в Android проекте.
У меня по рабочей задаче встал вопрос какой DI выбрать для трансформации Android проекта в KMP с поддержка Android, iOS, Desktop и конечно нормальной работой с Compose. Решил понять чего будет стоить миграции на Metro DI и был приятно удивлен.
За день с помощью AI перевел Now In Android на Metro и запустил различные тесты сравнения влияния DI на сборку проекта. Подробности в🪙 полной статье на Boosty
#Dagger #Metro #KMP #Performance
У меня по рабочей задаче встал вопрос какой DI выбрать для трансформации Android проекта в KMP с поддержка Android, iOS, Desktop и конечно нормальной работой с Compose. Решил понять чего будет стоить миграции на Metro DI и был приятно удивлен.
За день с помощью AI перевел Now In Android на Metro и запустил различные тесты сравнения влияния DI на сборку проекта. Подробности в
#Dagger #Metro #KMP #Performance
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
Hydra — это RASP-плагин для Android: подключаешь одной строкой в
build.gradle.kts, и на выходе assembleRelease APK несёт обфусцированное нативное ядро с защитой.plugins {
id("com.android.application")
id("com.github.iamjosephmj.hydra") version "1.9.0"
}Что проверяет на старте процесса: рут-доступ, Frida/hooking-инструменты, клонирование через virtual spaces (Parallel Space и похожие), эмуляторы, целостность APK. Нашёл критичное — завершает процесс. Без advisory-режима, сразу kill.
secrets {} в конфиге шифрует строки при сборке, в classes.dex попадает только цифертекст, расшифровка только на чистом устройстве:val url = withContext(Dispatchers.IO) { Hydra.secret("apiUrl") }Всё on-device, без сети, без телеметрии.
INTERNET permission не объявляется вообще.⚠️ Ядро
libdicore.so закрыто и обфусцировано — проверить что именно кладётся в APK нельзя. Для финтех-продакшна это принципиальный вопрос. Kill-by-default сломает эмуляторы в QA — тестировать только на реальных чистых устройствах. QUERY_ALL_PACKAGES потребует декларации в Play Console.В продакшн только после того, как понял, что именно ты кладёшь в свой APK.
#Android #AndroidDev #Безопасность
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Broadcast
‼️ Каждый год 31 августа наступает дедлайн по повышению targetSdk. В этом году дедлайн потребует минимум 36 (Android 16), и это не просто цифра в Gradle-скриптах!
Чуть больше двух месяцев до дедлайна Google Play. С 1 сентября новые публикации и обновления должны таргетировать Android 16 (API 36). Пропустить срок — приложение пропадёт из выдачи для новых пользователей на устройствах с Android новее вашего текущего таргета.
Главная ловушка: переход на
👉
👉 Native .so и 16KB page size. Если в приложении или транзитивных зависимостях есть нативный код — нужна проверка совместимости. NDK 27+ и
👉
👉 Health permissions.
Тестировать breaking changes можно уже сейчас, не повышая
Или точечно по конкретному флагу — удобнее разбирать изменения по одному. Подробнее читайте в документации.
#Android #AndroidDev #Android16
Чуть больше двух месяцев до дедлайна Google Play. С 1 сентября новые публикации и обновления должны таргетировать Android 16 (API 36). Пропустить срок — приложение пропадёт из выдачи для новых пользователей на устройствах с Android новее вашего текущего таргета.
Главная ловушка: переход на
targetSdk = 36 включает breaking changes, которые начинают работать сразу после сборки. Что поменяется после смены цифры:👉
onBackPressed() больше не вызывается. На Android 16 его переопределение игнорируется. Нужен OnBackPressedDispatcher или OnBackInvokedCallback.👉 Native .so и 16KB page size. Если в приложении или транзитивных зависимостях есть нативный код — нужна проверка совместимости. NDK 27+ и
useLegacyPackaging = false. Без этого возможны краши на части устройств.👉
USE_FULL_SCREEN_INTENT требует явного разрешения. Звонки, будильники, доставка — всё, что показывает уведомления поверх экрана блокировки, перестанет работать без декларации в манифесте.👉 Health permissions.
BODY_SENSORS и BODY_SENSORS_BACKGROUND заменяются на гранулярные android.permission.health.* — READ_HEART_RATE, READ_OXYGEN_SATURATION и т.д.Тестировать breaking changes можно уже сейчас, не повышая
targetSdk, через compat framework:adb shell am compat enable-all com.yourapp
Или точечно по конкретному флагу — удобнее разбирать изменения по одному. Подробнее читайте в документации.
#Android #AndroidDev #Android16
Forwarded from Android Broadcast
Стандартный Android Profiler показывает потоки. Не корутины. Kotlinx-coroutines-debug работает в unit-тестах, но не на реальном девайсе с живым UI. Яндекс Go сделали для этого отдельный инструмент.
Coroutine Tracer — плагин в их открытой библиотеке Demeter. Gradle-плагин на этапе сборки находит все launch/async через ASM и вставляет хук без единой правки в исходниках. В рантайме хук перехватывает возвращённый Job, регистрирует invokeOnCompletion и всё отображается как интерактивное дерево прямо на девайсе.Два технических момента, которые зацепили:
👉 Перехватывают
launch$default, а не только launch. Это та версия, которую компилятор Kotlin генерирует для вызовов с default-параметрами. Именно она выполняется в большинстве реальных вызовов.👉 Parent-child связи строятся через обратный индекс
Job → traceId. Без него launch-в-цикле даёт квадратичный оверхед на горячем пути. Дерево собирается итеративно — страховка от StackOverflowError на глубоких иерархиях.Zero overhead по умолчанию: без
includedClasses в конфиге плагин ничего не инструментирует.Отсутствие нормального рантайм-инструментария для корутин давно раздражало. Это первый инструмент из тех, что видел, который работает на живом девайсе без ручной расстановки меток.
🔗 Статья на Хабре
#Kotlin #Coroutines #AndroidDev
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Android Live 🤖
This media is not supported in your browser
VIEW IN TELEGRAM
Важный вопрос
Как думаете, юзеры удивятся, если увидят такой ввод пароля в банковском приложении?
Если что — вот код.
Как думаете, юзеры удивятся, если увидят такой ввод пароля в банковском приложении?
Если что — вот код.
Forwarded from Android Broadcast
Когда: вторник, 30 июня, 19:00 GMT+3
В прямом эфир буду обсуждать с разработчиком из компании, которая перешла на Kotlin Multiplatform, а теперь отказались и возвращаются назад! С другой стороны - я который переводит разработку банка на Compose Multiplatform.
Эфир пройдет на 🪙 Boosty, запись будет опубликована позже там же
#Kotlin #KMP #CMP #Compose #AndroidBroadcast
Please open Telegram to view this post
VIEW IN TELEGRAM
Jetpack Compose имеет собственный API для создания сетчатых градиентов, встроенный прямо в
androidx.compose.ui. В этой статье автор рассмотрит, что это такое, нарисует несколько примеров и поговорит о том, чем он отличается как от SwiftUI, так и от решений сообщества, которые вы, возможно, уже используете.
#свежак #Android
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Compose Broadcast
DrawBox работала как Android-only с 2021 года. В конце мая вышел
2.0.0-alpha02 с таргетами Android, iOS, JVM/Desktop и WASM. Живая демка работает прямо в браузере без установки.В 2.0 добавили: SVG и JSON экспорт, бесконечный канвас с зумом и паном, выделение и перетаскивание фигур, коннекторы, object eraser и Roborazzi тесты.
Автор написал пост про перенос, и самый ценный кусок там не про KMP. Самая интересная часть - использование MVI. Один
State, Intent на каждое действие, Reducer с (State, Intent) → State. После этого undo/redo - это стек из State, JSON-сериализация практически бесплатна, и логика платформ физически не может разъехаться.#Compose #KMP #ComposeMultiplatform
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Типичный программист
Android 17 даёт приложениям функции, которые ИИ-агенты могут вызывать сами
Привыкли, что приложение ждёт, пока вы сами нажмёте кнопку? В Android 17 Google меняет правила: разработчик аннотирует функции приложения, и ИИ-агент может дергать их через Jetpack, получая доступ к локальному состоянию.
Приложение перестаёт быть островом и становится частью инфраструктуры для агентов. 16 июня вышел Android 17 с API 37, а 9 июня появился Android CLI 1.0. Теперь проект можно собирать из командной строки.
Вдобавок с 30 сентября разработчиков ждёт обязательная верификация в четырёх странах, а в Play сервисный сбор отделяется от платёжного. Разобрали дайджест июня — кто платит, кто мигрирует и что ломается.
Привыкли, что приложение ждёт, пока вы сами нажмёте кнопку? В Android 17 Google меняет правила: разработчик аннотирует функции приложения, и ИИ-агент может дергать их через Jetpack, получая доступ к локальному состоянию.
Приложение перестаёт быть островом и становится частью инфраструктуры для агентов. 16 июня вышел Android 17 с API 37, а 9 июня появился Android CLI 1.0. Теперь проект можно собирать из командной строки.
Вдобавок с 30 сентября разработчиков ждёт обязательная верификация в четырёх странах, а в Play сервисный сбор отделяется от платёжного. Разобрали дайджест июня — кто платит, кто мигрирует и что ломается.
Forwarded from Android Broadcast
Команда Android в Банки.ру полторы недели дебажила Seamless-авторизацию (вход по номеру через
HTTP Header Enrichment): на iOS всё стабильно, на Android соединения рвались случайным образом. Логи врали, таймаут без причины, снифать мобильный трафик оператора нельзя, а сам оператор банил номер за десятки попыток авторизации подряд.Причина не в бэкенде и не в DNS. Когда открывается
Custom Tab для SSO, Activity приложения уходит в onPause() → onStop(). По документации Chrome, браузер должен поднимать process importance приложения через bound KeepAliveService, и процесс не попадает под сетевые ограничения. Но проприетарные слои энергосбережения Samsung и Xiaomi этот механизм игнорируют и убивают процесс по таймеру, не глядя на bound services. У Huawei логика другая — он смотрит на реальный сетевой трафик и не трогает активный процесс, поэтому там всё работало стабильно.Фикс —
ForegroundService с типом shortService:override fun onCreate() {
super.onCreate()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
startForeground(
NOTIFICATION_ID,
createNotification(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE,
)
} else {
startForeground(NOTIFICATION_ID, createNotification())
}
}`shortService
доступен с Android 14 (лимит ~3 минуты, для 10–15 секунд поллинга с запасом), на более старых версиях работает как обычный ForegroundService. Процесс получает importance PERCEPTIBLE_APP_ADJ, и даже Samsung не трогает foreground service на One UI 6+.
‼️ ВАЖНО: сервис стартует и работает, даже если пользователь запретил приложению уведомления — POST_NOTIFICATIONS` для запуска foreground service не требуется, просто плашка не появится в шторке.Хороший повод лишний раз не доверять только официальной доке по process lifecycle и тестировать не на одном Pixel, а хотя бы на паре вендоров с разной агрессией энергосбережения.
🔗 Полная статья — там же разбор всех отвергнутых гипотез (DNS, оператор, регион) и код привязки к жизненному циклу SSO.
#Android #AndroidDev
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Compose Broadcast
Media is too big
VIEW IN TELEGRAM
37 минут от Sebastian Aigner и Marton Braun (JetBrains) про всё, что вышло за последний год. Хорошо структурированный доклад: общие изменения, потом iOS, потом Web.
Ключевое:
👉 Navigation 3 — стабильный в CMP. Бэкстек это просто
SnapshotStateList<NavKey>, которым управляешь сам. Адаптивные Scene-API, нативные iOS-жесты, browser history на Web из коробки.👉 Compose Hot Reload — стабильный, встроен в новые проекты без настройки. Работает и с AI-агентами: IDE подхватывает правки в файлах и перезагружает UI сама.
👉 @Preview унифицировали:
androidx.compose.ui.tooling.preview.Preview теперь работает в commonMain. Прошлые аннотации deprecated.👉 iOS: параллельный render pipeline по умолчанию в 1.11 (+20% на сложных лейаутах),
placedAsOverlay для нативных Liquid Glass-компонентов, полноценный нативный ввод с magnifier / translate / autofill / кастомными IME.👉 Web (beta):
HTMLElementView для HTML прямо в Composition, VoiceOver через семантику, Coil на web workers.👉 Из цифр в докладе: Kuaishou (250M DAU) и Tencent Video (340M MAU) уже работают на CMP-экранах. По iOS-блоку видно, что команда за год реально закрыла большинство «но» для старта
0:00 Вступление: что такое Compose Multiplatform
2:04 Масштаб: Perk, Alipay, Kuaishou, Tencent
4:06 Демо: структура нового проекта
5:40 Compose Hot Reload
8:49 Паритет с Jetpack Compose
10:24 Navigation 3
16:05 Единая аннотация @Preview
17:39 iOS: новый pipeline рендеринга
19:43 iOS: Liquid Glass и overlay interop
27:00 iOS: нативный ввод текста
31:11 Web: HTML interop
33:46 Web: доступность и производительность
35:50 Итоги
#ComposeMultiplatform #KMP #Navigation3 #KotlinConf
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Kotlin Adept Notes (Alex Panov)
Обманчивая легкость из-за AI
Продолжая тему захода в чужие роли с помощью AI, в комментариях справедливо отметили, что AI лишь создает иллюзию легкости. И это действительно так, особенно когда речь идет о легаси-проектах, в которых весь контекст хранится в головах разработчиков.
Мне нужно было всего лишь вынести в публичное API некоторую функциональность из Telegram-бота. При этом бэкенд был написан на Kotlin🏝
Казалось, что это просто подарок судьбы и все можно сделать с агентом за пару часов. Но что-то пошло не так🤔
🔴 AI отлично подстраивается под проект и хорошо работает по аналогии. Но если проект состоит из большого количества легаси и в нем используется множество разных подходов, то AI просто не знает, как делать правильно. И ты тоже не знаешь 🙃
🔴 API в бэкенде — это только верхушка айсберга. Пришлось разбираться с кучей технологий: как работать с очередями в RabbitMQ, как читать логи в Elastic, как устроен отдельный сервис авторизации, как делать миграции в MongoDB и другим зоопарком внутренних решений.
🔴 Несмотря на один и тот же язык, подходы в бэкенде и мобильной разработке могут значительно отличаться, что тоже создает когнитивную нагрузку.
В итоге вместо пары часов мое путешествие по бэкенду затянулось на несколько недель, хотя задача была далеко не самой сложной.
При этом эта история не масштабируется: нельзя просто дать любому разработчику подписку на LLM и ожидать, что он сможет сделать что угодно в любой области.
Продолжая тему захода в чужие роли с помощью AI, в комментариях справедливо отметили, что AI лишь создает иллюзию легкости. И это действительно так, особенно когда речь идет о легаси-проектах, в которых весь контекст хранится в головах разработчиков.
Мне нужно было всего лишь вынести в публичное API некоторую функциональность из Telegram-бота. При этом бэкенд был написан на Kotlin
Казалось, что это просто подарок судьбы и все можно сделать с агентом за пару часов. Но что-то пошло не так
В итоге вместо пары часов мое путешествие по бэкенду затянулось на несколько недель, хотя задача была далеко не самой сложной.
При этом эта история не масштабируется: нельзя просто дать любому разработчику подписку на LLM и ожидать, что он сможет сделать что угодно в любой области.
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Compose Broadcast
Честный кейс от разработчицы: она в одиночку перевела приложение на 170+ экранов с Nav2 на Nav3 🤯. Не пересказ доков, а грабли из прода. Объем работы: 302 файла (по сути весь app), 2 недели разработки с овертаймами, ~1.5 недели стабилизации, 1 хотфикс.
Что стоит забрать себе ещё до старта:
Поэтапно не выйдет. Обратной совместимости между Nav2 и Nav3 нет, мигрируешь либо всё сразу, либо никак. Отсюда огромный affected area и главная организационная боль: команда не фризила разработку, коллеги параллельно пилили новые экраны на старой навигации. Чем дольше тянешь, тем дороже разгребать merge-конфликты. Вывод: закладывай отдельный спринт и закрывай быстро, не размазывай.
Bottom Sheets из коробки в навигации нет. Если у тебя, как у автора, шторки живут внутри навигационного стека, готового решения на старте не было. Пришлось городить обёртку вокруг
entry<> с флагом в metadata и вручную разруливать, что рисовать через ModalBottomSheetLayout, а что через NavDisplay:val NavEntry<out NavKey>.isBottomSheet: Boolean
get() = metadata["isBottomSheet"] as? Boolean == true
NavDisplay(
entries = navigationState.toEntries(mainEntryProvider)
.filter { it.isBottomSheet.not() },
onBack = { navigator.goBack() },
)
Сейчас это решается официально через BottomSheetSceneStrategy, свой костыль автор потом выкинула. Мигрируешь сегодня — сразу проверь, что шторки ложатся на
SceneStrategy, а не переоткрывай этот велосипед. ⚠️ И отдельный подвох: шторка часть стека, и если перед переходом на следующий экран не закрыть её руками, back вернёт её обратно. Легко забыть.Сериализация уронит тебя уже в проде. 💥 Всё, что прокидываешь через навигацию, должно быть
@Serializable. Автор прокинула entryPoint: NavKey (чтобы при блокировке юзера возвращать на нужный экран через несколько назад), а сам NavKey сериализуемым не был:Fatal Exception: kotlinx.serialization.SerializationException
Ловушка в том, что краш не в обычном флоу, а в отдельных сценариях восстановления, поэтому проходит ревью и ручные тесты, а ловится только у юзеров. Лечится обёрткой:
@Serializable
open class NavStateSerializable : NavKey
Мой вывод: миграция оправданная, если на карте планшеты/фолды и adaptive layouts (тут Nav3 реально снимает боль), а навигация уже на Compose. Но держи в голове, что это не «обновить либу», а big-bang рефактор с регрессиями. Я бы не лез, если сидишь на фрагментах (сначала выпиливать их), поджимают сроки или свой навигатор и так стабильно работает.
🔗 Полный разбор с кодом и схемами на Medium
#Compose #Navigation3 #Android
Please open Telegram to view this post
VIEW IN TELEGRAM