Osama Raddad

Android Team Lead at Vynatix · Gothenburg, Sweden

I lead an Android team in Gothenburg, work on Android Automotive, and write Kotlin libraries for crash recovery, dependency injection and transactional state.

See the work Email me

About

I’m an Android engineer in Gothenburg and Android Team Lead at Vynatix. I work on Android Automotive. From 2019 to 2021 I worked on in-vehicle system apps for Volvo Trucks: the media core, the media player and the default launcher. Before that I spent 2017 to 2019 on ArabiaWeather’s Android apps.

I also write Kotlin libraries in the open. FireCrasher recovers Android apps from uncaught exceptions instead of letting them die. Warehouse wires dependencies with a Kotlin DSL. Holdfast and Hallmark, built at Vynatix, bring transactions and validated types to Kotlin Multiplatform.

As of October 2026

  • Android Team Lead at Vynatix, a small software consultancy in Gothenburg that is part of Ultra Group.
  • Working on Holdfast, a transactional state library for Kotlin Multiplatform. It is pre-release.

Off the clock: I take photographs.

Languages: Arabic, English, Swedish (elementary).

Last updated:

Work

Highlighted names in the listings are the project’s own API.

Android library

FireCrasher

Catch an uncaught exception on the main thread and get the user back to a working screen.

Status

  • 2.x on JitPack
  • 3.0 on master

FireCrasher is an Android library that catches uncaught exceptions on the main thread and recovers the app instead of letting it crash. It replaces Android’s main-thread message loop with one that dispatches each message inside a try/catch. When something throws, your onCrash handler gets the exception first, so crash reporting still works, and then the library recovers in steps. The main-loop interception is adapted from SafeLooper (mmin18, 2013); the recovery ladder, back-stack tracking and handler API are FireCrasher’s own. I started it in 2016 and moved most of it to Kotlin in 2019. It was modernized, and made fully Kotlin, in 2026.

How it differs: Crash reporters such as Crashlytics, Sentry and Bugsnag record a crash, but the app still dies. FireCrasher keeps it running: it passes the exception to your reporter first, then recovers.

  • Recovery ladder: the first two crashes restart the activity. The third goes back if there is a screen behind it, and relaunches the app from its launcher activity if there isn’t.
  • On API 30+, the recovery level and retry count are saved with the process (a 5-byte state summary). If the process dies mid-recovery and the app relaunches within 30 seconds, the next crash picks up the ladder where it left off. (On master.)
  • Native crashes and ANRs kill the process before any handler runs. On API 30+, FireCrasher reads the system’s exit record on the next launch and passes it to onPreviousProcessExit { }. context.lastAbnormalExit() and context.historicalExitReasons() query the same records on demand. (On master.)
  • The public API is locked down with Kotlin explicit-API mode and a committed binary-compatibility baseline, both checked on every CI build. 34 JUnit and Robolectric tests. (On master.)
  • 7 merged pull requests from 5 outside contributors, 2016 to 2022.
Listing 1 3.0 API on master (not yet tagged) Kotlin
installFireCrasher {
    onCrash {
        FirebaseCrashlytics.getInstance().recordException(throwable)   // or Sentry, Bugsnag, …
        recover()
    }
}

Report the crash first, then recover. This DSL is on master and isn’t in a tagged release yet.

Listing 2 Install (JitPack) Groovy
repositories { maven { url 'https://jitpack.io' } }

dependencies {
    implementation 'com.github.osama-raddad:FireCrasher:2.0.0'
}

2.0.0 is the newest release with a clean JitPack build (2.0.1’s build is marked as failed). Like 2.0.1, it uses the 2.x CrashListener API.

Status
  • 2.x on JitPack
  • 3.0 on master
Years
2016–2026
Facts
Built with
  • Kotlin
  • Android
  • AndroidX Activity
  • Robolectric
  • GitHub Actions
  • JitPack

Kotlin library

Warehouse

Dependency injection, written as a Kotlin DSL.

Status

  • Released · 1.6.8x

Warehouse is a dependency injection library for the JVM, written as a Kotlin DSL. It wires dependencies with nested warehouse { module { factory { } } } blocks and hands them out through property delegation (by mainDI()). A warehouse can include other warehouses, and its accessibility level (OPEN, LOCAL or ISOLATED) decides which bindings pass up to the warehouse that includes it. Each factory can be named, exposed as an interface, and limited to the classes allowed to receive it.

How it differs: Dagger/Hilt and Koin are the established choices for dependency injection on Android. Warehouse is a smaller, DSL-based alternative for the JVM, and its own angle is access control: you decide which classes may receive a binding, and which bindings a warehouse passes up to the one that includes it.

  • injectsIn { Demo::class } limits who can receive a binding. Injecting it anywhere else fails with an error that names both classes.
  • @Named picks between bindings of the same type, and constructor parameters resolve from the graph with param() or param(name).
  • Three creation patterns: NEW, SINGLETON and REUSABLE.
  • Tests with JaCoCo coverage, Detekt and Dokka API docs were set up in GitHub Actions in 2022.
Listing 3 Adapted from the README Kotlin
val mainDI = warehouse(Accessibility.LOCAL) {
    warehouse { namesDI }
    module {
        factory {
            name { "GoodPerson" }
            constructor { GoodPerson(param(FIRST_NAME), param(LAST_NAME)) }
            injectsIn { Demo::class }
            contract { Person::class }
        }
    }
}

class Demo {
    @Named("GoodPerson")
    private val goodPerson: Person by mainDI()
}

One named factory, exposed as Person and injectable only into Demo.

Listing 4 Install (JitPack) Groovy
repositories { maven { url 'https://jitpack.io' } }

dependencies {
    implementation 'com.github.osama-raddad:Warehouse:1.6.8x'
}
Status
  • Released · 1.6.8x
Years
2022
Facts
Built with
  • Kotlin/JVM
  • kotlin-reflect
  • JUnit 5
  • MockK
  • Detekt
  • Dokka
  • JitPack

Kotlin Multiplatform library · Built at Vynatix

Holdfast

Transactional state for Kotlin Multiplatform.

Status

  • Pre-release · not yet published

Holdfast is a transactional state library for Kotlin Multiplatform. A store holds state, and its unit of consistency is the transaction. Inside action { } mutations are buffered and observers only see committed values. If the block throws, the whole action rolls back and nothing leaks. atomic(a, b) { } stretches that guarantee across stores: they all commit, or none of them do.

Why it exists: In a plain state holder such as MutableStateFlow, every write is published as soon as it is made, so an exception halfway through a multi-step update leaves half-applied state behind. Holdfast publishes once, on commit, and rolls everything back if the block throws.

It grew out of Vault (December 2024), a JVM Kotlin state container on my own GitHub where action { } blocks already rolled back on an exception.

  • action { } returns TransactionResult.Success or TransactionResult.Error. A failed transaction rolls back and its observers never fire.
  • atomic() and suspendAtomic() run an in-memory two-phase commit across stores, taking locks in one global order so frames can’t deadlock each other.
  • The frame is enforced: writing to a store you didn’t enroll throws, so it can’t commit on its own.
  • Separate modules for coroutines (Flow and StateFlow adapters, suspendAction), Compose (collectAsState) and tests (storeTest { }).
  • CI runs the tests on JVM, Android (host tests) and the iOS simulator. The wasmJs target is experimental.

Install: Not yet published

Listing 5 Cross-store transaction, from the README Kotlin
val transfer = atomic(accountA, accountB) {
    accountA.action { balance update { it - 30 } }
    accountB.action { balance update { it + 30 } }
    "transferred"
}

Both balances change together, or neither does.

Status
  • Pre-release · not yet published
Years
2026 (Vault: 2024–2025)
Facts
  • Apache-2.0
  • 0.x
Built with
  • Kotlin Multiplatform
  • Coroutines
  • Compose Multiplatform
  • Android
  • iOS
  • JVM

Kotlin Multiplatform library · Built at Vynatix

Hallmark

Refinement types for Kotlin Multiplatform.

Status

  • Pre-release · not yet published

Hallmark turns a raw String or Long into a type such as Email or Age, built through a validator that checks the value first. Validation accumulates, so you get every violation at once, each with the path to the field that failed. Uncivilized (2022) was my earlier take on the same idea: a small JVM library that wraps raw primitives in typed objects through rules and variations.

  • Typed wrappers (Boxed<T>), validators built from rule specs, and an infix of to construct a value.
  • A failure in a nested field arrives with its path, for example ["address", "zip"].
  • hallmark-coroutines adds suspending validation for checks such as database lookups.

Install: Not yet published (Uncivilized: implementation 'com.github.osama-raddad:Uncivilized:1.0.1' via JitPack)

Listing 6 From the README Kotlin
data class Email(override val value: String) : Boxed<String>

