Мобильная разработка
13.2K subscribers
912 photos
237 videos
3.03K links
Актуальное по мобильной разработке — Android, iOS, кроссплатформа

Разместить рекламу: @tproger_sales_bot
Правила общения: https://tprg.ru/rules
Другие каналы: @tproger_channels
Сайт: https://tprg.ru/site

Регистрация в перечне РКН: https://tprg.ru/oVBP
Download Telegram
Папка lib превратилась в лабиринт: модуляризация по фичам во Flutter

История типовая. Сначала lib, несколько экранов, папка моделей и один файл сервисов на всё. Приложение выходит, все довольны. Потом фич больше, команда больше, и однажды в моделях триста файлов, в сервисах шесть тысяч строк, а новому инженеру нужны недели, чтобы понять, куда вообще что добавлять.

Автор настаивает, что это не проблема дисциплины, а проблема структуры: код изначально не был устроен так, чтобы переживать рост. Модуляризация по фичам не новый фреймворк и не замена Clean Architecture или DDD, она берёт принципы обоих и применяет их к каждой фиче отдельно, чтобы кусок был самодостаточным и тестировался независимо.

Разбор идёт от минусов layer-first до сборки всего вместе. Актуально, если команда в одной кодовой базе растёт к двадцати с лишним людям.

#flutter
👍2
Jetpack XR SDK дошёл до беты: можно тащить XR в продакшен-процесс

Порт существующего 2D-приложения в XR перестал быть исследовательским проектом: Jetpack SceneCore, ARCore for Jetpack XR и XR Runtime вышли в бету, Jetpack Compose for XR обещают следом.

Формулировка Google прямая: API стабилизируются, и это хороший момент встраивать их в рабочие процессы, а не держать в песочнице. Делается это теми же инструментами Android, которыми вы уже пользуетесь, отдельный стек учить не нужно.

Релиз сфокусирован на базовых кирпичах SDK, так что смотреть стоит на них, а не на витринные демо. Что именно вошло в бету, перечислено в анонсе.

#android
Сигнатура с Unit врёт о том, чем функция может закончиться

Пример из статьи: fun signDocument(documentId: UUID, code: String): Unit. Unit в Kotlin означает, что функция отработала и не вернула ничего осмысленного, примерно как void в Java. Понятно? А теперь скажите по одной сигнатуре, что будет, если код неверный, документ уже подписан или его вообще нет.

Сигнатура об этом молчит. Про доменные ошибки вызывающий узнаёт из исключений, документации или чужой памяти, и компилятор ему здесь не помощник.

Сергей Чернов, который занимается аутентификацией и верификацией в финтех-платформе, разбирает, как вернуть эти случаи в тип возвращаемого значения и обрабатывать их функционально. Статья в блоге Kotlin.

#kotlin
🔥2
Как Google разводит по изолированным доменам автомобильный Android

AAOS SDV, версия Android Automotive для программно-определяемых автомобилей, построена на виртуализации: Google использует Cuttlefish, чтобы разделять системы, живущие в одной машине на одном железе.

Прошлые анонсы были про фичи, а этот текст про то, как устроена безопасность: доменная изоляция как фундамент и виртуализация как способ развести сосуществующие инстансы.

Читать стоит, если смотрите в сторону автомобильных проектов, но и обычному мобильному разработчику полезно как модель: те же приёмы изоляции постепенно спускаются в потребительский Android. Как она устроена, расписано в разборе Google.

#android
Движок IntelliJ уехал из IDE и работает в VS Code по LSP

В VS Code уже ставится расширение Java and Kotlin by IntelliJ IDEA с идентификатором JetBrains.intellij-server. Это не оболочка, изображающая IDE, а языковой движок IntelliJ, говорящий по протоколу LSP.

Причину переезда называют прямо: агенты уже ходят в языковые серверы за быстрым и детерминированным поиском по коду, и в перспективе это экономит токены. Поэтому движок и вынесли наружу.

Практические оговорки. Расширение привязано к VS Code версии 1.105.1 и выше, редакторы на его основе вроде Cursor тоже считаются, а одиночный .java-файл без проекта не заработает. Preview-сборки умирают через 30 дней после релиза, зато для чистого Kotlin остаётся бесплатный языковой сервер под Apache-2. Инструкция по запуску.

#kotlin
3
Tinder срезал холодный старт на 47% через R8 Configuration Analyzer

Кодовая база росла вместе с приложением, и к моменту оптимизации около 70% кода оставались неоптимизированными: 17 dex-файлов, из них три выделены только под запуск. R8 был включён, но большую часть его работы блокировали keep-правила, и команда не могла определить, какие именно.

Это и закрывает новый R8 Configuration Analyzer. Он показывает оценки по shrinking, оптимизации и обфускации и подсвечивает слишком широкие, дублирующие и устаревшие keep-правила, включая те, что приехали из сторонних библиотек.

Итог после чистки: холодные старты минус 47%, размер загрузки минус 28,98%, до 61,5 МБ, а ANR по ощущению пользователя минус 28%. Цифры и скриншоты анализатора лежат в блоге Android Developers.

#android
Media3 1.11 добавил слоты Player в Compose и предзагрузку коротких видео через PlayerPool

Media3 это библиотека, на которой работает подавляющее большинство топовых медиаприложений под Android. В 1.11 изменения затронули воспроизведение, редактирование и UI-компоненты сразу.

Для тех, кто на Compose, главное в UI-модулях: настраиваемые слоты Player с готовыми дефолтами, интерактивные жесты, наблюдатели состояния и предзагрузка коротких видео через PlayerPool. Последнее прямо про ленты в стиле Reels, где следующий ролик должен стартовать мгновенно.

Помимо этого интеграцию с Cast обновили под SystemUI Output Switcher, добавили сетевое расширение на клиенте Ktor и утилиты муксинга для Ogg и WAV.

#android
Космос, Ferrari, котёнок в коробке: обои на рабочий стол выбирали часами, перебирая варианты один за другим. SpaceWeb и Типичный программист вспомнили это в анкете к 25-летию компании, вместе с любимым спортом и лучшим другом — тоже родом из школьных анкет.

Между вопросами — история аськи, скайпа, биткоина и самой компании с 2001 по 2026 год, плюс немного будущего. В конце — промокод на услуги SpaceWeb и ответ на вопрос какое ты хранилище информации!
1
Справочник по BLE во Flutter: от разрешений и MTU до архитектуры сервиса под продакшен

Туториалы по Flutter обычно заканчиваются на REST. Как только надо поговорить с пульсометром, умной лампой или своим железом, начинается Bluetooth Low Energy, где разрешения различаются между Android и iOS и даже между версиями Android, а жизненный цикл соединения имеет больше состояний, чем ожидаешь. Пакет flutter_blue_plus прячет платформенную боль, оставляя контроль над сканированием и обменом.

🔘 теория BLE, конфигурация обеих платформ, разбор рекламных пакетов при сканировании;
🔘 согласование MTU, обнаружение сервисов, чтение и запись, уведомления и дескрипторы;
🔘 спаривание, фоновая работа, обработка ошибок и архитектура сервиса под продакшен;
🔘 каждый фрагмент кода в справочнике разобран построчно.

#flutter
Kotlin, NDK и JNI: как позвать C и C++ из Android-приложения

Поводов спуститься в нативный код три: не хватает производительности, есть готовая библиотека на C или нужна функциональность уровнем ниже, чем даёт платформа. Инструментарий даёт Android NDK, а мостом между Kotlin или Java и нативной стороной работает JNI.

Разбор начинается с архитектуры этой связки, а не с копипасты первого рабочего примера: видно, какие слои участвуют, где проходят границы ответственности и в каком месте вы платите за переход через JNI.

Полезно как карта местности перед первым спуском, особенно если раньше нативный код в проекте трогал кто-то другой.

#kotlin
Android Skills специально строят так, чтобы их можно было выбросить

Google выпустил официальные Android Skills в апреле, отклик превзошёл ожидания, и теперь команда объясняет философию проекта и отвечает на накопившиеся вопросы.

Главный из них: почему официальных навыков так мало. Ответ в заголовке поста: они строятся с расчётом на депрекацию. Навык живёт ровно столько, сколько живёт разрыв между тем, что модель знает сама, и тем, что ей приходится подсказывать.

Практическая часть про то, что происходит при установке и использовании навыка. Понимание этой механики напрямую экономит и токены, и время, если вы работаете с агентом в Android-проекте.

#android
Compose Multiplatform 1.12.0 отдаёт запущенное приложение агенту через MCP

Вышла версия 1.12.0. Главное для тех, кто кодит с ассистентом: в Compose Hot Reload появился MCP-сервер, через который агент обращается к работающему приложению, а не угадывает его состояние по исходникам.

Помимо этого подтянули управление веб-ресурсами и дали более тонкий контроль над состояниями окна на десктопе.

Если у вас общий UI под Android и iOS, смотреть стоит именно на связку hot reload и агентов: это тот случай, когда инструмент меняет цикл правка-сборка-проверка, а не добавляет ещё один API в список. Заметка о релизе в блоге JetBrains.

#compose
Android 17 включает ECH на уровне всей системы

Google добавил в Android 17 поддержку Encrypted Client Hello: стандарт скрывает от сети, какие сайты открывает пользователь. Работает в паре с приватным DNS и прячет имя домена, шифруя его ключом, который расшифровывает только сам сайт.

Для разработчика тут две практические детали. Первая: ECH GREASE включён по умолчанию, устройство подмешивает фиктивные ECH-расширения к сайтам без поддержки, чтобы защищённые соединения не выделялись на общем фоне. Вторая: OkHttp уже втянул поддержку ECH в ядро библиотеки, так что сторонним приложениям она доступна.

В том же наборе Local Network Protection: приложение теперь обязано спросить разрешение, прежде чем сканировать локальную сеть или подключаться к устройствам в ней. Разбор в The Hacker News.

#android
👍5
iOS Safari уносит панели за экран при открытии клавиатуры, и лечится это одной строкой CSS

Сценарий узкий, но узнаваемый: полноэкранный мобильный редактор сделан оверлеем с position: fixed, сверху закреплённая панель инструментов, снизу навигация. Открывается системная клавиатура, и Safari укатывает весь ваш хром за пределы экрана.

🔘 воспроизводится только на коротком контенте, поэтому легко не поймать на тестах;
🔘 плясок с viewport в JavaScript не нужно: достаточно padding-bottom: 60vh на области редактирования.

#ios
Незарегистрированные приложения выпадут из Google Play 30 сентября

Google включает проверку разработчика: package name приложения должен быть зарегистрирован в Play Console. 99% приложений зарегистрировали автоматически, остальное на вас: проверьте список на главной Play Console. Осталось три недели, дальше приложение удаляют из Play глобально.

С той же даты установки проверяют у пользователей Бразилии, Индонезии, Сингапура и Таиланда, не только из Play: Galaxy Store, GetApps, HONOR и OPPO App Market, Palm Store, V-Appstore. Остальные страны подключат в 2027 году. Сборки, которые вы раздаёте мимо стора, регистрируются в Play Console, иначе они не поставятся на сертифицированные устройства.

Если приложений много, в июле заработали API: Android Developer ID Status API проверяет, зарегистрирован ли package name, Android Developer Console API регистрирует имена из CI/CD.

#android
В Китае генеративные фичи вашего iOS-приложения могут отвечать иначе

Вызовы Writing Tools и фреймворка Foundation Models вы пишете один раз, а отвечать на них в разных регионах будут разные модели. The New Stack со ссылкой на Reuters пишет, что Apple собрала для Китая отдельную модель при участии Alibaba: ни ChatGPT, ни Gemini, ни Claude предоставлять там свои сервисы не могут, поэтому опереться можно только на то, что разработано или одобрено внутри страны. Рядом с новой моделью должен работать Qwen, возможно и технологии Baidu.

Какая модель отвечает за какую часть Apple Intelligence, ни Apple, ни партнёры не объяснили. Даты запуска тоже нет, Reuters ждёт сервис в ближайшие месяцы.

Так что генеративные фичи придётся тестировать на китайском аккаунте отдельно. Промпт, отлаженный на европейском регионе, там может ответить иначе.

#ios
Код на C во Flutter дёргается из Dart напрямую, без обвязки под каждую платформу

Готовый код на C в приложении (кодек, крипта, обработка картинок) обычно заворачивают в platform channel, и обвязку пишут дважды: под Android и под iOS. Dart FFI этот слой убирает, Dart вызывает C-функцию сам.

Цена: сигнатуры руками. На каждую функцию объявляете два typedef, один в типах FFI (Int32 Function(Int32, Int32)), второй в дартовых (int Function(int, int)). А функция в библиотеке должна быть с C-совместимым ABI, иначе Dart не найдёт символ.

Загрузка зависит от платформы: на Android библиотека открывается по имени файла, DynamicLibrary.open('libnative_math.so'), в остальных случаях символ ищут в самом процессе приложения, DynamicLibrary.process().

Туториал на dev.to собирает минимальный проект и говорит, где FFI не нужен: под платформенные API Android и iOS ближе platform channels.

#flutter
1👍1