> ## Documentation Index
> Fetch the complete documentation index at: https://number0-improve-contact.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Kotlin

> Use iroh from Kotlin on the JVM or Android.

| Platform | Architectures                                                           |
| -------- | ----------------------------------------------------------------------- |
| macOS    | arm64, x86\_64                                                          |
| Linux    | x86\_64, aarch64 (glibc)                                                |
| Windows  | x86\_64                                                                 |
| Android  | aarch64, armv7 (requires [building from source](#building-from-source)) |

* **API reference:** [Kotlin API docs](https://n0-computer.github.io/iroh-ffi/kotlin/)
* **Example app:** [hello-iroh-ffi](https://github.com/n0-computer/hello-iroh-ffi/tree/main/kotlin-android), a Jetpack Compose demo that streams live positions between two devices
* **All languages:** [platform support matrix](/languages#platform-support)

The Kotlin bindings live in [iroh-ffi](https://github.com/n0-computer/iroh-ffi), generated by [uniffi-rs](https://github.com/mozilla/uniffi-rs) from the same Rust core as the Swift and Python bindings. Published to Maven Central as `computer.iroh:iroh`.

## Prerequisites

* A JDK (21 or newer) and `java` on your `PATH`
* [Gradle](https://gradle.org/)

## Install

In your `build.gradle.kts`:

```kotlin theme={null}
repositories {
    mavenCentral()
}

dependencies {
    implementation("computer.iroh:iroh:1.0.0")
}
```

<Note>
  The published artifact is single-platform. It does not yet ship a multiplatform build, so it won't cover Android or arbitrary host triples out of the box. If you need a target the artifact doesn't cover, [build the bindings from source](#building-from-source).
</Note>

## Hello, iroh

```kotlin theme={null}
import computer.iroh.*
import kotlinx.coroutines.runBlocking

private val ALPN = "hello-iroh/0".toByteArray()

fun main() = runBlocking {
    val ep = Endpoint.bind(
        EndpointOptions(preset = presetN0(), alpns = listOf(ALPN)),
    )
    println("endpoint id: ${ep.id()}")
    ep.shutdown()
}
```

Drop this in any module that depends on the generated `computer.iroh` package. The API mirrors the Swift and Python bindings: same `Endpoint.bind`, same `EndpointOptions`, same presets.

## Next steps

<Card title="Connect two endpoints" icon="rocket" href="/connect-two-endpoints" horizontal>
  Walkthrough of endpoints, tickets, and ALPNs. Code samples are Rust but APIs map 1:1 to Kotlin.
</Card>

<Card title="hello-iroh-ffi example app" icon="github" href="https://github.com/n0-computer/hello-iroh-ffi" horizontal>
  A full working Jetpack Compose demo: two devices stream live positions to each other at 60 Hz and show whether the connection is direct or relayed.
</Card>

<Card title="Kotlin API reference" icon="book" href="https://n0-computer.github.io/iroh-ffi/kotlin/" horizontal>
  Generated Dokka reference for the `computer.iroh` package.
</Card>

<Card title="iroh-ffi on GitHub" icon="github" href="https://github.com/n0-computer/iroh-ffi" horizontal>
  Source, Kotlin tests, and issue tracker.
</Card>

## Foreground and backgrounding

On Android, the OS aggressively suspends background processes: sockets get torn down, threads stop scheduling, and an iroh endpoint that was happily accepting connections a moment ago goes silent. Treat each foreground/background transition as a lifecycle event for your endpoint:

* **Going to background**: call `ep.shutdown()` to close cleanly and release sockets. Persist the endpoint's secret key (`ep.secretKey().toBytes()`) somewhere durable (e.g. `EncryptedSharedPreferences`) so the next bind keeps the same endpoint id.
* **Returning to foreground**: re-bind with `EndpointOptions(secretKey = persistedBytes, preset = presetN0(), ...)`. Discovery republishes the new direct addresses automatically.
* **Staying live while backgrounded**: run iroh inside an [Android foreground service](https://developer.android.com/develop/background-work/services/foreground-services) (with the appropriate `FOREGROUND_SERVICE_*` permission for your use case). Without one, Android will eventually kill the network sockets regardless of how the coroutine scope is structured.

For desktop JVM apps these constraints don't apply. Keep the endpoint bound for the lifetime of the process and call `shutdown()` on exit.

## Building from source

For Android, an unsupported host, or to hack on the bindings themselves, clone iroh-ffi and generate the sources locally:

```bash theme={null}
git clone https://github.com/n0-computer/iroh-ffi
cd iroh-ffi
cargo install cargo-make
cargo make bindgen-kotlin     # generates Kotlin sources + the cdylib
cargo make test-kotlin        # bindgen + ./gradlew test (optional)
```

The Kotlin sources land in `kotlin/lib/src/main/kotlin/` and the native library is staged into `kotlin/lib/src/main/resources/`. Point your project at that lib module via `settings.gradle.kts` to consume it instead of the Maven artifact.

For Android, install the [Android NDK](https://developer.android.com/ndk) via Android Studio and point Cargo at it via `.cargo/config.toml`. The relevant ABI targets are `aarch64-linux-android`, `armv7-linux-androideabi`, `i686-linux-android`, and `x86_64-linux-android`. The full NDK config template is in the [iroh-ffi Kotlin README](https://github.com/n0-computer/iroh-ffi/blob/main/README.kotlin.md#android-development).
