Assembling the digest… kotlin-digest
TRENDING

EDITION 2026·W32
03 AUGUST 2026
73 articles · 9 sources
Archive →

The Kotlin world, assembled weekly, for Android engineers.

6 chapters · ordered by topic score · About & Contributing
Filter

FOCUS — select topics to show only those chapters.

TRENDING
█████▇█ compose-multiplatform 85 █████▇█ compose 81 ███████ kotlin 72 █████▇█ jetpack 33 ██████▇ jetbrains 29 █████▇▇ google-io 27 ██████▇ navigation 23 ███▇▇▇▇ clean-architecture 23 ███████ material3 22 ███████ android-developers 22 ██▇▇█▇▇ kmp 20 ███▇▇▆▆ architecture 15 ██▇█▇▇▇ ktor-server 10 ██▇▇▆▆█ context-receivers 10 █▇█▇▇▆█ android-auto 8 ▅▅▆▆██▇ shot 8 ▇▇██▇▇▆ testing 8 ██▇▇▆▆▅ coroutines 7 ▇██▇▇▆▆ gradle-plugin 6 ▇██▇▇▆▆ build-logic 6 █████▇█ compose-multiplatform 85 █████▇█ compose 81 ███████ kotlin 72 █████▇█ jetpack 33 ██████▇ jetbrains 29 █████▇▇ google-io 27 ██████▇ navigation 23 ███▇▇▇▇ clean-architecture 23 ███████ material3 22 ███████ android-developers 22 ██▇▇█▇▇ kmp 20 ███▇▇▆▆ architecture 15 ██▇█▇▇▇ ktor-server 10 ██▇▇▆▆█ context-receivers 10 █▇█▇▇▆█ android-auto 8 ▅▅▆▆██▇ shot 8 ▇▇██▇▇▆ testing 8 ██▇▇▆▆▅ coroutines 7 ▇██▇▇▆▆ gradle-plugin 6 ▇██▇▇▆▆ build-logic 6

EDITION 2026·W32
03 AUGUST 2026
73 articles · 9 sources

The Kotlin world, assembled weekly, for Android engineers.

6 chapters · ordered by topic score · About & Contributing
Cover Story · Kotlin Core
Trending · Contents
compose-multiplatform█████▇█
compose█████▇█
kotlin███████
jetpack█████▇█
jetbrains██████▇
google-io█████▇▇
navigation██████▇
clean-architecture███▇▇▇▇
material3███████
android-developers███████
kmp██▇▇█▇▇
architecture███▇▇▆▆

Compose & UI

14 stories

Kotlin Core

19 stories

Architecture

11 stories

Testing

5 stories

KMP

5 stories

Android Platform

13 stories

Community

4 stories

Networking

1 stories

Build & Tooling

1 stories

§ 01

Compose & UI

Medium Kotlin Tag 4 Aug

Five Years of Jetpack Compose: Five Things I Love About It

A five-year retrospective on Jetpack Compose highlighting LazyColumn replacing RecyclerView/DiffUtil boilerplate, AnimatedVisibility simplifying view-animation callback juggling, cheaper layout nesting versus ConstraintLayout, and Compose Multiplatform sharing composables across desktop/iOS/web.

▸ ANIMATED VISIBILITY
AnimatedVisibility( visible = isExpanded, enter = fadeIn() + expandVertically(), exit = fadeOut() + shrinkVertically() ) { DetailPanel() }
composeanimationcompose-multiplatform
Medium Kotlin Tag 6 Aug

Two things called “State”: how mutableStateOf and StateFlow really work underneath

Compares mutableStateOf and StateFlow: both expose an observable .value but come from different libraries with different machinery. Explains why Compose's snapshot state could not simply reuse StateFlow, and how each notifies readers and fits Compose vs coroutine code.

composeflowscoroutineskotlin
Medium Kotlin Tag 4 Aug

Thinking Like the Compose Runtime — Part 4: When Compose Decides to Do Nothing

Fourth part of a Compose Runtime series explains why the runtime skips recomposition when a stable parameter's value hasn't changed, since doing no work beats doing fast work. Clarifies that stable types can still mutate, but only through observable state Compose can track, which is why @Stable/@Immutable annotations matter.

▸ STABLE MUTABLE STATE
class Counter { var count by mutableStateOf(0) } // count changes, but every change is // observable, so Compose never misses it
composekotlin
Proandroiddev 7 Aug

Stop Writing Compose Like It’s 2024–10 Recent Updates Every Android Developer Should Know

Rounds up ten Compose changes from the past year worth adopting: default pausable composition improving scroll performance, the new retain {} API for non-serializable UI-scoped objects like players, stable Navigation 3, dropShadow/innerShadow, TextFieldState, and Material 3 Expressive. Contrasts old vs new code for each.

▸ RETAIN SCOPED STATE
val exoPlayer = retain(mediaUri) { ExoPlayer.Builder(appContext).build().apply { setMediaItem(MediaItem.fromUri(mediaUri)) prepare() } } RetainedEffect(exoPlayer) { onRetire { exoPlayer.release() } }
composenavigationmaterial3testing
Medium Kotlin Tag 3 Aug

