Get Started
Add the recorder for your UI toolkit, initialise Coryn in your Application, then start recording when appropriate for your app's consent flow. See Introduction for build requirements.
Add the Maven repository
Declare the repository in your Gradle settings:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://nexus.coryn.ai/repository/android-public")
}
}
Add dependencies
Choose one recorder dependency. recorder-compose includes the View recorder and core API; recorder includes the core API.
- Compose or mixed UI
- XML Views
dependencies {
implementation("ai.coryn.replay.api:recorder-compose:1.1.123")
}
dependencies {
implementation("ai.coryn.replay.api:recorder:1.1.123")
}
Use the same Coryn version for every artifact. Optional modules:
dependencies {
// Choose one if you want map-based States.
implementation("ai.coryn.replay.api.state-serialization:gson:1.1.123")
// implementation("ai.coryn.replay.api.state-serialization:moshi:1.1.123")
// In-app diagnostics for development builds only.
debugImplementation("ai.coryn.replay.api:log-viewer:1.1.123")
}
A build variant that does not need session recording can use ai.coryn.replay.api:core:1.1.123 instead of a recorder. Core does not include the Compose integration, so code referencing Coryn Composables or modifiers still needs recorder-compose.
Release artifacts include consumer R8 rules. See Artifacts Verification for signatures and SBOMs.
Enable core library desugaring
If your app's minSdk is 25 or lower, enable desugaring with the _nio variant:
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs_nio:2.1.5")
}
This is required for the SDK's file APIs on Android 6.0–7.1. It also applies if desugaring was already enabled with desugar_jdk_libs: replace that artifact with desugar_jdk_libs_nio.
Initialise the SDK
Call Coryn.init() after super.onCreate() in your custom Application, using your project API key from the Coryn AI Dashboard. Initialise once per application process lifetime, before calling any other Coryn API. Further initialisation calls do not replace the first configuration.
- Kotlin
- Java
import android.app.Application
import ai.coryn.replay.api.core.main.Coryn
class CustomApplication : Application() {
override fun onCreate() {
super.onCreate()
Coryn.init(this, BuildConfig.CORYN_AI_API_KEY) {
network {
isUploadOnMeteredNetworkAllowed = false
}
}
}
}
import android.app.Application;
import ai.coryn.replay.api.core.main.Coryn;
import ai.coryn.replay.api.core.model.configuration.CorynConfiguration;
public class CustomApplicationJava extends Application {
@Override
public void onCreate() {
super.onCreate();
CorynConfiguration configuration = CorynConfiguration.Builder()
.setUploadOnMeteredNetworkAllowed(false)
.build();
Coryn.init(this, BuildConfig.CORYN_AI_API_KEY, configuration);
}
}
BuildConfig.CORYN_AI_API_KEY is an app-defined build field. Supply it through your build configuration instead of committing the value to source control. An API key embedded in an Android app remains extractable from that app.
Register your Application class in the manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:name=".CustomApplication">
<!-- Your application's components. -->
</application>
</manifest>
Initialisation configuration
The Kotlin DSL and CorynConfiguration.Builder() configure the same options:
| Kotlin option | Default |
|---|---|
network.baseUrl | "https://api.coryn.ai/api/" |
network.isUploadOnMeteredNetworkAllowed | false |
logViewerIndicator.visibility | VISIBLE_IF_ANY_ERRORS |
logViewerIndicator.paddingTop | 0 dp |
logViewerIndicator.paddingRight | 0 dp |
Java builder methods are setNetworkBaseUrl, setUploadOnMeteredNetworkAllowed, setLogViewerIndicatorVisibility, setLogViewerIndicatorPaddingTop, and setLogViewerIndicatorPaddingRight, followed by build().
Leave baseUrl at its default for Coryn Cloud; set it only for a self-hosted deployment. It is configured inside network { }.
By default, recording and diagnostic uploads wait for an unmetered network. To permit uploads on metered networks, including cellular or metered Wi-Fi, set isUploadOnMeteredNetworkAllowed = true at initialisation. This controls uploads, not whether sessions are recorded or all SDK network requests. See Synchronisation.
The optional Log Viewer indicator opens the in-app diagnostics screen when tapped. Configure it inside logViewerIndicator { }. Top padding is added to the built-in status bar offset; negative padding reduces the offset. The visibility enum is ai.coryn.replay.shared.logviewer.CorynLogViewerIndicatorVisibility:
| Value | Behaviour |
|---|---|
VISIBLE_ALWAYS | Always visible |
VISIBLE_IF_ANY_ERRORS | Visible for warnings or errors; orange for warnings, red for critical errors |
VISIBLE_IF_RECORDING_CRITICAL_ERRORS | Visible when a critical error cancels recording |
GONE | Hidden |
Keep the Log Viewer dependency in development builds only. Changing the indicator configuration does not install the Log Viewer module.
Start recording
Call Coryn.startRecording() after initialisation, optionally after obtaining user consent. The first request supplies the recording configuration; later requests do not update it or restart a stopped recording. Recording also depends on the project's feature flags and having a recorder dependency installed.
- Kotlin
- Java
import ai.coryn.replay.api.core.main.Coryn
import ai.coryn.replay.shared.listener.CorynRecordingListener
import ai.coryn.replay.shared.uicapture.OverscrollStrategy
Coryn.startRecording {
isUiCapturingEnabled = true
overscrollStrategy = OverscrollStrategy.AdditionalPaddingPercent(5f)
memoryLeakCodePackages = setOf("com.example.checkout")
listener = CorynRecordingListener { sessionId ->
// Attach sessionId to your crash reporter or analytics.
}
}
import java.util.Collections;
import ai.coryn.replay.api.core.main.Coryn;
import ai.coryn.replay.api.core.model.configuration.CorynRecordingConfiguration;
import ai.coryn.replay.shared.uicapture.OverscrollStrategy;
CorynRecordingConfiguration configuration = CorynRecordingConfiguration.Builder()
.setUiCapturingEnabled(true)
.setOverscrollStrategy(new OverscrollStrategy.AdditionalPaddingPercent(5f))
.setMemoryLeakCodePackages(Collections.singleton("com.example.checkout"))
.setRecordingListener(sessionId -> {
// Attach sessionId to your crash reporter or analytics.
})
.build();
Coryn.startRecording(configuration);
Recording configuration
Set these options directly in Coryn.startRecording { }, or use CorynRecordingConfiguration.Builder():
| Kotlin option | Default | Meaning |
|---|---|---|
isUiCapturingEnabled | true | Capture the app's UI alongside the session timeline. |
listener | null | Receive the session ID when recording starts. |
overscrollStrategy | 5% directional padding | AdditionalPaddingPercent(5f) expands masks during overscroll and scrolling that may produce it. See Privacy Masking. |
memoryLeakCodePackages | Empty set | Add code packages for Fragment/ViewModel leak diagnostics. Inferred Application and manifest component packages remain included. See Built-in State Providers. |
If recording was deliberately delayed, pass a reason:
Coryn.startRecording(delayReason = "Waiting for user consent") {
isUiCapturingEnabled = true
}
This is an alternative to the earlier start call, not a second start request. If another condition delays the actual start further, the SDK reports that later delay reason.
Built-in Screen Text collection is active during recording even when isUiCapturingEnabled = false; that option disables visual snapshots. Mark sensitive text with the hiding APIs before exposing it.
For Compose, also configure privacy masking and overscroll tracking. For SurfaceView content, see SurfaceView Capture.
Next steps
-
API Requests — manual request Events and optional OkHttp integration
-
Recording Lifecycle — pause, resume, and stop behaviour
-
Privacy Masking — protect sensitive UI
-
Synchronisation — uploads, offline storage, and multiple processes