btw: MoQ is under active development. The APIs and protocols are still evolving and will change. Most of this documentation is AI generated until things get more stable.

Skip to content

Kotlin Libraries

The Kotlin bindings expose Media over QUIC to Android apps and JVM-based services. Built on the same Rust core (moq-ffi) as the Python and Swift packages, wrapped with idiomatic Flow and coroutines.

Packages

Two Kotlin Multiplatform artifacts, each publishing JVM and Android variants under one coordinate.

dev.moq:moq

The ergonomic wrapper. Pure Kotlin layered on dev.moq:moq-ffi: a Moq.connect(...) facade, Flow-based async sequences with structured cancellation, and clean dev.moq typealiases for the FFI types. Versioned independently of the crate. Most consumers want this.

dev.moq:moq-ffi

The raw UniFFI bindings (uniffi.moq.*) plus the native binaries (JNI on Android, JNA on desktop JVM: Linux, macOS, Windows; arm64-v8a, armeabi-v7a, x86_64). Auto-released on every moq-ffi-v* tag, so its version tracks the crate. Depend on it directly only if you want the FFI surface without the wrapper.

Learn more

Installation

kotlin
// build.gradle.kts
dependencies {
    implementation("dev.moq:moq:0.4.3")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
}

The wrapper depends on dev.moq:moq-ffi:[0.3,0.4), so Gradle pulls the newest bindings patch (with its bundled native binaries) automatically; no extra setup is needed on the consumer side. The wrapper publishes via release-kt-lib.yml and the bindings via release-kt-ffi.yml.

Quickstart

kotlin
import dev.moq.*
import kotlinx.coroutines.flow.collect

Moq.connect("https://relay.example.com").use { moq ->
    moq.announcements("demos/").collect { announcement ->
        println("got broadcast ${announcement.path()}")

        announcement.broadcast().subscribeCatalog().updates().collect { catalog ->
            println("catalog: $catalog")
        }
    }
}

Moq.connect wires an internal origin for publish + subscribe and returns a Moq you can use {}. Cancelling the surrounding coroutine scope propagates through to the native consumer's cancel() via the wrapper's onCompletion hook.

Source and issues

Licensed under MIT or Apache-2.0