Top Jetpack Compose Interview Questions for Senior Android Developers (UK)

A rundown of interview questions for senior Android roles covering Compose fundamentals: remember vs rememberSaveable, state hoisting, recomposition, CompositionLocal, LazyColumn performance, navigation, and snapshot testing. No answers are given, just prep prompts.

composemvvmtestingnavigation
Medium Kotlin Tag 5 Aug

Deep Linking in Android: The One Feature Every App Needs in 2026

Walks through Android deep linking basics: custom URI schemes versus verified App Links, then a step-by-step Kotlin implementation wiring an AndroidManifest intent-filter to a Compose Navigation destination via navDeepLink so a web URL opens a specific screen directly.

▸ NAV DEEP LINK
composable( route = "details/{itemId}", arguments = listOf(navArgument("itemId") { type = NavType.StringType }), deepLinks = listOf(navDeepLink { uriPattern = "$BASE_URL/product/{itemId}" }) ) { backStackEntry -> val itemId = backStackEntry.arguments?.getString("itemId") ?: "Unknown" DetailsScreen(itemId = itemId) }
navigationcomposeandroid-api
Proandroiddev 4 Aug

From God ViewModel to Composed Screen Logic

Proposes splitting a bloated Compose screen ViewModel into focused 'controller' interfaces (sources, articles, search, refresh) that share one state store, avoiding a single God ViewModel while keeping one UiState and one action entry point.

▸ GROUPED USER ACTIONS
sealed interface HomeAction { data object Refresh : HomeAction data class SourceSelected(val source: SourceItem?) : HomeAction data class SearchQueryChanged(val query: String) : HomeAction }
composeviewmodelarchitecturemvvm
Medium Kotlin Tag 6 Aug

Pocketflow #Week1 - The Core Idea & Multiplatform Architecture

A build-in-public log for a Compose Multiplatform node-based AI workflow editor targeting iOS and Android from one codebase. Covers using Compose's Canvas and gesture APIs for an infinite pannable node graph, plus expect/actual declarations to persist generated media files per platform.

▸ KMP EXPECT DECLARATION
expect object LocalStorage { fun saveMediaToTemp(bytes: ByteArray, extension: String): String }
compose-multiplatformkmp
Medium Kotlin Tag 8 Aug

Use Compose Multiplatform Components in a UIKit Scroll View (Without Losing Your Mind)

Solves Compose Multiplatform components rendering at zero height inside a UIKit/Objective-C scroll view, since Compose has no intrinsicContentSize: the Kotlin side reports its measured height via onGloballyPositioned, and Swift turns that report into an Auto Layout constraint.

▸ REPORT HEIGHT TO UIKIT
Column( modifier = Modifier .fillMaxWidth() .onGloballyPositioned { coordinates -> val heightDp = with(density) { coordinates.size.height.toDp().value } onHeightChanged(heightDp) } ) { }
compose-multiplatformios-interopkmp
Medium Kotlin Tag 8 Aug

Common Mistakes Android Developers Make When Learning Jetpack Compose (and How to Avoid Them)

Walks through common mistakes Android developers make when learning Jetpack Compose, rooted in carrying an XML/View mental model into declarative UI. Covers state-as-source-of-truth, recomposition, side-effect handling (LaunchedEffect), and unidirectional data flow, with before/after code examples.

▸ STATE-DRIVEN UI
@Composable fun Greeting(username: String, isLoading: Boolean, canSubmit: Boolean) { if (isLoading) { CircularProgressIndicator() } else { Text("Hello, $username") Button(onClick = { }, enabled = canSubmit) { Text("Submit") } } }
composeandroid-developers
Proandroiddev 8 Aug

Your Compose App Isn’t Slow — Your State Is

Walks through seven Compose recomposition mistakes — reading state too high in the tree, reading animated values during composition instead of layout/draw, monolithic UiState objects — each with a before/after fix using lambda-overload modifiers and derivedStateOf to shrink the invalidation blast radius.

▸ DEFER OFFSET READ
val offset by animateDpAsState(targetValue = targetOffset) Box( Modifier .offset { IntOffset(x = offset.roundToPx(), y = 0) } .size(80.dp) )
composeanimation
Medium Kotlin Tag 3 Aug

BoxWithConstraints: When You Actually Need It

Explains BoxWithConstraints, which uses SubcomposeLayout to expose incoming maxWidth/maxHeight before children compose, letting a composable branch into structurally different content based on available space, useful for cards inside variable-width grids. Warns it's costlier than plain modifiers and best reserved for genuine 'what to compose' decisions, not simple resizing.

▸ ADAPTIVE WIDTH BRANCH
BoxWithConstraints { if (maxWidth < 400.dp) { CompactContent() } else { WideContent() } }
composeadaptive-ui
Medium Kotlin Tag 3 Aug

Thinking Like the Compose Runtime — Part 3: How Compose Never Loses Its Place

Explains how the Jetpack Compose runtime tracks composable identity across recompositions using call site plus execution order, then introduces the Slot Table as the structure that stores per-composable state so recomposition resumes rather than restarts. Notes why key() matters when list order changes.

