TGViewer
Channel Public Channel
Android Good Reads

Android Good Reads

@droidgr

Самые интересные статьи, видео и новости, связанные с Android разработкой. Не больше трёх материалов в день.

Размещение рекламы: @tanyasanovna
Subscribers
4.03K
Photos
420
Videos
17
Links
2.2K

Showing posts older than #2266 · Back to latest

Older Posts 20 shown
Post #2264 3.01K
Используем UseCase как функцию из DI

Идея в том чтобы описать функцию, использующую DI для обработки входных данных. В итоге получим тестируемую функцию, которую можно переиспользовать

Пример:

public class GoodReadsUseCase @Inject public constructor(
private val repository: Repository,
private val manager: Manager,
private val clock: Clock
) {

public suspend operator fun invoke(params: Params): Boolean {
return someServerLogic
}
}


Ну а внутри ViewModel это будет выглядеть как то так:

public class ViewModel @Inject constructor(
private val useCase: GoodReadsUseCase
) {
public suspend fun read(params: Params) {
val isBool = useCase(params)
}
}


Удобно и понятно на что писать тесты! Используем?
  • 🤷‍♂ 22
  • 👍 4
  • 😢 3
  • 🤓 2
Post #2263 3.11K
Защищаемся от MITM атак

Немного про безопасноть можно почитать тут OWASP Mobile 2024, а что можно предпринять, во избежании проблем:
👉 Использования HTTPS с TLS 1.2, 1.3. Валидные SSL/TLS сертификаты. Использовать HSTS (HTTP Strict Transport Security), который не позволяет свалиться обратно к HTTP

<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">yourdomain.com</domain>
</domain-config>
</network-security-config>

👉 Certificate Pinning, для предотвращения подмены сертификата. Тут, возможно, надо чуть больше подумать над реализацией, чтобы приложение не сломалось при изменениях сертификата.

val client = OkHttpClient.Builder()
.certificatePinner(
CertificatePinner.Builder()
.add("yourdomain.com", "sha256/your-certificate-hash")
.build()
)
.build()

👉 Использование Strong Network Security Configuration, которое, в целом, дает все преимущества первых двух пунктов, но работает начиная с Android 7.0

<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">yourdomain.com</domain>
<pin-set>
<pin digest="SHA-256">your-certificate-hash</pin>
</pin-set>
</domain-config>
</network-security-config>

👉 Корректная валидация SSL/TLS сертификатов и отключение поддержки устаревших протоколов.

val sslSocketFactory = SSLContext.getInstance("TLSv1.3").apply { init(null, null, null) }.socketFactory
val client = OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).trustManagers[0] as X509TrustManager)
.build()


Есть ли у вас в проекте TrustManager с доверием к любым сертифкатам без лишних вопросов?
  • 👍 12
  • 🔥 4
  • 👏 3
  • ❤ 1
  • 👎 1
Post #2262 2.86K
  • 🔥 6
  • ❤ 2
Post #2261 3.01K
Android Good Reads Compose 👨‍💻 👉 Релиз androidx.media3:media3-ui-compose, UI для ExoPlayer через Compose будет рисовать проще 👉 Проблемы с изменением размера ModalBottomSheet ? 👉 Норм ли ранний дроп в @Composable? @Composable fun Label(val label: String?) { if(label ==…
Compose 😎

👉 Обновления: BOM -> 2025.03.00, Material3 теперь 1.4.0-alpha10 с кучей обновлений API, а Compose получил первый RC для версии 1.8.0. Ждем?

Минорные библиотеки:

androidx.activity:activity-compose:1.11.0-alpha01
androidx.lifecycle:lifecycle-runtime-compose:2.9.0-alpha12
androidx.lifecycle:lifecycle-runtime-compose-android:2.9.0-alpha12
androidx.lifecycle:lifecycle-runtime-compose-jvmstubs:2.9.0-alpha12
androidx.lifecycle:lifecycle-runtime-compose-linuxx64stubs:2.9.0-alpha12
androidx.lifecycle:lifecycle-viewmodel-compose:2.9.0-alpha12
androidx.lifecycle:lifecycle-viewmodel-compose-android:2.9.0-alpha12
androidx.lifecycle:lifecycle-viewmodel-compose-desktop:2.9.0-alpha12
androidx.media3:media3-ui-compose:1.6.0-rc01
androidx.navigation:navigation-compose:2.8.9
androidx.navigation:navigation-compose:2.9.0-alpha08
androidx.navigation:navigation-compose-android:2.9.0-alpha08
androidx.navigation:navigation-compose-jvmstubs:2.9.0-alpha08
androidx.navigation:navigation-compose-linuxx64stubs:2.9.0-alpha08
androidx.navigation:navigation-fragment-compose:2.8.9
androidx.navigation:navigation-fragment-compose:2.9.0-alpha08
androidx.savedstate:savedstate-compose:1.3.0-alpha10
androidx.savedstate:savedstate-compose-android:1.3.0-alpha10
androidx.savedstate:savedstate-compose-jvmstubs:1.3.0-alpha10
androidx.savedstate:savedstate-compose-linuxx64stubs:1.3.0-alpha10


👉 Зачем нужно прокидывать Initial State?
👉 Можно ли сделать горизонтально-прокручиваемый FlowRow?

В связи с этим, небольшой опрос о состоянии Compose в вашем проекте
  • 👍 2
Post #2259 3.15K
Разбираемся в разнице между try-catch и runCatching

👉 runCatching возвращает Result, что позволяет использовать экстеншены с Result и поддерживать функциональный стиль кода
👉 runCatching это скоуп функция, поэтому все возможности скоуп функций доступны
👉 Легко заменить try-catch с пустым catch блоком на runCatching
👉 Проще отлавливать вложенные exception


Зеркало с примерами. С runCatching код выглядит чище и в одном стиле.
Medium Kotlin Tips and Tricks You May Not Know: #7 — Goodbye try-catch, Hello runCatching! A cleaner way to handle exceptions in Kotlin with runCatching.
  • 👍 4
Post #2257 3.14K
Android Good Reads Пятница! Если уж релизите в пятницу, то проведите дополнительные тесты, а именно Accessibility Check Android Studio Iguana уже стабильна, а это значит вам точно доступен UI check mode, которая покажет как на разных экранах будет выглядеть ваше приложение…
Ещё немного про Accessibility, но теперь и в Compose

👉 Конечно, про contentDescription, это важно даже для разных состояний кнопок
👉 onClickLabel который помогает вызову TalkBack функции
👉 minimumTouchTargetSize(), если не хотите думать над кастомной областью клика для иконок

Документация про Accessibility: https://developer.android.com/develop/ui/compose/accessibility
Android Developers Accessibility in Jetpack Compose | Android Developers This document discusses how to develop Android applications with accessibility in mind using Jetpack Compose, focusing on making UIs usable for everyone by leveraging Compose's declarative APIs and tools.
  • ❤ 2
  • 🔥 2
Post #2256 3.85K
Про стирание типов!

Если кратко - вся статья про inline reified. Внутри так же примеры для noinline и crossinline. Заметил хороший практический пример про работу с crossinline, который можно было бы спросить на собеседовании на понимание:

inline fun doSomething(action: () -> Unit) {
println("Start doSomething")
action()
println("End doSomething") // This might NOT be printed
}

fun test1() {
doSomething {
println("Inside lambda")
return // This exits test1(), NOT just the lambda!
}
println("This will NOT be printed")
}

inline fun doSomethingSafely(crossinline action: () -> Unit) {
println("Start doSomethingSafely")
action()
println("End doSomethingSafely") // This WILL be printed
}

fun test2() {
doSomethingSafely {
println("Inside lambda")
return // This exits ONLY the lambda
}
println("This WILL be printed")
}

fun main() {
println("Running test1:")
test1()
println("\nRunning test2:")
test2()
}


Ответ:
test1() // Вывод: Start doSomething, Inside lambda
test2() // Вывод: Start doSomethingSafely, Inside lambda, End doSomethingSafely, This WILL be printed
  • 👍 8
  • ❤ 4
  • 🔥 3
Post #2255 3.29K
Опасности добавления permission READ_MEDIA_IMAGES

Если вы релизите часто приложение, вы верно знаете о правилах гугла в отношении permission. Автор статьи решает задачу отображения превью существующих фото из девайса. О его попытках можно узнать тут, но как итог - фичу полностью ревертнули, чтобы не блокировать релиз.
  • 👍 3
  • ❤ 2
  • 🔥 2
Post #2254 4.08K
Новая typesafe навигация в Jetpack Compose привносит новые сложности. На деле, все сильно проще. О том как делать вложенную навигацию с BottomNavBar как раз следующая статья. Внутри:

👉 Примеры 2 разделенных графов навигации
👉 Пример основного экрана с BottomNavBar
👉 Судя по всему совместимо с CMP, код будет выглядеть 1 в 1

Не стоит забывать и о документации
Rock and Null Flat approach for tabbed Navigation in Jetpack Compose Simplify Jetpack Compose tabbed navigation with a flat structure and conditional visibility, avoiding complex nested graphs. This approach solves URL mapping issues in Compose Web and streamlines deep linking.
  • 👍 3
  • ❤ 2
  • 🔥 2
Post #2253 3.86K
Упрощенное тестирование ViewModel

Начиная с androidx.lifecycle:lifecycle-viewmodel-testing:2.9.0-alpha01 нам доступна структура ViewModelScenario для проверки того как ViewModel переживает реконфигурацию или восстановление состояния. Пример:

class MyViewModelTest {

@Test
fun testStateRestoration() = runTest { // this: TestScope
viewModelScenario { // this: CreationExtras
MyViewModel(
scope = this@runTest,
handle = createSavedStateHandle(),
)
}.use { scenario: ViewModelScenario ->
// Устанавливаем `ViewModel` state.
scenario.recreate()
// Проверяем что state восстановился корректно
}
}
}


Совместимо с KMP!
  • 🔥 16
  • 👍 7
Post #2252 4.59K
В чатах по KMP часто всплывает вопрос: "Вот я Android разработчик, с чего мне начать изучать про KMP?" и, помимо официальной доки, ответить то было и нечего. Но вот появилась достаточно хорошо структурированная книга (open-source):
https://santimattius.github.io/kmp-for-mobile-native-developers-book/

Внутри примеры кода, разбор структуры и основных фреймворков. Пробовали ли KMP и что посоветуете начинающим?
  • 👍 15
  • 🤔 5
  • 😁 3
  • 🔥 1
Post #2251 3.89K
Android Good Reads Продолжаем про Compose! 👉 Можно ли сделать скролл чуть медленнее и плавнее? Да, с помощью NestedScrollConnection 👉 Почему ContextualFlowRow депрекейтнули? Начиная с Jetpack Compose 1.8 beta01 множество api выходит из статуса experimental, однако часть уезжает…
Compose 👨‍💻

👉 Релиз androidx.media3:media3-ui-compose, UI для ExoPlayer через Compose будет рисовать проще
👉 Проблемы с изменением размера ModalBottomSheet ?
👉 Норм ли ранний дроп в @Composable?

@Composable
fun Label(val label: String?) {
if(label == null) return
...
}

или

@Composable
fun Label(val label: String?) {
if(label != null){
...
}
}

👉 Обновилась библиотека для Compose-driven architecture - Circut
👉 Coil получил обновление 3.1.0 c улучшением перфоманса для AsyncImage
  • 🔥 6
  • 👍 4
  • 👏 3
Post #2250 2.7K
Частая проблема в проектах, где я работаю - синхронизация времени клиента и предотвращение перевода часов через настройки. А тут Google представляет TrustedTime API, который должен решить эту проблему наконец-таки.
Как использовать?

👉 Подключаем зависимость com.google.android.gms:play-services-time:16.0.1
👉 Создаем где-нибудь экземпляр

TrustedTime.createClient(context)

👉 Используем с фолбеком к стандартному способу

val currentTimeMillis =
myApp.trustedTimeClient?.computeCurrentUnixEpochMillis()
?: System.currentTimeMillis()


Под капотом синхронизация с Google серверами. Буду интегрировать в проект наряду с kotlinx-datetime
Android Developers Blog TrustedTime API: Introducing a reliable approach to time keeping for your apps The Trusted Time API in Google Play Services offers developers a reliable, accurate time source independent of device settings to ensure consistency.
  • 👍 15
  • 🔥 6
  • ❤ 3
Post #2249 3.32K
5 ошибок в корутинах о которых никто не говорит

Внутри разбор с примерами и объяснением почему это ошибка:
👉 Вызов suspend функции напрямую из вьюхи
👉 Некорректное использование GloablScope. В Android разработке его вообще некорректно использовать. Есть ли у вас примеры, когда это уместно?
👉 Последовательный, а не асинхронный запрос данных
👉 Вылов CancellationException внутри suspend функции
👉 В длительных цикличных операциях забываем про ensureActive()
  • 👍 12
  • 🔥 4
  • 👏 3
Post #2248 3.49K
Android Good Reads Kotlin Multiplatform Roadmap 2025 Дорожная карта на 2025 год. Как будет развиваться мультиплатформа: 👉 В Compose Multiplatform будет упор на интеграцию Jetpack Compose, улучшение перфоманса iOS. Стабилизация и доведение до релизного состояния таких фичей…
⚡️ Команда Kotlin Multiplatform отказывается от дальнейшей разработки собственной IDE и поддержки KMP в Fleet IDE

О причинах тут: https://blog.jetbrains.com/kotlin/2025/02/kotlin-multiplatform-tooling-shifting-gears/
The JetBrains Blog Kotlin Multiplatform Tooling – Shifting Gears - The JetBrains Blog A couple of years ago, we initiated the idea of creating a Kotlin Multiplatform IDE to help facilitate the development of KMP applications. We embarked on this venture, building on the Fleet platform,
  • 😁 17
  • ❤ 5
  • 💔 4
Post #2247 3.28K
Android Good Reads Про Compose! 👉 Compose Multiplatform получила релиз 1.8.0-alpha02. Внутри в основном багфиксы и поддержка drag-and-drop для iOS 👉 Как запустить анимацию одновременно для 2 элементов? 👉 Можно ли двигать элементы по своему, когда открываем IME (клавиатуру)?…
Продолжаем про Compose!

👉 Можно ли сделать скролл чуть медленнее и плавнее? Да, с помощью NestedScrollConnection
👉 Почему ContextualFlowRow депрекейтнули? Начиная с Jetpack Compose 1.8 beta01 множество api выходит из статуса experimental, однако часть уезжает сразу в Deprecated

👉 Пачка зависимостей получила обновление:

androidx.lifecycle:lifecycle-runtime-compose:2.9.0-alpha09
androidx.lifecycle:lifecycle-runtime-compose-android:2.9.0-alpha09
androidx.lifecycle:lifecycle-runtime-compose-jvmstubs:2.9.0-alpha09
androidx.lifecycle:lifecycle-runtime-compose-linuxx64stubs:2.9.0-alpha09
androidx.lifecycle:lifecycle-viewmodel-compose:2.9.0-alpha09
androidx.lifecycle:lifecycle-viewmodel-compose-android:2.9.0-alpha09
androidx.lifecycle:lifecycle-viewmodel-compose-desktop:2.9.0-alpha09
androidx.navigation:navigation-compose:2.8.6
androidx.navigation:navigation-compose:2.9.0-alpha05
androidx.navigation:navigation-fragment-compose:2.8.6
androidx.navigation:navigation-fragment-compose:2.9.0-alpha05
androidx.savedstate:savedstate-compose:1.3.0-alpha07
androidx.savedstate:savedstate-compose-android:1.3.0-alpha07
androidx.savedstate:savedstate-compose-jvmstubs:1.3.0-alpha07
androidx.savedstate:savedstate-compose-linuxx64stubs:1.3.0-alpha07


👉 Полезный плагин: Figma to Jetpack Compose Icon сконвертирует иконку сразу в нужный формат в приложении
  • 👍 6
  • 🥱 1
Post #2246 2.76K
Разбираем, что происходит при нажатии кнопки "Старт" в Android Studio

Или как собрать и запустить приложение без Android Studio:

👉 Генерируем APK-файл
./gradlew assembleDebug

👉Запуск эмулятора
emulator -list-avds
emulator -avd <имя_эмулятора>

👉 Установка APK
adb install -r app/build/outputs/apk/debug/app-debug.apk

👉 Запуск
adb shell am start -n <package_name>/<activity_name>

UPD: В комментариях уточнение по поводу сборки билда и выбора эмулятора от подписчика!
Medium Behind the Scenes: What Happens When You Press the Start button in Android Studio? As Android developers, we frequently rely on Android Studio’s “Run” or “Start” button to build, deploy, and launch our applications on…
  • 👍 6
  • ❤ 4
  • 😁 1
  • 🤔 1
  • 🤪 1
Post #2245 2.38K
Небольшая свежая библиотека KAnalytics (⭐️ 15)

Не сказал бы, что на этой стадии я бы стал её использовать, но она может быть хорошим примером того, как стоит держать аналитику в приложении: с удобным дебаггером, поддержкой KMP и без глубокой связности с основным приложением.
  • 👍 2
Post #2244 3.13K
Разбираем использование runBlocking в Android

👉 Что такое runBlocking?
Функция, которая запускает новую корутину и блокирует текущий поток до её завершения.
Часто используется в примерах для демонстрации корутин в main() функции.

👉 Почему стоит быть осторожным с runBlocking в Android?
Блокирует текущий поток, что на Android может привести к замораживанию UI и возникновению ANR (Application Not Responding).
Особенно критично при выполнении операций ввода-вывода в главном потоке.

👉 Пример неправильного использования:
class MainViewModel(private val mainRepository: MainRepository) : ViewModel() {
// Не рекомендуется
private fun fetchPosters() = runBlocking {
mainRepository.fetchPosters()
}
}

В этом примере runBlocking блокирует главный поток, что может привести к проблемам с отзывчивостью приложения.

👉 Альтернативы:
Используйте viewModelScope для запуска корутин, что обеспечивает автоматическую отмену задач при уничтожении ViewModel.
Применяйте launch или async для асинхронных операций без блокировки главного потока.
getstream.io Exercise Caution When Using runBlocking on Android Explore the internal mechanism of runBlocking and the reasons why you exercise caution when using runBlocking.
  • 😁 14
  • 👍 7
  • 🔥 3
  • 👎 1
  • 💔 1
Post #2243 2.63K

Forwarded from Android Live 🤖

Что нового в Android 16?
#android #google

Что же, в этом году нас ждёт свежий Android, и к его нововведениям стоит подготовиться. Давайте разберём основные изменения, опираясь на официальную документацию Google.

🔴Progress-centric Notifications — фактически аналог Live Activities на iOS, где теперь у нас добавляется Notification.ProgressStyle для отображения прогресса текущего процесса. Полезно для приложений с загрузками, доставками и навигацией. Выглядит здорово, одобряем.

🔴Predictive back updates — новые API для предсказуемого поведения жестов "назад". Теперь onBackInvokedCallback позволяет точнее обрабатывать нажатия. Пока неясно, насколько это улучшит UX — навигация жестами и так работает достаточно стабильно.

🔴Richer Haptics — более классная обработка haptic-эффектов. В VibrationEffect.Compositions, добавили более точную настройку вибрационных эффектов. Одобряю, очень мало приложений хорошо используют haptic-эффект.

🔴System-triggered profiling — обновлённый ProfilingManager, появившийся в Android 15, теперь собирает ещё больше данных о производительности приложений. Не тестировал, если пробовали — расскажите, как вам?

🔴Better job introspection — полезное обновление, призванное улучшить дебаг запущенных Job. Теперь можно просматривать их историю и анализировать причины задержек или неудачного выполнения. Круто.

🔴Photo picker improvements — Google активно продвигает использование Photo Picker, а в новой версии API добавляет Embedded Photo Picker который делает выбор изображений ещё более естественным и встроенным в приложение. Отличное обновление.

🔴Vertical text — небольшая, но любопытная доработка: теперь Paint поддерживает вертикальный текст. Не знаю, можно ли было раньше сделать это без библиотек, но Google решил это подстветить как фичу. Подсвечу и я.

Тут только некоторые из фичей, хотя и основные, а все можно увидеть тут.
Android Developers Features and APIs | Android Developers Learn about the new features and APIs for developers in Android 16.
  • 👍 9
  • ❤ 1
  • 🥱 1
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →