Skip to content

Kotlin SDK (Android & KMP)

Maven Central

Replace LAST_VERSION with the version shown on the badge.

Since 2.0 the SDK is split into one module per feature: add the core, then only the modules you use. Every module has a -no-op twin with the same API, so release builds ship nothing.

Requirements: Android API 23+, or a Kotlin Multiplatform project (Android, JVM, iOS, Wasm).

Let your AI agent do it

The Flocon plugin adds the dependencies, starts Flocon and keeps it out of release builds for you.

1. Add the dependencies

[versions]
flocon = "LAST_VERSION"

[libraries]
flocon = { module = "io.github.openflocon:flocon", version.ref = "flocon" }
flocon-no-op = { module = "io.github.openflocon:flocon-no-op", version.ref = "flocon" }

flocon-network = { module = "io.github.openflocon:flocon-network-core", version.ref = "flocon" }
flocon-network-no-op = { module = "io.github.openflocon:flocon-network-core-no-op", version.ref = "flocon" }
flocon-okhttp = { module = "io.github.openflocon:flocon-okhttp-interceptor", version.ref = "flocon" }
flocon-okhttp-no-op = { module = "io.github.openflocon:flocon-okhttp-interceptor-no-op", version.ref = "flocon" }
flocon-analytics = { module = "io.github.openflocon:flocon-analytics", version.ref = "flocon" }
flocon-analytics-no-op = { module = "io.github.openflocon:flocon-analytics-no-op", version.ref = "flocon" }
# ... one pair per module you use, see the table below
// app/build.gradle.kts
dependencies {
    debugImplementation(libs.flocon)
    releaseImplementation(libs.flocon.no.op)

    debugImplementation(libs.flocon.network)
    releaseImplementation(libs.flocon.network.no.op)
    debugImplementation(libs.flocon.okhttp)
    releaseImplementation(libs.flocon.okhttp.no.op)
    debugImplementation(libs.flocon.analytics)
    releaseImplementation(libs.flocon.analytics.no.op)
}

The flocon-bom pins every Flocon module (and its -no-op) to the same version: declare the version once, then leave the modules without a version.

[libraries]
flocon-bom = { module = "io.github.openflocon:flocon-bom", version = "LAST_VERSION" }
flocon = { module = "io.github.openflocon:flocon" }
flocon-no-op = { module = "io.github.openflocon:flocon-no-op" }
flocon-network = { module = "io.github.openflocon:flocon-network-core" }
flocon-network-no-op = { module = "io.github.openflocon:flocon-network-core-no-op" }
dependencies {
    debugImplementation(platform(libs.flocon.bom))
    releaseImplementation(platform(libs.flocon.bom))

    debugImplementation(libs.flocon)
    releaseImplementation(libs.flocon.no.op)

    debugImplementation(libs.flocon.network)
    releaseImplementation(libs.flocon.network.no.op)
}
dependencies {
    debugImplementation("io.github.openflocon:flocon:LAST_VERSION")
    debugImplementation("io.github.openflocon:flocon-network-core:LAST_VERSION")
    debugImplementation("io.github.openflocon:flocon-okhttp-interceptor:LAST_VERSION")

    releaseImplementation("io.github.openflocon:flocon-no-op:LAST_VERSION")
    releaseImplementation("io.github.openflocon:flocon-network-core-no-op:LAST_VERSION")
    releaseImplementation("io.github.openflocon:flocon-okhttp-interceptor-no-op:LAST_VERSION")
}
kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("io.github.openflocon:flocon:LAST_VERSION")
            implementation("io.github.openflocon:flocon-network-core:LAST_VERSION")
            implementation("io.github.openflocon:flocon-ktor-interceptor:LAST_VERSION")
        }
    }
}

A multiplatform module has a single variant: swap the real modules for the no-ops in the release configurations of the app, see Release builds.

All modules (Maven group io.github.openflocon; add -no-op to the artifact name for the release twin):

Feature Artifact Platforms
Core, Dashboards flocon Android, JVM, iOS, Wasm
Network (mocks, bad network, WebSocket logging) flocon-network-core Android, JVM, iOS, Wasm
OkHttp interceptor (+ WebSockets) flocon-okhttp-interceptor Android, JVM
Ktor plugin flocon-ktor-interceptor Android, JVM, iOS, Wasm
gRPC flocon-grpc-interceptor, flocon-grpc-interceptor-lite, flocon-grpc-interceptor-base Android
Databases flocon-database-core + flocon-database-room (Room 2) or flocon-database-room3 (Room 3) or flocon-database-sqldelight Android, JVM, iOS (+ Wasm for Room 3)
Preferences flocon-sharedprefs Android, JVM, iOS, Wasm
DataStore flocon-datastores Android, JVM, iOS
Files flocon-files Android, JVM, iOS, Wasm (no file browsing on Wasm)
Tables flocon-tables Android, JVM, iOS, Wasm
Deeplinks flocon-deeplinks Android, JVM, iOS, Wasm
Analytics flocon-analytics Android, JVM, iOS, Wasm
Feature flags flocon-feature-flags Android, JVM, iOS, Wasm
Timeline flocon-timeline Android, JVM, iOS, Wasm
Crash reporter flocon-crashreporter Android, JVM, iOS, Wasm
Accessibility flocon-accessibility Android, JVM, iOS, Wasm (automatic capture on Android and iOS)
WebView flocon-webview Android, JVM, iOS, Wasm (automatic attach on Android)
QR code scanner flocon-qr-scanner Android
BOM flocon-bom all

2. Start Flocon

Start the SDK as early as possible, then install the features you use. A feature that is not installed does nothing instead of crashing, so calls to it can stay in your code.

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()

        startFlocon(FloconContext(this)) {
            install(FloconNetwork)
            install(FloconAnalytics)
        }
    }
}
fun main() {
    startFlocon(FloconContext(appName = "My App", packageName = "com.example.myapp")) {
        install(FloconNetwork)
        install(FloconAnalytics)
    }
    // launch your application
}
fun initFlocon() {
    startFlocon(FloconContext()) {
        install(FloconNetwork)
        install(FloconAnalytics)
    }
}

Each plugin is then reachable with Flocon.xxxPlugin (for example Flocon.analyticsPlugin.log(...)). Set FloconLogger.enabled = true to see what Flocon does (connection, plugins not installed...).

Plugin to install Module Page
FloconNetwork flocon-network-core (+ OkHttp / Ktor / gRPC interceptor) Network
FloconDatabase flocon-database-core + a Room / SQLDelight provider Databases
FloconPreferences flocon-sharedprefs (+ flocon-datastores) Preferences
FloconFiles flocon-files Files
FloconDashboard flocon Dashboards
FloconTable flocon-tables Tables
FloconDeeplinks flocon-deeplinks Deeplinks
FloconAnalytics flocon-analytics Analytics
FloconFeatureFlags flocon-feature-flags Feature flags
FloconCrashReporter flocon-crashreporter Crash reporter
FloconWebView flocon-webview WebView
FloconTimeline flocon-timeline Timeline
FloconAccessibility flocon-accessibility Accessibility

Release builds

Flocon is a debugging tool: once connected, the desktop can read your network calls, edit your preferences, delete files and run SQL on your databases. Keep it out of release builds.

Use debugImplementation with the -no-op twin in releaseImplementation, as in step 1. The no-op has the same API: nothing is started and no connection is made. Use flocon-no-op and the no-op of every module you use. In a shared Kotlin Multiplatform module, which has a single variant, swap the modules in the release configurations of the app:

// app/build.gradle.kts
val floconNoOps = mapOf(
    "io.github.openflocon:flocon" to "io.github.openflocon:flocon-no-op:LAST_VERSION",
    "io.github.openflocon:flocon-network-core" to "io.github.openflocon:flocon-network-core-no-op:LAST_VERSION",
    "io.github.openflocon:flocon-ktor-interceptor" to "io.github.openflocon:flocon-ktor-interceptor-no-op:LAST_VERSION",
    // ... one line per Flocon module you use
)

configurations.configureEach {
    if (name.startsWith("release")) {
        resolutionStrategy.dependencySubstitution {
            floconNoOps.forEach { (module, noOp) ->
                substitute(module(module)).using(module(noOp))
            }
        }
    }
}

The no-ops are binary compatible: code compiled against the real modules runs on them.

Next: connect

Run the app with Flocon Desktop open: on an Android emulator or a USB device it connects by itself. See Connect.