compose
Medium Android Tag 6 Aug

A Designer’s Field Guide to WCAG, iOS, and Android Rules

A cross-platform design reference consolidating WCAG 2.2 success criteria, Apple Human Interface Guidelines, and Material Design 3 rules into one checklist. Covers Android-specific specs: 48dp touch targets, FAB sizing, 8dp grids, dynamic color roles, and navigation component choices.

material3android-api
§ 02

Kotlin Core

Medium Kotlin Tag 7 Aug

The Bugs That Don’t Fail

Postmortem on building mongkn, a Kotlin/Native cinterop MongoDB driver: four silent bugs (BSON type mismatch, missing @SerialName for _id, explicit BsonNull breaking sparse indexes, string timestamps breaking TTL indexes) that passed 294 tests yet broke in production, prompting integration-test-only rules for native storage layers.

kotlintestingkmp
Jetbrains Blog 5 Aug

Qodana User Spotlight: Meet Fullstack Software Engineer Drew Penrod

Interview with a DevSecOps engineer at a kids'-phone company on why inconsistent linting across Kotlin, TypeScript and React repos led them to adopt Qodana for unified static analysis, dependency scanning and license auditing to meet CIS/NIST security controls.

kotlinandroid-developers
Medium Kotlin Tag 8 Aug

Android Engineering From Scratch

First entry in a beginner Android series arguing Kotlin developers should default to val over var, since read-only references communicate intent and prevent accidental mutation. Notes MVVM/Compose UI state models rely on val plus copy() rather than in-place mutation.

kotlinandroid-developers
Medium Kotlin Tag 7 Aug

Staff Android Interview Questions: Kotlin & Advanced Language Features

A rundown of advanced Kotlin questions asked in Staff-level Android interviews: inline/noinline/crossinline semantics, reified generics, interface and property delegation, value classes, sealed classes vs sealed interfaces, variance, type erasure, and context receivers. Frames these features as design tools for scalable APIs rather than trivia.

▸ VALUE CLASS WRAPPER
@JvmInline value class UserId(val value: String)
kotlinvalue-classessealed-classescontext-receivers
Medium Kotlin Tag 3 Aug

Preventing Race Conditions with Mutex in Kotlin Coroutines

Walks through a real race condition where the same chat voice-note gets processed twice after arriving via both a socket event and an API sync, then fixes it with a Mutex-guarded set of in-flight message IDs instead of one global lock, preserving concurrency across independent downloads.

▸ ATOMIC CLAIM MUTEX
private val activeDownloadsMutex = Mutex() private val activeDownloadIds = mutableSetOf<String>() private suspend fun claimDownload(messageId: String): Boolean = activeDownloadsMutex.withLock { activeDownloadIds.add(messageId) }
coroutineskotlin
Medium Kotlin Tag 3 Aug

Mutex vs Semaphore in Kotlin Coroutines

Compares Kotlin coroutine synchronization primitives: Mutex enforces exclusive access to a critical section (one coroutine at a time via withLock), while Semaphore caps concurrent access to N coroutines via withPermit. Warns that Semaphore(N>1) still allows race conditions since it limits concurrency, not exclusivity.

▸ MUTEX VS SEMAPHORE
val mutex = Mutex() mutex.withLock { counter++ } val semaphore = Semaphore(3) semaphore.withPermit { // at most 3 coroutines run this at once }
coroutineskotlin
Medium Kotlin Tag 4 Aug

Kotlin Coroutine Exception Handling: The Mental Model That Made It Click for Me

Builds a mental model for Kotlin coroutine exception handling by separating three questions per coroutine: which builder determines how failure is observed, which parent Job is affected by it, and which scope function determines where it can be caught, distinguishing cancellation from failure propagation.

▸ CHILD CANCEL VS PARENT
val parent = launch { val child = launch { delay(1_000) } child.cancelAndJoin() println("Child cancelled: ${child.isCancelled}") println("Parent is still active: $isActive") } parent.join()
coroutineskotlin
Medium Kotlin Tag 3 Aug

Context parameters in production Kotlin: what the docs don’t emphasise

Kotlin 2.4.0 made context parameters stable, letting functions declare and receive ambient values (like tenant/trace IDs) without threading them through every signature. Compares them to ThreadLocals and constructor injection, arguing context parameters suit per-call values while constructor injection still wins for per-instance dependencies.

▸ CONTEXT PARAMETER API
data class RequestContext( val tenant: String, val traceId: String, ) context(ctx: RequestContext) fun loadOrders(): List<Order> = repository.findByTenant(ctx.tenant)
kotlincontext-receivers
Lib Detekt 4 Aug

v2.0.0-alpha.6

Detekt 2.0.0-alpha.6 targets Kotlin 2.4.10, Gradle 9.6.1, AGP 9.3.1 and JDK 25; its Gradle task now runs type-resolution analysis on all Kotlin source sets by default, and the ktlint-wrapper rules module raises its minimum to JVM 17.

kotlingradle-plugin
Medium Kotlin Tag 5 Aug

Mutability and Immutability in Kotlin: Why val Is the Default Choice

Explains Kotlin's val/var distinction, clarifying that val only freezes the reference (not object contents) and contrasting read-only vs mutable collections. Recommends isolating mutation to a single manager class returning copies via toList() for safer, more predictable, concurrency-friendly state.

▸ ENCAPSULATE MUTABLE STATE
class ShoppingCartManager { private val _items = mutableListOf<Product>() fun getState(): ShoppingCartState { return ShoppingCartState( items = _items.toList(), total = _items.sumOf { it.price } ) } }
kotlinkotlin-stdlib
Medium Kotlin Tag 7 Aug

How Kotlin 2.4.20 simplifies equality and uniqueness checks

Kotlin 2.4.20-Beta2 adds four experimental stdlib functions — allEqual, allEqualBy, allDistinct, allDistinctBy — for collections, sequences and arrays, gated behind ExperimentalStdlibApi. They replace verbose toSet()/distinct() workarounds and fix edge cases like empty-collection equality returning true instead of false.

▸ NEW EQUALITY CHECKS
@OptIn(ExperimentalStdlibApi::class) fun validateUpload(parts: List<UploadPart>) { require(parts.isNotEmpty()) { "Upload must contain at least one part" } require(parts.allEqualBy { it.uploadId }) { "Mixed upload IDs" } require(parts.allDistinctBy { it.index }) { "Duplicate part index" } }
kotlinkotlin-stdlib
Medium Kotlin Tag 9 Aug

String Interpolation in Kotlin: Write Cleaner and More Readable Strings

Covers Kotlin string templates: $variable and ${expression} syntax, calling functions and filtering collections inside interpolated strings, and the common pitfall where $obj.property parses as $obj followed by literal .property text.

▸ INTERPOLATION GOTCHA
val newStudent = Student(name = "Alex", scores = listOf(15, 25, 30)) println("Scores: $newStudent.scores") println("Scores: ${newStudent.scores}")
kotlinkotlin-stdlib
Medium Kotlin Tag 8 Aug

Lazy initialization in Kotlin

Explains Kotlin's by lazy delegate: single-execution, cached initialization on first access, the three LazyThreadSafetyMode options (SYNCHRONIZED, PUBLICATION, NONE), how it differs from lateinit, and a memory-leak pitfall when a lazy property captures a short-lived context.

▸ LAZY PROPERTY DELEGATE
val heavyResource: HeavyClass by lazy { HeavyClass() }
kotlinkotlin-stdlib
Jetbrains Blog 5 Aug

Java Annotated Monthly – August 2026

JetBrains' August Java/Kotlin roundup links a Kotlin Corner covering Kotlin turning 15, the Exposed SQL library, Amper's current state, value semantics in Kotlin, local lifetimes, and an open-sourced KotlinLLM project, alongside broader Java news.

kotlinexposed
Medium Kotlin Tag 7 Aug

Garbage Collector (GC) Necə İşləyir: JVM Yaddaşı Dayanmadan Necə Təmizlənir?

Explains how the JVM's G1 garbage collector organizes the heap into thousands of small regions instead of fixed young/old blocks, using Remembered Sets to track cross-region references and a special path for oversized 'humongous' objects. Also covers tricolor marking and the SATB technique G1 uses to avoid losing live objects during concurrent collection.

kotlin
Medium Kotlin Tag 8 Aug

Kotlin const val, val, and var: What’s the Difference?

Beginner explainer distinguishing Kotlin's const val, val, and var: compile-time constant, read-only reference, and mutable reference respectively. Clarifies that val only locks the reference, not the underlying object, and that const val values get inlined at compile time.

kotlin
Medium Kotlin Tag 3 Aug

StateFlow vs. Flow vs. SharedFlow vs. LiveData: A Simple Guide for Android Developers

Compares Flow, StateFlow, SharedFlow, and LiveData for exposing ViewModel data to Compose UIs, explaining when each fits: Flow for cold streams, StateFlow for persistent UI state, SharedFlow for one-time events, LiveData as the older lifecycle-aware alternative.

▸ STATEFLOW UI STATE
class LoginViewModel : ViewModel() { private val _isLoggedIn = MutableStateFlow(false) val isLoggedIn: StateFlow<Boolean> = _isLoggedIn fun onLoginSuccess() { _isLoggedIn.value = true } }
flowscoroutinesviewmodelmvvm
§ 03

Architecture

Medium Kotlin Tag 3 Aug

Beyond the Acronym — SOLID Principles for Android Developers

Walks through Robert Martin's five SOLID principles using Android/Kotlin examples: splitting an overloaded ViewModel into a mapper, analytics tracker, and leaner ViewModel for Single Responsibility, and replacing a payment-type when-branch with a PaymentStrategy interface for Open/Closed.

▸ STRATEGY OVER WHEN
interface PaymentStrategy { suspend fun process(amount: BigDecimal): PaymentResult } class PayPalPayment( private val client: PayPalClient ) : PaymentStrategy { override suspend fun process(amount: BigDecimal) = client.createOrder(amount) }
clean-architecturearchitecturekotlin
Medium Kotlin Tag 8 Aug

MVI Architecture in Android with Kotlin and Jetpack Compose: A Practical Guide with Clean…

Builds a login screen using MVI on top of Unidirectional Data Flow with a three-layer Clean Architecture (Presentation/Domain/Data), comparing a flat UiState data class against a sealed UiState hierarchy, and clarifies that MVI and Clean Architecture are independent, complementary choices.

▸ SEALED UI STATE
sealed interface LoginUiState { data object Idle : LoginUiState data object Loading : LoginUiState data object Success : LoginUiState data class Error(val message: String) : LoginUiState }
mvicomposeclean-architectureviewmodel
Medium Android Tag 3 Aug

MVVM vs MVI in Android: XML Views and Jetpack Compose, Side by Side

Builds the same search-and-filter screen four ways — MVVM and MVI, each with XML Views and Jetpack Compose — showing MVVM's independent StateFlows needing manual combining for derived UI state, versus MVI's single State object computing it directly and triggering fewer recompositions.

▸ MVI DERIVED STATE
data class ProductScreenState( val products: List<Product> = emptyList(), val isLoading: Boolean = false, val error: String? = null, ) { val isEmptyStateVisible: Boolean get() = products.isEmpty() && !isLoading && error == null }
mvvmmvicomposearchitecture
Medium Kotlin Tag 4 Aug

MVI architecture in Jetpack Compose

Explains MVI architecture for Compose screens: an immutable State data class, a sealed Intent hierarchy covering every user action, a ViewModel that's the sole place turning intents into new states, and a purely rendering Composable. Argues this discipline scales more predictably than scattering mutableStateOf across a screen.

▸ MVI INTENT SEALED CLASS
sealed interface ProfileIntent { data class LoadProfile(val userId: String) : ProfileIntent object Retry : ProfileIntent object DismissError : ProfileIntent }
mvicomposeviewmodel
Medium Android Tag 3 Aug

MVVM vs MVI in Android: A Practical Guide to Choosing the Right Architecture

Companion decision guide comparing MVVM and MVI on Android: MVVM's independent state fields are simpler for small screens but can drift out of sync, while MVI's single immutable State object is more predictable and testable but adds boilerplate. Recommends choosing per-screen rather than project-wide.

mvvmmviarchitectureclean-architecture
Medium Kotlin Tag 6 Aug

Is SOLID Really Solid? The Android Edition

Auditing several production Android/Compose Multiplatform codebases against SOLID, the author finds Interface Segregation violations (one bloated repository interface everyone depends on) the most damaging, while Dependency Inversion via Hilt/Koin consistently pays off. Lays out a strangler-style sequence for splitting god ViewModels and god repositories without breaking consumers.

architectureclean-architecture
Medium Kotlin Tag 5 Aug

Your MVI is probably MVVM with extra steps

Argues that 'dispatch-style' MVI is often MVVM with a sealed-class router in front, since both write state from inside the async coroutine; contrasts it with 'reducer MVI', where a pure reduce function and a single writer make transitions atomic and cancellable.

▸ PURE REDUCER FUNCTION
fun reduce(s: SearchState, r: Result): SearchState = when (r) { Result.Started -> s.copy(loading = true, error = null) is Result.Loaded -> s.copy(loading = false, items = r.items) is Result.Failed -> s.copy(loading = false, error = r.message) }
mvimvvmarchitecturecoroutines
Medium Kotlin Tag 5 Aug

60 Android Interview Questions for Mid-Level Developers (2–5 Years)

A study guide of Android interview questions for 2-5 year developers, spanning architecture (MVVM/MVI/Clean Architecture), coroutines, Flow vs StateFlow, dependency injection, Room migrations, and API/error handling.

▸ UI STATE SEALED INTERFACE
sealed interface UiState { data object Loading : UiState data class Success(val data: List<Item>) : UiState data class Error(val message: String) : UiState }
architecturemvvmcoroutinesroom
Medium Kotlin Tag 5 Aug

Android System Design: Building a Production-Ready Authentication Flow

Describes a production Android auth architecture: encrypted token storage behind a SessionManager, mutex-guarded single-flight token refresh, a separate unauthenticated Retrofit/OkHttp client for refresh calls, and an OkHttp Authenticator that transparently retries requests once after a 401.

architectureokhttpretrofitcoroutines
Medium Android Tag 8 Aug

Building Redoubt Analytics: A Counter-UAS Risk Intelligence Platform

Describes building Redoubt Analytics, a counter-UAS risk platform with a Kotlin/Jetpack Compose Android client, a Spring Boot backend handling auth and access control, and a separate Monte Carlo simulation engine. Focuses on splitting responsibilities across the three services to serve security officers, risk officers and SOC operators differently.

architecturespring-kotlin
Medium Android Tag 8 Aug

Android System Design: Pagination

Explains Android pagination strategies — offset-based, cursor-based and keyset — for large datasets like product catalogs and feeds, covering consistency trade-offs as data changes and query-performance costs of large offsets. Frames pagination as a system-design concern spanning API, architecture, caching and Paging 3 implementation.

architecture
§ 04

Testing

Medium Kotlin Tag 7 Aug

The Snapshot-Test Matrix, Two Ways: Parameterized JUnit vs TestBalloon

Compares two ways to generate a 135-case snapshot-test matrix (27 screens x 5 configs) with Roborazzi: ParameterizedRobolectricTestRunner versus TestBalloon's Kotlin DSL, where suites are plain code and loops replace annotation-driven parameterization. Notes a current Android-target bug in TestBalloon's public release.

▸ SNAPSHOT VARIANT ENUM
enum class SnapshotVariant( val qualifiers: String, val fontScale: Float, val isDark: Boolean = false ) { BASELINE(qualifiers = "+en-w411dp-h891dp", fontScale = 1.0f), DARK(qualifiers = "+en-w411dp-h891dp-night", fontScale = 1.0f, isDark = true), FONT_SCALE(qualifiers = "+nl-w411dp-h891dp", fontScale = 2.0f) }
testingcompose-multiplatformkotlin
Proandroiddev 5 Aug

How to Ban a Class or Method in Code (And Why You Should)

Explains automating bans on dangerous APIs like MockK's spyk, GlobalScope, and Thread.sleep via Detekt's ForbiddenMethodCall/ForbiddenImport rules, Konture architecture unit tests, or @Deprecated(level=ERROR), turning wiki guidelines into compiler/build-time guardrails.

▸ DEPRECATE WITH ERROR LEVEL
@Deprecated( message = "BaseActivity is banned. Use ComposeActivity instead.", replaceWith = ReplaceWith("ComposeActivity()"), level = DeprecationLevel.ERROR ) class BaseActivity
testingcoroutinesarchitecturekotlin
Medium Kotlin Tag 6 Aug

Why Modern Android Testing Is Different

Argues the classic testing pyramid no longer fits modern Android: Compose can render on the JVM via Robolectric, semantics-tree queries replace brittle view matching, unidirectional state makes UI logic unit-testable, and screenshot tools like Paparazzi/Roborazzi catch visual regressions cheaply. Opening chapter of a book on modern Android testing strategy.

testingcomposepaparazzi
Medium Android Tag 8 Aug

How We Moved 1,500 Android Screenshot Tests to Roborazzi

Thumbtack's Android team describes porting 1,500 Firebase Test Lab screenshot tests to Roborazzi, a JVM-local, Robolectric-based screenshot testing framework for Compose apps. Covers batch-porting steps, a font-cache test-isolation bug across parallel Robolectric runs, and cross-OS shadow-rendering mismatches between macOS and CI.

testingcompose
Medium Android Tag 6 Aug

Android Visual Testing: When to Use OCR, Templates, and Screenshots

Argues Android visual testing should pick the narrowest assertion for the requirement rather than one universal tool: UI/accessibility state for semantics, screenshot comparison for layout, OCR for localized text, and template matching for stable icons. Proposes a five-stage evidence-logging pattern for reliable checks.

testing
§ 05

KMP

Medium Kotlin Tag 8 Aug

Building Type-Safe Navigation for Android & iOS in Kotlin Multiplatform (Part 6)

Part 6 of a KMP series proposes sharing only navigation intent between Android and iOS while keeping execution native: a shared ViewModel emits sealed NavigationDestination/Effect values via SharedFlow, mapped to NavController routes on Compose and NavigationStack on SwiftUI.

▸ SHARED NAV INTENT
sealed interface NavigationDestination { data object ShowList : NavigationDestination data class ShowDetail(val showId: Long) : NavigationDestination }
kmpnavigationios-interopcompose-multiplatform
Medium Kotlin Tag 5 Aug

From Android MVVM to Kotlin Multiplatform: Evolving SignalBrief for Android and iOS

Walks through evolving a single-module Android MVVM/Compose news app into SignalBrief, a Kotlin Multiplatform app with shared domain/data/presentation modules, Compose Multiplatform UI, Room KMP persistence, and Ktor+kotlinx.serialization replacing Retrofit+Gson, while keeping DI and platform hosting Android/iOS-specific.

kmpcompose-multiplatformktormvvm
Medium Kotlin Tag 7 Aug

I Shipped a Photo-Streak App in Three Weeks with One Kotlin Codebase. Here Is What I Learned.

Solo developer's account of shipping StreakShow, a photo-streak habit app, in three weeks using Kotlin Multiplatform with Compose Multiplatform for Shipaton 2026, sharing UI and ViewModels across Android and iOS. Lists three near-fatal mistakes: hidden second streak in navigation, priceless paywall, and a skipped account-deletion flow.

kmpcompose-multiplatformroom
Medium Kotlin Tag 5 Aug

Shipping OneSignal for Shipaton

Details migrating a Kotlin Multiplatform price-alert app from direct Firebase Cloud Messaging to OneSignal, switching addressing from per-device tokens to an OneSignal.login(userId) identity, a config-gated no-flag-day rollout, and a durable-inbox-first delivery pattern. Covers a Kotlin/Swift closure bridge since Kotlin can't see the Swift-only OneSignal iOS SDK.

▸ NO THROW PUSH BINDING
interface PushIdentityBinder { fun login(userId: String) fun logout() } class AndroidPushIdentityBinder : PushIdentityBinder { override fun login(userId: String) { runCatching { OneSignal.login(userId) } } override fun logout() { runCatching { OneSignal.logout() } } }
kmpios-interop
§ 06

Android Platform

Proandroiddev 3 Aug

Master Android Binder IPC & AIDL with a Hands-On Jetpack Compose Example

Walks through Android's Binder IPC and AIDL by building a three-module Gradle project (shared, server, client) where a Jetpack Compose app binds to a remote service via a generated Stub/Proxy pair. Explains why Binder beats sockets or HTTP for cross-process calls: kernel-verified identity, single-copy memory transfer, and automatic lifecycle cleanup.

▸ AIDL STUB PROXY
override fun onServiceConnected(name: ComponentName?, service: IBinder?) { iaidlColorInterface = IAIDLColorInterface.Stub.asInterface(service) } override fun onServiceDisconnected(name: ComponentName?) { iaidlColorInterface = null }
android-apicomposekotlin
Medium Kotlin Tag 3 Aug

Your Android App Is One Null Away From Crashing — Here’s Why

Walks through three real production crashes: unboxing a null Boolean pulled from a Map, throwing unguarded exceptions from a when-expression instead of using runCatching/Result, and reading a not-yet-initialized ArrayList from a BroadcastReceiver callback registered before the list was set up.

▸ RUNCATCHING RESULT
fun performOperation(op: Char, b: Double, a: Double): Result<Double> = runCatching { when (op) { '+' -> a + b '/' -> if (b == 0.0) throw UnsupportedOperationException("div0") else a / b else -> throw UnsupportedOperationException("Unknown: $op") } }
android-apikotlin
Proandroiddev 4 Aug

AI, Meet App: Testing Android App Functions

Walks through testing Android's private-preview App Functions API using adb (list-app-functions) and Google's Testing Agent app wired to a Gemini API key, verifying that natural-language prompts correctly trigger a registered function.

android-apitestingandroid-developers
Medium Android Tag 3 Aug

Update Your Target API Level by August 31, 2026: What It Means, Why It Matters, and How to Prepare

Explains Google Play's August 31, 2026 Target API Level deadline: what targetSdk/compileSdk mean, consequences of missing it, and a step-by-step checklist covering Gradle/AGP upgrades, notification permissions, scoped storage, background/foreground service limits, and staged rollout testing.

▸ TARGET SDK BUMP
android { compileSdk = 36 defaultConfig { minSdk = 24 targetSdk = 36 } }
android-apigradleandroid-developers
Proandroiddev 4 Aug

Android AppFunctions: Teaching AI Agents How to Use Your App

Explains Android AppFunctions, an API letting apps expose callable capabilities (e.g. createNote, addItemToShoppingList) so AI agents can invoke business logic directly instead of navigating the UI; includes the KSP/Gradle setup needed to register functions.

▸ KSP APPFUNCTIONS CONFIG
ksp { arg("appfunctions:aggregateAppFunctions", "true") arg("appfunctions:generateMetadataFromSchema", "false") }
android-apikspandroid-developers
Medium Kotlin Tag 4 Aug

The Android Overlay Shortcut We Almost Overbuilt (Until We Remembered What We Already Had)

Recounts choosing Accessibility Service's TYPE_ACCESSIBILITY_OVERLAY window instead of the SYSTEM_ALERT_WINDOW permission flow to show a brief popup on a kiosk tablet, since the app already ran an accessibility service for text injection and gained the overlay capability for free with no runtime permission dance.

android-apiandroid-developers
Medium Kotlin Tag 6 Aug

14/28: The Journey of a Single Touch, From Driver to Your View

Traces how a single Android touch event travels from the kernel evdev driver through InputReader/InputDispatcher in system_server, across a Unix-socket IPC hop, into ViewRootImpl's InputStage chain, before reaching dispatchTouchEvent. Explains why onInterceptTouchEvent quirks and dropped touches during fast scrolling originate upstream of app code.

android-apiandroid-developers
Commonsware 8 Aug

From Wear to Pebble

CommonsWare's Mark Murphy recounts leaving Wear OS for an open-source Pebble Time 2 after growing frustrated with Google's wearable stack, and plans to start writing Pebble apps alongside his Kotlin Multiplatform work.

wear-oskmp
Medium Kotlin Tag 3 Aug

13/28: The 16ms Frame Budget Is a Lie (Now)

Argues the classic 16ms Android frame budget only holds at 60Hz; walks through per-frame budget as 1000/refreshRate, Choreographer's skippedFrames math and its 30-frame warning threshold, and how variable refresh rate (ARR) plus Surface.setFrameRate shift the real budget at runtime.

android-apianimation
Medium Android Tag 6 Aug

Cut Android Rebuffers by 70–80%: Ten Fixes, Priced in Dev-Days

Ten prioritized fixes for Android video rebuffering in 2026: tuning Media3's LoadControl per network class, shipping AV1+HEVC while dropping VP9 (software VP9 thermal-throttles budget chips), enabling native CMCD telemetry, and reserving low-latency HLS/DASH for genuinely latency-sensitive streams, with dev-day cost estimates per fix.

media3android-api
Medium Kotlin Tag 8 Aug

Why My Flutter Timer Needed a Native Android Service

Describes how a Flutter timer app added a native Kotlin foreground service to keep countdown state accurate while the Flutter engine is paused. Uses SystemClock.elapsedRealtime() for monotonic timing, a MethodChannel bridge, and state snapshots restored on resume.

▸ MONOTONIC DEADLINE CLOCK
val now = SystemClock.elapsedRealtime() lastAccountingMs = now deadlineMs = now + remainingMs
android-api
Proandroiddev 8 Aug

On-Device AI Series (Part 4): LiteRT

Part four of an on-device AI series covering LiteRT (formerly TensorFlow Lite), Google's edge runtime for classical ML and quantized generative models like Gemma and Llama on Android. Walks through the CompiledModel API's tensor-buffer lifecycle for image classification and BERT text classification with manual int8 quantization handling.

▸ COMPILED MODEL API
compiledModel = CompiledModel.create( context.assets, "efficientnet_lite0.tflite", CompiledModel.Options(Accelerator.CPU), null ) val inputBuffers = compiledModel.createInputBuffers() val outputBuffers = compiledModel.createOutputBuffers() inputBuffers[0].writeInt8(extractPixelBytes(bitmap)) compiledModel.run(inputBuffers, outputBuffers)
android-api
Medium Kotlin Tag 8 Aug

Android Keystore in Practice: Key Generation, StrongBox, and Biometric Binding

Explains what the Android Keystore actually guarantees — hardware-backed key material via TEE or StrongBox versus software fallback — and gives a working pattern for generating an AES-256 GCM key with KeyGenParameterSpec, plus pitfalls like ECB mode or reused key aliases.

▸ HARDWARE BACKED AES KEY
val spec = KeyGenParameterSpec.Builder( KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(256) .build()
android-api
§ 07

Community

Proandroiddev 7 Aug

Android Skills — What Google Just Released and Why Most Developers Are Already Using It Wrong

Explains Google's Android Skills system, launched in April: modular SKILL.md instructions that auto-trigger for confirmed AI failure modes such as Navigation 2.8+ type-safe routing, AGP 9 migrations, and R8 analysis. Warns against installing too many skills due to token cost, and includes a sample AGENTS.md template.

▸ TYPE-SAFE NAV ROUTES
@Serializable object Home @Serializable data class Detail(val userId: String) NavHost(navController = navController, startDestination = Home) { composable<Home> { HomeScreen(onNavigateToDetail = { userId -> navController.navigate(Detail(userId)) }) } composable<Detail> { backStackEntry -> val detail: Detail = backStackEntry.toRoute() DetailScreen(userId = detail.userId) } }
android-developersnavigationcomposehilt
Jetbrains Blog 7 Aug

JetBrains Academy – July Digest

JetBrains Academy's July roundup, flagged as covering Kotlin's 15th anniversary and the IntelliJ IDEA Conf lineup announcement. The article body was blocked by a bot-check page at fetch time, so only the headline topics from the excerpt are available.

jetbrainskotlin
Android Developers Blog 6 Aug

Inside Android Skills - Built for deprecation

Android Developer Relations explains why official Android Skills for AI coding agents stay narrow: they're only built for verifiable knowledge gaps in current models, such as AGP 9, Navigation 3, Camera APIs, and Perfetto SQL, since every installed skill adds token overhead. Details the eval framework used to validate each skill before release and when smaller/cheaper models still benefit from basic skills.

android-developersgradle-pluginnavigation
Medium Kotlin Tag 3 Aug

Episode #38

Recap of Kotlin Kenya & Android254 meetup #38, hosted by Terra Softworks, covering a talk on building a BLE-based smartwatch companion app (Chronos), a panel on building products users love, and a plug for DroidCon x FlutterCon Kenya 2026 tickets.

android-developersdroidcon
§ 08

Networking

Lib Ktor 4 Aug

3.5.2

Ktor 3.5.2 release notes: RateLimit can scope limits by authentication result, ApplicationCall.isStaticContent is fixed inside plugin interceptors, ContentNegotiation handles content-type suffixes, SwaggerUI adds oauth2-redirect.html support, and kotlinx-io bumps to 0.9.1.

ktorktor-server
§ 09

Build & Tooling

Medium Kotlin Tag 4 Aug

ReTect: A Two-Layer Model for Protecting Android Apps Against Reverse Engineering

Argues obfuscation can't secure Android apps since APKs are always readable, and proposes a two-layer 'Reduce & Detect' model: proxy API keys server-side, require auth, minimize returned data, and enable R8 so a cracked APK yields nothing; then add RASP (Play Integrity, root/tamper detection) to raise attacker cost.

r8-proguardandroid-api

No articles match your current filters.

Try broadening your selection or reset all filters.