Android Broadcast
14.5K subscribers
3.83K photos
397 videos
11 files
6.3K links
Подборка новостей и статей для Android разработчиков.

Реклама и связь с автором @ab_manager

РКН https://abdev.by/rkn_tg_ab #MQRZR
Download Telegram
Вот реальная история, как знание механики работы ViewModel спасло мне вечер 👇

У меня приложение на Compose и Jetpack Navigation 3 (работает на основе состояния Back Stack). Экран «Навигатор файлов» открывает папки рекурсивно: по сути это тот же экран, но с другими данными. Все данные — из одной и той же ViewModel.❗️Баг: при переходе в папку навигация срабатывает, UI не меняется. Современные ИИ подсказали общие вещи, но не помогли — промты, видимо, подвели (тут мне ещё надо прокачать знания) 🙂

Вспомнил ключевой факт про архитектуру:
👉 Все ViewModel живут в ViewModelStore.
👉 В пределах одного ViewModelStoreOwner (Activity/Fragment/NavBackStackEntry) получение ViewModel по умолчанию идёт по типу.
👉 Если нужно несколько экземпляров одного типа на одном owner’е — используем key.

Решение в одну строку — привязать ключ к ViewModel, связанный с текущей папкой:
@Composable
fun FileNavigator(
folderId: Id,
modifier: Modifier = Modifier,
) {
// новый folderId → новый экземпляр ViewModel → новый UI-стейт
val viewModel: FileNavigatorViewModel = viewModel(
key = "files(rootId='$folderId')"
)
// ...
}


Мини-чеклист, если ловите такой баг
👉 Один экран используется повторно с разными параметрами? → Нужен key.
👉 Меняется route, но owner тот же? → key обязателен.
👉 Используете Hilt/Koin? → У этих функций тоже есть параметр key (hiltViewModel(key=...), koinViewModel(key=...)).
👉 key должен детерминированно зависеть от входных данных (например, folderId).
👉 При навигации назад убедитесь, что ViewModel освобождается ожидаемо.

Ещё нюанс - если у вас сложная иерархия графов, проверьте, к какому ViewModelStoreOwner вы реально привязаны.

Рекомендую посмотреть мои видео по теме:
📹 Разбор Jetpack Navigation 3
🪙 Полный разбор Jetpack ViewModel в Android и Kotlin Multiplatform

#android #compose #androidjetpack #viewmodel #архитектура
Please open Telegram to view this post
VIEW IN TELEGRAM
🤖 Как проверить, какие комбинации фичей поддерживает камера смартфона

Современные смартфоны умеют снимать с HDR, 120 FPS и стабилизацией, но вот какая комбинация этих фич реально доступна — загадка. Например, стабилизация часто работает только при 1080p, а 60 FPS не всегда доступны в 4K.

С выходом Jetpack CameraX 1.5 появилось API GroupableFeature и новые параметры для SessionConfig, которые позволяют из кода проверить, какие функции камера может использовать одновременно.

// Пример проверки неподдерживаемых комбинаций
val unsupportedFeatures =
mutableSetOf<GroupableFeature>()
val appFeatureOptions =
setOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION)
appFeatureOptions
.filterNot { it in currentFeatures }
.filter { featureOption ->
cameraInfo.isFeatureGroupSupported(
SessionConfig(
useCases = useCases,
requiredFeatureGroup =
currentFeatures + featureOption
)
)
}
.forEach { unsupportedFeatures.add(it) }


Так можно заранее отсеять неподдерживаемые сочетания — например, когда HDR и стабилизация не работают вместе при 60 FPS 🎥

Подробнее в статье (EN)

#android #camerax #Jetpack #androidjetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Вышел Jetpack WorkManager 2.11.0

Что важного в новой версии:

❗️ minSdk: 23 (Marshmallow). Lollipop (API 21–22) больше не поддерживается.

🎉 Новое API: setRemoteSessionTimeoutMillis() в Configuration.Builder — задаёт время жизни сессии RemoteWorkManager после последнего использования.
class App : Application(), Configuration.Provider {
override fun getWorkManagerConfiguration(): Configuration {
return Configuration.Builder()
// Сколько живёт RemoteWorkManager-сессия после последнего использования
.setRemoteSessionTimeoutMillis(TimeUnit.MINUTES.toMillis(5))
.build()
}
}


🎉 Тестирование: TestDriver.stopRunningWorkWithReason(...) — можно останавливать выполняющуюся работу с указанием причины.
Зачем: удобно эмулировать внешние условия (остановку системой/приложением) и проверять, что код корректно реагирует на «принудительное завершение».
// Arrange
val request = OneTimeWorkRequestBuilder<MyWorker>().build()
WorkManager.getInstance(context).enqueue(request).result.get()

// Act
val testDriver = WorkManagerTestInitHelper.getTestDriver(context)!!
testDriver.stopRunningWorkWithReason(
request.id,
/* reason */ 0 // укажите код причины, например ваш тестовый/константу из проекта
)

// Assert — далее проверяете ожидаемое состояние


🛠 Также сделали исправление багов

#android #jetpack #workmanager #jetpackupdate #androidjetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥 Jetpack CameraX теперь разрабатывается вместе с командой камеры Pixel

Вышла первая альфа-версия Jetpack CameraX 1.6.0

Главное изменение — переход на унифицированный высокопроизводительный стек камеры, тот самый, что используется в приложении камеры Pixel. Этот стек известен как CameraPipe — и теперь CameraX и Pixel Camera развиваются совместно.

Новый стек принесёт:
👉 более быструю и стабильную инициализацию камеры,
👉 консистентную обработку фреймов,
👉 и улучшенную совместимость между устройствами.

Повод задуматься для миграции на CameraX для тех, кто не решался это сделать

#android #jetpack #androidjetpack #camerax #camera
🚀 Вышел SavedState 1.4.0 — теперь с поддержкой nullable типов

Saved State — это библиотека Jetpack, которая помогает сохранять и восстанавливать состояние при пересоздании, например из-за изменений конфигурации в Android или при выгрузке процесса системой. Поддерживает Kotlin Multiplatform


Вышел androidx.savedstate:1.4.0, и в этом обновлении основное внимание уделено улучшению API. Ключевое изменение - добавлена нативная поддержка nullable типов в SavedStateRegistryOwner.saved, а также в функциях encodeToSavedState() и decodeFromSavedState() — теперь можно напрямую сохранять и восстанавливать null-значения без костылей.

// Теперь это работает корректно без дополнительных проверок.
var name: String? by savedState(saved = "name", default = null)


#android #jetpack #kotlin #kmp #jetpackupdate #androidjetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Вышел Core SplashScreen 1.2.0

Что нового:
🌙 Добавлен атрибут isLightTheme для тем SplashScreen — можно корректно выбирать оформление под светлую/тёмную тему
🖼 Иконка загрузки теперь корректно подтягивается через AppCompatResources (улучшена поддержка ресурсов и векторных изображений)
👉 Убрали ручное объявление обращения к новым API — теперь всё автоматически моделируется при сборке с AGP ≥ 7.3 и R8 ≥ 3.3
🐘 Для AGP 8.1 и выше — всё работает “из коробки” без дополнительных настроек ⚙️ (рекомендуется обновление до этой версии AGP или выше)

#android #jetpack #androidjetpack #jetpackupdate
Please open Telegram to view this post
VIEW IN TELEGRAM
‼️ Google отменяет Compose Material Icons

С релизом Compose Material 3 — версии 1.4.0 Google сделала радикальный шаг: библиотека androidx.compose.material.icons исключена из Material3 и больше не рекомендуется к использованию.

Что произошло
👉 Material Icons удалены из актуального релиза Material3 1.4.0
👉 Поддержка библиотеки прекращена
👉 Можно подключить вручную, но это временная мера для тех, кто не успел мигрировать

Основная причина отказа - негативное влияние на скорость сборки. Библиотека Material Icons тащит весь огромный набор иконок. Это ощутимо увеличивает build time крупных Android и Compose Multiplatform проектов.

Google предлагает переходить на Vector Drawable XML в Android или Compose Multiplatform ресурсах. Скачивайте иконки с вкладки Android на странице Material Symbols и храните в ресурсах проекта

Преимущества использования Material Symbole:
✔️ актуальный набор иконок
✔️ минимальный вес и отсутствие лишних зависимостей
✔️ предсказуемое время сборки
✔️ лучший контроль над ресурсами проекта

❗️ Обновлений библиотеки Material Icons не будет!

Источник - официальная документация Android Jepack

Благодарю подписчика Evgeny F. за то, что обратил внимание на изменение.

#Android #AndroidJetpack #Material3 #Compose #CMP
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Google выпустила androidx.webgpu:webgpu:1.0.0-alpha01 — WebGPU нативно в Android-приложения.

WebGPU — это новый графический и вычислительный API, который приходит на смену устаревающему WebGL. Его цель — дать разработчикам современный доступ к GPU для тяжёлых визуальных и вычислительных задач как в вебе, так и теперь — в Android, благодаря androidx.webgpu. Если упрощённо — WebGPU открывает дверь к автоматически оптимизированной работе с видеокартой без необходимости использовать низкоуровневые графические движки.

Что даёт WebGPU разработчикам:
🧩 Современная графика уровня Vulkan/Metal/DX12
⚙️ Compute-шейдеры для вычислений прямо на GPU
🚀 Высокую производительность рендеринга и ML-вычислений
🔁 Кроссплатформенность: единый подход Web + Android (и не только)
📦 Потенциально меньше нативного кода на C++/NDK
🧪 Удобный доступ к GPU-фичам для прототипов и экспериментов

Версия для Android пока в alpha, API нестабилен, документации немного. Но это важный шаг: Google фактически легализует WebGPU как будущий GPU-базис на Android.

#AndroidDev #Android #Jetpack #AndroidJetpack #WEB #GPU
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Google взялась за упрощение Picture‑in‑Picture

PiP на Android долго был зоопарком: разный API на версиях, разный UI‑стейт, много if (SDK_INT…) и бойлерплейта. Новая Jetpack‑библиотека androidx.core:core-pip как раз и создана, чтобы это спрятать: она выравнивает вызовы PiP между версиями Android, даёт единый способ задавать параметры (особенно для видео/плееров), объединяет разрозненные колбэки состояния PiP и уменьшает количество кода за счёт готовых пресетов действий для типовых сценариев.

Требования: обновляем Activity

Чтобы всё это заработало, мало просто подключить core-pip — нужно обновиться до свежей Activity 1.13.0 (пока в альфе). В этой версии есть новые API для отслеживания состояния PiP (PictureInPictureUiStateCompat и слушатели), на которых удобно строить логику поведения UI, когда окно уходит в PiP или, например, «прячется» в угол.

// Пример кода: реагируем на состояние PiP
class PlayerActivity : ComponentActivity() {

private val pipUiStateListener =
Consumer<PictureInPictureUiStateCompat> { state ->
if (state.isStashed) {
/* спрятать контролы плеера */
} else {
/* показать контролы плеера */
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// ... инициализация UI / плеера ...
addOnPictureInPictureUiStateChangedListener(pipUiStateListener)
}

override fun onDestroy() {
removeOnPictureInPictureUiStateChangedListener(pipUiStateListener)
super.onDestroy()
}
}

🔗 Подробности про библиотека в документации

#Android #AndroidDev #AndroidJetpack #PIP
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Начали разработку Room 3.0, который станет полностью KMP-библиотекой с поддержкой JS и WASM, а также избавится от легаси.

Разработчики популярного ORM для Android и KMP решили выпустить мажорную версию, чтобы отразить всю важность изменений:
👉 Полный переход на androidx.sqlite driver API.
👉 Генерация кода будет только на Kotlin, никакой больше Java.
👉 APT и KAPT больше не будут поддерживаться. Остается только KSP.
👉 Room API теперь будет делаться в подходе "Kotlin Coroutines first", делая весь ORM асинхронным по умолчанию.

Что нас ждет из новых фичей и возможностей:
👉 Появится полноценная поддержка JS и WASM-таргетов.
👉 Можно будет добавить собственные возвращаемые типы в Room. Например, Room, RxJava, Paging и пр.

Новая версия Room будет выпущена под новым пакетом androidx.room3. Room 2.X не получит новых фичей, только багфиксы.

🔗 Источник - блог Android Developers.
🔗 Release Notes Room 3.0.0-alpha01

#Android #AndroidDev #Room #SQLite #Jetpack #AndroidJetpack #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Compose Broadcast
⚙️ Jetpack Compose 1.11 — стабильный релиз! 🚀

Что нового:
👉 Визуальная отладка переходов Shared Elements
👉 Переработанная поддержка трекпадов — теперь работают как мышь и распознают жесты
👉 Preview Wrappers для более быстрой работы с превью
👉 Host Defaults для KMP-проектов
👉 Testing APIs v2 для корутин
👉 Экспериментальные API: Styles, MediaQuery, Grid, FlexBox

Подробности по каждому пункту — отдельными постами в @compose_broadcast

#Compose #Android #AndroidJetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Jetpack Telecom 1.1.0 добавил то, чего не хватало VoIP-приложениям с самого начала — историю звонков прямо в системном дайлере.

До этого момента пропущенный звонок в Telegram или любом другом VoIP-приложении требовал переключиться в само приложение, найти вкладку с историей и перезвонить оттуда. Теперь это можно делать прямо из нативного дайлера Android.

Работает через два новых механизма. Первый — интеграция лога звонков. Приложение регистрирует звонки через TelecomManager.addCall, и они автоматически попадают в системную историю. Для обратного звонка нужно зарегистрировать intent-фильтр на TelecomManager.ACTION_CALL_BACK и правильно обработать EXTRA_UUID, который система отдаёт вместе с вызовом. UUID генерирует CallControlScope.getCallId в момент регистрации звонка — его и нужно хранить, чтобы потом разрезолвить детали вызова.

Второй механизм — исключение из лога. Не каждый звонок стоит светить в системной истории, и теперь это явно контролируется через флаг isLogExcluded = true в CallAttributesCompat. Например, эфемерные или приватные звонки можно просто не записывать.

‼️ ВАЖНО: фичи доступны только на Android 16.1 (SDK 36.1) и выше. Кроме того, нативные дайлеры используют package allowlist для контроля того, какие VoIP-приложения отображаются в истории. Роллаут идёт поэтапно, первым подключился Google Meet. Для локального тестирования Google рекомендует Telecom Sample Dialer из platform-samples.

Меня радует сам вектор: Google последовательно закрывает разрыв между VoIP и нативной телефонией. Жаль, что allowlist пока ограничивает возможности сторонних приложений. Печально то, что это делают так поздно, когда звонки не по телефону делают уже 5–10 лет.

🔗 Источник: android-developers.googleblog.com

#Android #Telecom #AndroidJetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Вышел Room 3.0 Stable и это не просто поднять версию, а надо мигрировать на новую библиотеку!

Google зарелизил Room 3.0 (androidx.room3), и это самый серьёзный мажор Room за всю его историю: библиотеку переписали под Kotlin Multiplatform с нуля.

Ради обратной совместимости 3.0 живёт в отдельном пакете и maven-координатах (androidx.room3:room3-runtime вместо androidx.room:room-runtime), поэтому 2.x и 3.x спокойно уживаются в одном проекте на разных базах данных. Мигрировать можно постепенно, модуль за модулем.

Cама миграция не косметическая. Cursor и SupportSQLite слой под Android убраны, всё теперь через корутины:

// было (Room 2.x)
roomDatabase.query("SELECT * FROM Song").use { cursor -> ... }

// стало (Room 3.x)
roomDatabase.useReaderConnection { connection ->
connection.usePrepared("SELECT * FROM Song") { stmt -> ... }
}


KAPT для Room больше не работает вообще, только KSP и весь код генерируется на Kotlin. InvalidationTracker.Observer заменили на Flow (createFlow()). Конфигурация через Executor тоже ушла, теперь CoroutineContext.

Из нового:
🔥 FTS5 через @Fts5
🔥 поддержка JS и WasmJS (драйвер поверх Web Worker и OPFS)
🔥 кастомные DAO return type converters. Paging, RxJava и LiveData интеграции теперь строятся на одном общем API вместо трёх разных костылей ранее.

‼️ ВАЖНО: это не «обновил зависимость и всё скомпилировалось». Если у тебя много прямых обращений к SupportSQLiteDatabase или ты завязан на Executor-конфигурацию, то закладывай время на миграцию.

#Android #AndroidDev #KMP #Web #WASM #AndroidJetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Вышел AndroidX Tracing 2.0.0 — серьёзный апгрейд трейсинга

Tracing - это инструмент для низкооверхедного in-process трейсинга — записи временных срезов выполнения кода прямо внутри процесса приложения.

Полезен, когда нужно:
👉 понять, где именно тормозит код (особенно в корутинах);
👉 собирать детальные трейсы в поле / на проде, а не только в Studio;
👉 инструментировать библиотеки без жёсткой привязки к Android;
👉 потом мёржить эти трейсы с системными (Perfetto).

Особенно пригодится:
👉 Android-разработчикам, которые занимаются перформансом;
👉 авторам библиотек (в т.ч. KMP);
👉 командам с тяжёлым использованием корутин;
👉 тем, кто пишет бенчмарки (хорошо дружит с AndroidX Benchmark 1.5+).

Выход 2.0 обусловлен полностью новым API и архитектурой работы:
👉 Появился полноценный in-process tracing с собственным буфером (не зависит от system trace buffer).
👉 Новая модель: TraceDriver + Tracer + TraceSink (можно подключать свои бэкенды).
👉 Настоящая поддержка корутин с отслеживанием suspend/resume и переключений потоков.
👉 Поддержка KMP (Android + JVM).
👉 Существенно ниже оверхед по сравнению со старым android.os.Trace / trace {}.

Старый API не deprecated его по-прежнему рекомендуют для редких критичных событий, которые обязаны попасть в system trace.

🔗 Полные release notes по ссылке

#AndroidDev #Perfromance #AndroidJetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Вышел AndroidX WebKit 1.17.0 — обновленная навигация и контроль над кэшем

Самое полезное в новом минорном релизе:
👉 WebViewCompat.navigate наконец-то нормальная замена loadUrl. Можно заменять страницу в истории, получать объект Navigation и корректно сохранять/восстанавливать заголовки. Для приложений, где WebView — не просто «открыть ссылку», а нормальный флоу, это давно было нужно.

if (WebViewFeature.isFeatureSupported(WebViewFeature.WEBVIEW_NAVIGATE_EXPERIMENTAL_V1)) {
val params = NavigationParameters.Builder()
.setShouldReplaceCurrentEntry(true) // заменяет текущую запись в истории
.addAdditionalHeader("X-Custom-Header", "value")
.build()

val navigation: Navigation
= WebViewCompat.navigate(webView, "https://example.com", params)

// navigation можно потом матчить в NavigationListener
}


👉 Контроль HTTP-кэша через Profile.getHttpCache. Можно посмотреть квоту и при необходимости подкрутить. Полезно, если много статики, или наоборот — когда кэш только место жрёт.

if (WebViewFeature.isFeatureSupported(WebViewFeature.HTTP_CACHE_MANAGER)) {
val profile = ProfileStore.getInstance().getOrCreateProfile("my_profile")
val httpCache = profile.httpCache // или profile.getHttpCache()

// Посмотреть текущую квоту
val currentQuota = httpCache.quotaBytes
val defaultQuota = httpCache.defaultQuotaBytes
val isDefault = httpCache.isUsingDefaultQuota

// Задать свою квоту (например, 50 МБ)
httpCache.setQuotaBytes(50L * 1024 * 1024)

// Или вернуть автоматическое управление
// httpCache.useDefaultQuota()
}


👉enqueuePreconnect — можно заранее поставить preconnect в очередь, не заставляя WebView стартовать прямо сейчас.

👉 Можно отключить автоматическую загрузку фавиконок (setDownloadFaviconsEnabled). Мелочь, но экономит память и трафик, особенно если иконок много.

👉 Плюс Android Lint, который теперь ругается, если кастомный WebViewClient не переопределил onRenderProcessGone. Полезно, потому рендерер падает регулярно.

🔗 Подробности релиза

#Android #AndroidDev #WebView #AndroidJetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Вышел стабильный Jetpack Glance 1.2.0: превью виджета из композиции и альфа у картинок

Jetpack Glance - библиотека для разработки с Android Desktop Widget и Wear Tile на Compose


Glance 1.2.0 вышел 26 августа 2026. С релиза 1.1 прошло больше года, в stable доехало то, что жили в альфе с мая 2025 🤯

Главное для виджетов на домашнем экране - генерация превью на Android 15+. Переопределяешь GlanceAppWidget.providePreview, публикуешь через GlanceAppWidgetManager.setWidgetPreviews. Композиция одноразовая, без рекомпозиции и эффектов. На более старых версиях по-прежнему статическое превью.

Что еще нового:
👉 alpha у Image (0f..1f)
👉 MultiProcessGlanceAppWidget, если ресиверы живут в разных процессах
👉 лямбды больше не experimental
👉 previewSize у requestPinGlanceAppWidget
👉 повысили minSdk до Android 6.0 (API level 23)

Legacy glance-wear-tiles deprecated в пользу androidx.glance.wear.

#Android #AndroidDev #Compose #AppWidgets #AndroidJetpack #WearOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Jetpack PDF вышел в Beta. Встраиваемый PDF в Android приложении уже можно пробовать

Google довёл Jetpack PDF до беты. Это не обёртка над PdfRenderer, а готовый вьюер внутри своего UI: открыть документ, зум/скролл, поиск, выделение текста, стилус, двухстраничный режим на планшете, клавиатура и мышь.

Точка входа: PdfViewerFragment. Рядом Compose`PdfViewer` и PdfViewerState, но они ещё за @ExperimentalPdfApi.

Редактирование тоже есть, и это главная причина смотреть библиотеку сейчас, а не через полгода. EditablePdfViewerFragment даёт аннотации (перо, маркер, ластик, undo/redo через androidx.ink), заполнение форм и запись правок через PdfWriteHandle. Есть распознование данных (OCR)

// просмотр + правки (experimental)
@OptIn(ExperimentalPdfApi::class)
class EditorFragment : EditablePdfViewerFragment()

// включить перо / маркер / формы
fragment.isEditModeEnabled = true

// сохранить драфт в файл
lifecycleScope.launch {
fragment.applyDraftEdits().use { handle ->
handle.writeTo(outputPfd)
}
}


Рендер и чтение бэкпортировали до minSdk 28 (Android 9.0)

Бета релиз значит публичные API просмотра зафиксировали, в прод можно тащить аккуратно. Теперь можно пробовать отказаться от коммерческих решений на замену стандартного решения, только вот minSdk не всем может позволить

🔗 Релизные заметки
🔗 Как встроить в приложение

#Android #AndroidDev #AndroidJetpack #PDF
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 В Jetpack Emoji2 1.7.0 (пока только первая альфа) решили сделать перфоманс релиз!

Что уже сделали:
👉 размер метаданных: ~2.2 MB → ~80 KB
👉 аллокации на старте: 24 178 → 82
👉 ускорили сканирование доступных эмоджи

В прод тащить НЕ стоит. Имеет смысл смотреть, если профилируешь старт или видишь emoji2 в памяти.

#Android #AndroidDev #AndroidJetpack
Please open Telegram to view this post
VIEW IN TELEGRAM