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

1 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.

Currently

  • 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).

2 Work

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

Flagship · Android library

2.1 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 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.

  • 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
  • 147 GitHub stars
  • 30 forks
  • Apache-2.0
Built with
  • Kotlin
  • Android
  • AndroidX Activity
  • Robolectric
  • GitHub Actions
  • JitPack

Flagship · Kotlin library

2.2 Warehouse

Dependency injection, written as a Kotlin DSL.

Status

  • Released · 1.6.8x

Warehouse 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. It runs on the JVM.

  • 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
  • 19 GitHub stars
  • Apache-2.0
Built with
  • Kotlin/JVM
  • kotlin-reflect
  • JUnit 5
  • MockK
  • Detekt
  • Dokka
  • JitPack

Flagship · Kotlin Multiplatform library · Built at Vynatix

2.3 Holdfast

Transactional state for Kotlin Multiplatform.

Status

  • Pre-release · not yet published

A Holdfast 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.

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

Featured · Kotlin Multiplatform library · Built at Vynatix

2.4 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

Featured · Android library

2.5 gentle-palette

Snap any color to the nearest color in a palette.

Status

  • Released · 0.1.3
  • (round() unreleased)

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
  • 1 GitHub stars
  • Apache-2.0
Built with
  • Java
  • Android
  • JitPack
  • JUnit 4

Featured · Kotlin Multiplatform app (proof of concept)

2.6 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.

  • 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

2.7 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.

3 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

4 Writing

  1. Medium

    Context Engineering: The Architecture of AI Understanding

    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

    The Human Compiler

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

  3. Medium

    Stream what you hear: Android to Windows audio

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

  4. Medium

    Mastering WorkManager in Android

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

  5. MindOrks

    The Gerrit Playbook

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

  6. Medium

    Storage options in Android

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

  7. MindOrks

    The Wicked Android Crashes and How to Disarm them

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

More on Medium

5 Community

6 Get in touch

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