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.
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
dependencies {
implementation("io.seatlayer:seatlayer-android:0.3.5")
implementation("io.seatlayer:seatlayer-android-compose:0.3.5")
}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
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:
<io.seatlayer.android.compose.SeatLayerPickerView
android:id="@+id/picker"
android:layout_width="match_parent"
android:layout_height="match_parent" />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:
SeatLayerConfiguration(
event = "ev_private",
buyerAccessTokenProvider = BuyerAccessTokenProvider { context ->
buyerBackend.mintSeatLayerAccess(context.reason)
},
)Mint the native buyer-access session on your backend through 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.
Checkout and hold ownership
The app selects and temporarily holds inventory. The trusted backend inspects and books after payment or order validation.
onCheckoutreceives oneSeatLayerPickerCheckoutHandoff.- Send only its opaque
holdIdplus normal order context to your backend. - Inspect authoritative hold items and calculate the payable total there.
- Charge through your payment provider.
- Reuse the same
bookingReffor 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 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:
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
git clone --branch v0.3.5 --depth 1 https://github.com/seatlayer/seatlayer-android.git
cd seatlayer-android
./gradlew validate
./gradlew :sample:installDebugThe 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.