Skip to main content

Installation

Prerequisites​

Before integrating the Flex Checkout Android SDK, ensure your project meets the following requirements:

  • Android API level 26+ (Android 8.0 Oreo)
  • Kotlin 1.9+ or Java 17
  • Java 17 target compatibility
  • Your Activity extends FragmentActivity or AppCompatActivity
info

The SDK is written in Kotlin and exposes a Java-friendly API surface (@JvmStatic, @JvmOverloads, SAM listener interfaces, and a CheckoutConfig.Builder). Both languages are first-class consumers — examples below show both.


Gradle Dependency​

Add JitPack to your project's settings.gradle.kts:

Kotlin
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}

Then add the Flex Checkout Android SDK to your app's build.gradle.kts:

Kotlin
dependencies {
implementation("com.github.flexapp:flex-checkout-android:1.7.0")
}

Initializing the SDK​

Initialize the Flex SDK by calling Flex.initialize() with a Context and a FlexConfig object. The SDK is a singleton — call initialize() once at app startup, then access the instance anywhere with Flex.instance (Kotlin) or Flex.getInstance() (Java).

The recommended place to initialize is your Application class, which is created once for the lifetime of the app:

import android.app.Application
import com.flex.checkout.Flex
import com.flex.checkout.configuration.FlexConfig
import com.flex.checkout.types.FlexEnvironment

class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Flex.initialize(this, FlexConfig(
clientId = "your-flex-client-id",
environment = FlexEnvironment.INT // use FlexEnvironment.PROD for production
))
}
}

Register it in your AndroidManifest.xml:

XML
<application
android:name=".MyApplication"
...>

Then access the SDK instance from any Activity:

val sdk = Flex.instance
warning

Flex.instance / Flex.getInstance() will throw if accessed before initialize() has been called.

warning

Flex.initialize() will throw FlexError.MissingClientId immediately if clientId is empty. Ensure your clientId is set before calling initialize().

FlexConfig Fields​

ParameterTypeDescription
clientIdStringRequired The client id provided by Flex which identifies your Flex client.
environmentFlexEnvironmentThe environment to use — either FlexEnvironment.INT (testing) or FlexEnvironment.PROD (production). Defaults to FlexEnvironment.INT.
developerFlexDeveloperConfig?Developer tool configuration options. Only takes effect in non-production environments.

Developer Tools​

The optional developer field can be configured to enable verbose logging for debugging.

Flex.initialize(this, FlexConfig(
clientId = "your-flex-client-id",
developer = FlexDeveloperConfig(logs = true)
))

Developer Fields​

Fields for the developer object.

ParameterTypeDescription
logsBooleanDisplays informative logs for debugging the Flex Android SDK in your Logcat output.

Environments​

There are only two environments for you to use:

EnvironmentUse it forDescription
FlexEnvironment.INTTestingIntegration / sandbox environment. Use it for all development and testing.
FlexEnvironment.PRODProductionProduction environment. Use it only for live, production traffic.

Token​

loadToken registers a token provider that the SDK calls to fetch a token from your backend. Kotlin uses a suspend lambda; Java uses the callback-based FlexTokenProvider interface.

sdk.loadToken {
val response = yourApi.getFlexToken()
response.token
}

The Java overload accepts a FlexTokenProvider (a SAM interface), which delivers the token (or error) via the FlexTokenCallback passed in. Invoke exactly one of onTokenReceived or onError per call.

warning

loadToken must be called before checkout can be opened. The SDK will throw a FlexError.NoTokenLoader error if no token provider has been registered.


Lifecycle Management​

User state (form input, scroll position, partial flow progress) is preserved across opens — if a user starts onboarding, closes the sheet, and reopens, they resume right where they left off.

If Android kills your app process (low memory, OS housekeeping), nothing special needs to happen on your side. Your Application.onCreate() runs again the next time the app launches, which re-runs Flex.initialize() and rebuilds the SDK from a clean state. Partners do not need to special-case process death — preserved user state is intentionally tied to the SDK's lifetime and a fresh process is a fresh start.

Cleanup​

Call cleanup only when the user signs out of your app. The SDK's WebView retains the previous user's in-flight UI state (form input, partial flow, cached client-side data), so if the next user signs in without cleanup, they would land into the previous user's session inside the WebView. Calling cleanup on sign-out wipes that state.

fun signOut() {
Flex.instance.cleanup()
// ...your sign-out logic
}

After cleanup, the SDK rebuilds itself the next time the user opens checkout — you do not need to call Flex.initialize again.

warning

Do not call cleanup from onStop(), onPause(), onDestroy(), or whenever the user navigates away from your checkout screen. Doing that loses the user's in-progress checkout state every time they re-enter — they'd have to restart onboarding from the beginning.

For most apps the sign-out hook is the only place cleanup is needed.


Analytics​

logImpression(data)​

Logs an impression event when the Flex checkout entry point (button, screen, etc.) becomes visible to the user. Call this from onResume() or whenever the checkout entry point appears on screen.

Flex.instance.logImpression(mapOf(
"residentId" to "xyz",
"propertyId" to "prop-12345",
"placement" to "homepage",
"element" to "split_rent_button",
))

Recommended fields for impression data:

ParameterTypeDescription
residentIdStringid associated with the resident.
propertyIdStringid associated with the property.
placement"homepage"
"payments"
"checkout"
Where the user interaction takes place in your portal.
element"split_rent_button"
"learn_more"
"awareness_banner"
Element displayed for the interaction.

ProGuard / R8​

The SDK ships with consumer ProGuard rules that are automatically applied to your release build. No additional configuration is required.

If you encounter issues with minification, ensure the SDK's consumer rules are being picked up by checking your merged ProGuard configuration.


Error Reference​

Setup​

Flex.initialize throws FlexError.MissingClientId if clientId is blank. There are no other setup-time errors; everything else surfaces via onError at runtime.

Runtime (onError messages)​

The onError checkout callback receives a descriptive String whenever something goes wrong. For load failures, the SDK already displays its own retry UI inside the sheet (see Checkout → Error Handling) — these messages are for your logging and analytics.

MessageWhen it occurs
"No token loader provided. Call loadToken() before opening checkout."openCheckout invoked before loadToken was registered
"FlexCheckout not configured — call Flex.initialize first."openCheckout invoked before Flex.initialize
"Flex checkout host not ready. Try again momentarily."openCheckout invoked at app launch before the SDK's host has attached
"Checkout is temporarily unavailable. Please try again later."Flex kill-switch is active for your client
"Checkout failed to load: <reason>"WebView load, JS handshake, or token loader failed — SDK shows its own retry UI in the sheet

For "Checkout failed to load: <reason>", the <reason> suffix is one of:

  • "The Internet connection appears to be offline." — no network
  • "Checkout did not load in time" — 15-second JS handshake timeout
  • "Failed to load token: <your loader's error>" — your loadToken lambda threw
  • "Token loader returned an empty token" — your loadToken lambda returned ""
sdk.checkout(CheckoutConfig(
onError = { error ->
// Log + report — the SDK already shows the user-facing error UI.
analytics.track("flex_checkout_error", mapOf("message" to error))
}
))

Next Steps​

Now that the SDK is installed and configured: