---
title: "Android SDK"
description: "Install the aligned SeatLayer Android 0.3.5 core and Compose artifacts for a ready-made picker, branded flow, custom Compose/View layout, or raw map."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.seatlayer.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Android SDK

SeatLayer Android `0.3.5` ships the complete adaptive native picker on Maven
Central. Jetpack Compose supplies the ready-made tree and public components;
View/XML applications can host the same tree or use the headless
state/controller. The preserved `SeatLayerView` remains available for raw-map
integrations.

> **Two aligned Maven artifacts**
>
> Use `0.3.5` for both `seatlayer-android` and
> `seatlayer-android-compose`. Core contains the raw map plus headless state,
> controller, and map View. Compose contains the complete
> picker, themes, strings, styles, builders, native components, and View/XML
> host. Never mix their versions.

## Requirements

- Android API 24+ and compile SDK 36
- JDK 17 for local builds
- AndroidX
- `android:enableOnBackInvokedCallback="true"` when predictive Back is required
  on an activity targeting Android 15 or lower

## Install

```kotlin title="app/build.gradle.kts"
dependencies {
    implementation("io.seatlayer:seatlayer-android:0.3.5")
    implementation("io.seatlayer:seatlayer-android-compose:0.3.5")
}
```

```kotlin title="settings.gradle.kts"
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }
}
```

Raw-only applications can omit `seatlayer-android-compose`. Maven Central is
the permanent release channel; do not use old JitPack coordinates or a moving
snapshot.

## Ready-made Compose picker

```kotlin title="CheckoutActivity.kt"
class CheckoutActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            SeatLayerPicker(
                configuration = SeatLayerConfiguration(
                    event = "<YOUR_EVENT_KEY>",
                    publicKey = "<YOUR_PUBLIC_KEY>",
                    currency = "USD",
                    maxSelection = 6,
                ),
                modifier = Modifier.fillMaxSize(),
                onCheckout = { handoff ->
                    checkoutBackend.start(holdId = handoff.holdId)
                },
                onError = ::reportPickerError,
                onClose = ::finish,
            )
        }
    }
}
```

The default tree covers adaptive compact/wide layouts, native header and
legend, floors and sections, accessibility filters, confirmation and tiers,
GA/table quantities, dense cart, temporary holds and lapse recovery, checkout,
3D and panorama chrome, 37 locale dictionaries, lifecycle reconciliation, and
Android predictive Back.

Give the picker a definite size and keep the venue map outside a scrolling or
gesture-competing parent.

## View and XML applications

Use `SeatLayerPickerView` to host the same ready-made Compose tree in an
existing View screen:

```xml
<io.seatlayer.android.compose.SeatLayerPickerView
    android:id="@+id/picker"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
```

```kotlin
binding.picker.bind(
    lifecycleOwner = this,
    configuration = configuration,
    onCheckout = ::openCheckout,
    onReady = ::observeReady,
    onSnapshot = ::observeSnapshot,
    onClose = ::finish,
)
```

For a completely custom View hierarchy, bind a
`SeatLayerPickerStateHolder` to one `SeatLayerPickerMapView`, collect its
immutable `state`, and invoke the typed `controller`.

## Public and private inventory

The examples use a publishable key for Public inventory. For login-gated,
presale, partner, channel, or other private inventory, omit `publicKey` and use
the renewable in-memory provider:

```kotlin
SeatLayerConfiguration(
    event = "ev_private",
    buyerAccessTokenProvider = BuyerAccessTokenProvider { context ->
        buyerBackend.mintSeatLayerAccess(context.reason)
    },
)
```

Mint the native buyer-access session on your backend through
[buyer access sessions](/server-api/buyer-access-sessions), return only its
short-lived token to the provider, and treat SDK access details as opaque.
Never ship a SeatLayer secret in the APK, configuration, logs, or analytics.

## Choose an integration path

| Path | API | Your application owns |
| --- | --- | --- |
| Ready Compose | `SeatLayerPicker` | Configuration, callbacks, destination |
| Branded Compose | Theme, strings, options, styles, builders | Brand and selected complete parts |
| Custom Compose | `SeatLayerPickerScope` + public composables | Entire Compose hierarchy |
| Ready View/XML | `SeatLayerPickerView` | Existing View screen and dismissal |
| Custom Views | `SeatLayerPickerStateHolder` + `SeatLayerPickerMapView` | Entire View hierarchy |
| Raw map | `SeatLayerView` | Every buyer surface and hold transition |

Every native-picker path keeps one picker state, ordered actions,
supported-feature checks, hold ownership, foreground recovery, and the same
typed checkout handoff.

[Explore customization, headless state, and public components](/buyer-sdk/android/native-picker).

## Checkout and hold ownership

The app selects and temporarily holds inventory. The trusted backend inspects
and books after payment or order validation.

1. `onCheckout` receives one `SeatLayerPickerCheckoutHandoff`.
2. Send only its opaque `holdId` plus normal order context to your backend.
3. Inspect authoritative hold items and calculate the payable total there.
4. Charge through your payment provider.
5. Reuse the same `bookingRef` for idempotent retries.

Ordinary picker state includes hold status, expiry, and owner, not `holdId`.
Successful handoff transfers ownership to the host. Closing before handoff may
release picker-owned inventory; closing afterwards must preserve the host-owned
hold. A rejected callback rejects only that exact handoff and restores a
recoverable picker state.

Read [holds and secure checkout](/buyer-sdk/holds-and-checkout) before wiring
payment.

## Application and SDK ownership

| Native Android owns | SeatLayer SDK owns |
| --- | --- |
| Header, legend, floors/sections, filters, confirmation, tiers/quantities, cart, holds, checkout, loading/errors, Test Mode, attribution, adaptive layout, TalkBack, haptics and Back | Seats, labels, geometry, hit testing, pan/pinch, camera, authored 3D, and panorama pixels |
| Compose/View hierarchy, 48dp targets, safe areas, lifecycle and window behavior | Authoritative inventory state and supported map capabilities |

The SDK presents one confirmation, cart, Test Mode indicator, and checkout
action around the venue surface.

## Lifecycle, Back, and recovery

The ready picker installs lifecycle, haptic, and Back behavior. Foreground or
return from checkout refreshes availability when supported, reconciles server
hold truth, reports lost inventory, and presents one hold-lapse recovery state.

Hardware and predictive Back consume one semantic layer at a time: quantity
prompt → expanded cart → panorama → venue 3D → seat confirmation → focused
section → host close. Custom Compose hosts install
`SeatLayerPickerLifecycle`, `SeatLayerPickerBackHandler`, and
`SeatLayerPickerHapticEffects`, or provide equivalent behavior around the same
controller.

Recomposition and configuration-handled resize retain picker state. Activity
or process recreation creates new state; restore a host-owned hold with
`initialHoldId` and the same renewable access provider, then let SeatLayer
authoritatively resume it.

## Optional picker prewarm

`SeatLayerPickerPrewarmer.prewarm()` is an optional API that prepares the
picker before navigation:

```kotlin
lifecycleScope.launch {
    val result = SeatLayerPickerPrewarmer.prewarm(applicationContext)
    check(result.engineStarted)
}
```

Prewarm receives no Activity, event key, public key, buyer token, or hold. It
never starts a buyer session.

## Test Mode and attribution

Test Mode follows authoritative event state. Required `Powered by SeatLayer`
attribution appears at the safe bottom-right edge according to the SeatLayer
account configuration. Client-side options, builders, and styles cannot
override either truth signal.

## Run the tagged sample

```bash
git clone --branch v0.3.5 --depth 1 https://github.com/seatlayer/seatlayer-android.git
cd seatlayer-android
./gradlew validate
./gradlew :sample:installDebug
```

The sample covers ready/branded/custom Compose, ready/custom View, and raw-map
paths. Validate API 24+, TalkBack, large
text, RTL, rotation, split-screen, process restoration, foreground recovery,
tiers, GA/tables, 3D/panorama, checkout rejection, Test Mode, and attribution
on physical devices before rollout.

## Product scope

Android `0.3.5` accepts one published Event per picker. Native Performance
Group and Season configuration is not part of this release.

## Next steps

- [Compose, View/XML, and headless customization](/buyer-sdk/android/native-picker)
- [Raw-map API](/buyer-sdk/android/raw-map)
- [Compare all four native SDKs](/buyer-sdk/mobile)
- [Secure checkout](/buyer-sdk/holds-and-checkout)
- [Troubleshooting matrix](/buyer-sdk/mobile#troubleshooting)
- [`v0.3.5` source](https://github.com/seatlayer/seatlayer-android/tree/v0.3.5)
- [Tagged native-picker guide](https://github.com/seatlayer/seatlayer-android/blob/v0.3.5/docs/native-picker.md)
- [Tagged sample](https://github.com/seatlayer/seatlayer-android/tree/v0.3.5/sample)
- [Tagged migration guide](https://github.com/seatlayer/seatlayer-android/blob/v0.3.5/docs/migration-0.3.md)
- [Tagged changelog](https://github.com/seatlayer/seatlayer-android/blob/v0.3.5/CHANGELOG.md)

Source: https://docs.seatlayer.io/buyer-sdk/android/index.mdx