object EmailValidator : BoxedValidator<String, Email>() {
    override val specs = listOf(
        Spec(
            rules   = listOf(NonBlankRule(), LengthInRule(3..254), MatchesRule(Regex(".+@.+"))),
            mode    = SpecMode.ALL,
            factory = ::Email,
        ),
    )
}

val email: Email = EmailValidator of "alice@example.com"

EmailValidator of … returns a typed Email, or throws with every violation.

Status
  • Pre-release · not yet published
Years
2026 (Uncivilized: 2022–2023)
Facts
  • Hallmark Apache-2.0
  • Uncivilized has no license file
Built with
  • Kotlin Multiplatform
  • Coroutines
  • Android
  • iOS
  • JVM

Android library

gentle-palette

Snap any color to the nearest color in a palette.

Status

  • Released · 0.1.3
  • (round() unreleased)

gentle-palette is an Android library that snaps a color to the nearest color in a palette: give it a color int and an array of #RRGGBB strings and you get back the closest entry. It was made to sit next to Android’s Palette library: take the dominant color of an image and round it to the nearest flat or Material color. The released 0.1.3 uses a callback and plain RGB distance. Master was modernized in 2026 with a direct round() call and redmean-weighted distance, and isn’t released yet.

  • Five built-in palettes: flat, Material, social brand colors, Fluent and Metro.
  • No runtime dependencies.
  • Listed in the Android section of awesome-jordan since 2018.
  • Unreleased on master: round() returns the color directly, validates its input, and has 12 JUnit tests.
Listing 7 0.1.3 callback API, from the demo app Java
GentlePalette.generate(palette.getDominantColor(ContextCompat.getColor(this, android.R.color.white)), Palettes.FLAT_COLORS,
        findViewById(R.id.toolBar)::setBackgroundColor);

Round an image’s dominant color to a flat color and paint the toolbar with it.

Listing 8 Install (JitPack) Groovy
repositories { maven { url 'https://jitpack.io' } }

dependencies {
    implementation 'com.github.osama-raddad:gentle-palette:0.1.3'
}
Status
  • Released · 0.1.3
  • (round() unreleased)
Years
2017–2026
Facts
Built with
  • Java
  • Android
  • JitPack
  • JUnit 4

Kotlin Multiplatform app (proof of concept)

vin-dating-app

One Compose Multiplatform UI on Android, iOS, desktop and the web.

Status

  • Proof of concept

A proof of concept for a dating app’s UI flow, written once in Compose Multiplatform. It goes from onboarding to phone number entry, a six-digit code screen, profile setup and a tabbed home screen, with sample data and no backend. The same module builds for Android, iOS through a SwiftUI host, desktop JVM, and the browser through Kotlin/Wasm.

Why it exists: It is a demonstration, not a product: one Compose Multiplatform UI flow running on Android, iOS, desktop and the web from a single module, with no backend behind it.

  • One :composeApp module: commonMain plus Android, iOS, desktop and wasmJs source sets.
  • Navigation is a sealed Screen class driven by state, with no navigation library.
  • A Ktor client with per-platform engines (Android, Darwin, OkHttp) and an auth layer that isn’t connected to a backend yet.
  • Desktop packaging for DMG, MSI and DEB.
  • Kotlin 2.2.0, Compose Multiplatform 1.8.2, Material 3.

Install: Not published (an app).

Listing 9 The whole navigation model Kotlin
sealed class Screen {
    object Onboarding : Screen()
    object PhoneAuth : Screen()
    data class VerificationCode(val phoneNumber: String) : Screen()
    object ProfileSetup : Screen()
    object Home : Screen()
}

Five screens, one sealed class, one when.

Status
  • Proof of concept
Years
2025
Facts
  • Kotlin Multiplatform
  • 4 platforms
  • no license file
Built with
  • Kotlin Multiplatform
  • Compose Multiplatform
  • Material 3
  • Ktor
  • Kotlin/Wasm
  • SwiftUI

Older work

  • Slick-Slider (2018): auto-playing timeline slider views for Android, with right-to-left variants.
  • Shaper (2018): splits Activities and Fragments into lifecycle-aware components, each with its own RxJava disposables.
  • Semple-Weather (2018): a small Kotlin weather app, with an Express backend.

Experience

Over ten years of Android engineering.

  1. Now · Vynatix, Gothenburg

    Role: Android Team Lead

    • I work on Android Automotive.
    • Holdfast and Hallmark, two pre-release Kotlin Multiplatform libraries, were built here and are open source on the Vynatix GitHub.

    vynatix.com

  2. 2019–2021 · Volvo Trucks in-vehicle system apps

    • Media Core: the system app that manages the truck’s media sources, including phone projection, Bluetooth, USB and radio.
    • Also the Media Player, the interface for USB and Bluetooth media, and the truck’s default launcher (2020–2021).
  3. 2017–2019 · ArabiaWeather

    Scope: the ArabiaWeather Android apps

    • The Android app and its crowd-sourced weather reports, where users post photos, video or text about the weather around them.
    • Maater (2019): an Android app in a rain and flood early-warning system for the Saudi Arabian government. ArabiaWeather CEO Award in 2018 and 2019.
  4. 2010–2015 · Zarqa University

Writing

Recent, 2023–2025

  1. Medium

    Treats a model’s context as something you assemble on purpose, from instructions, knowledge, tools, memory, state and the query, then covers RAG, memory, compression and security.

  2. Medium

    An essay on the team as the compiler that turns requirements into software, opening with the 13 people behind Instagram.

  3. Medium

    Streaming an Android device’s audio to a Windows PC with scrcpy, with sndcpy and AudioRelay for older devices.

  4. Medium

    One-time and periodic work, constraints, chaining, and watching WorkInfo with Jetpack WorkManager.

  5. MindOrks

    Gerrit’s review workflow for people who already know Git: pushing to refs/for, amending a change, review scores and rebasing.

Archive, 2019–2020

  1. Medium

    Content providers, shared preferences, files and SQLite, with everyday analogies for content providers and shared preferences.

  2. MindOrks

    What a crash costs you with users, and how FireCrasher’s three recovery levels keep the app running. See FireCrasher, section 2.1

More on Medium

Community

FAQ

Who is Osama Raddad?

Osama Raddad is an Android engineer in Gothenburg, Sweden, and Android Team Lead at Vynatix, a small software consultancy that is part of Ultra Group. The work is Android Automotive. Earlier work includes in-vehicle system apps for Volvo Trucks (2019–2021) and ArabiaWeather’s Android apps (2017–2019). Open-source Kotlin libraries include FireCrasher, Warehouse, Holdfast and Hallmark.

What is FireCrasher?

FireCrasher is an Android library that catches uncaught exceptions on the main thread and recovers the app instead of letting it crash. The first two crashes restart the activity. The third goes back if there is a screen behind it, and relaunches the app from its launcher activity if there isn’t. See FireCrasher, section 2.1.

How do I install FireCrasher?

From JitPack: add the JitPack repository and com.github.osama-raddad:FireCrasher:2.0.0, the newest release with a clean JitPack build. The 3.0 API is on master and isn’t in a tagged release yet. The full snippet is Listing 2 in FireCrasher, section 2.1.

Does FireCrasher replace Crashlytics, Sentry or Bugsnag?

No. Crash reporters record a crash, but the app still dies. FireCrasher keeps the app running, and your onCrash handler gets each exception first, so you can send it to Crashlytics, Sentry or Bugsnag and then call recover().

What is Warehouse, and how does it compare with Dagger and Koin?

Warehouse is a dependency injection library for the JVM, written as a Kotlin DSL: dependencies are wired with nested warehouse { module { factory { } } } blocks and handed out through property delegation. Dagger/Hilt and Koin are the established choices on Android. Warehouse is a smaller, DSL-based alternative, and its own angle is access control: injectsIn { } limits which classes may receive a binding, and a warehouse’s accessibility level decides which bindings pass up to the warehouse that includes it. See Warehouse, section 2.2.

What is Holdfast, and can I use it yet?

Holdfast is a transactional state library for Kotlin Multiplatform: changes inside an action { } block either all commit or all roll back, and atomic() extends that across stores. It is pre-release and not yet published. See Holdfast, section 2.3.

Why use Holdfast instead of a plain MutableStateFlow?

In a plain MutableStateFlow, every write is published as soon as it is made, so an exception halfway through a multi-step update leaves half-applied state behind. Holdfast buffers the writes inside action { }, publishes once on commit, and rolls everything back if the block throws.

Which platforms does Holdfast support?

Holdfast is for Kotlin Multiplatform: JVM, Android and iOS. CI runs its tests on the JVM, on Android (host tests) and on the iOS simulator, and the wasmJs target is experimental. Separate modules cover coroutines (Flow and StateFlow), Compose and tests.

Get in touch

If you have a question about one of these libraries, or want to work together, email me.