Android

The Android SDK wraps the Lean Link SDK in an Activity-based WebView, exposed via a fluent Lean.Builder() API and a Lean.Listener callback interface.

šŸ“˜

Prerequisites

Before calling any SDK method you need to have completed the backend setup in the Getting Started section:

This page covers only the client-side SDK integration.

Installation

Add JitPack to your project's build.gradle:

repositories {
    maven { url 'https://jitpack.io' }
}

Add the dependency in your module's build.gradle:

dependencies {
    implementation "me.leantech:link-sdk-android:X.X.X"
}

The latest version is on JitPack.

Demo app

See lean-android-test-app.

Setup

Instantiate Lean once via the Builder:

val lean = Lean.Builder()
    .setAppToken("<YOUR_APP_TOKEN>")
    .setVersion("latest")
    .setCountry("ae")     // or "sa"
    .setLanguage("en")    // or "ar"
    .setSandboxMode()     // remove for production
    .showLogs()           // development only
    .build()

Listener pattern

Every method requires a Lean.Listener that receives a Lean.Response on completion, cancellation, or error.

lean.connect(
    activity = this,
    customerId = "CUSTOMER_ID",
    // ... other fields
    leanListener = object : Lean.Listener {
        override fun onResponse(response: Lean.Response) {
            when (response.status) {
                "SUCCESS"   -> { /* flow completed */ }
                "CANCELLED" -> { /* user cancelled */ }
                "ERROR"     -> { /* inspect response.message, response.secondaryStatus */ }
            }
        }
    }
)

See LinkSDK statuses for the full list of status codes.

šŸ“˜

Legacy listener interface

The older LeanListener interface with onSuccess() / onFailure() callbacks is deprecated. Use Lean.Listener with onResponse(response) as shown above.

Available methods

All methods accept camelCase parameters (e.g. customerId, paymentDestinationId). Every call takes an activity reference as its first argument — the LeanActivity launches over it — and a Lean.Listener that receives the Lean.Response on completion.

.connect()

Link a bank account for data access (and optionally payments).

Required: activity, customerId, permissions.

lean.connect(
    activity = this,
    customerId = "CUSTOMER_ID",
    bankIdentifier = null,
    paymentDestinationId = "PAYMENT_DESTINATION_ID",
    permissions = arrayListOf(
        Lean.UserPermissions.IDENTITY,
        Lean.UserPermissions.ACCOUNTS,
        Lean.UserPermissions.TRANSACTIONS,
        Lean.UserPermissions.BALANCE,
        Lean.UserPermissions.PAYMENTS
    ),
    customization = null,
    accessTo = null,
    accessFrom = null,
    failRedirectUrl = null,
    successRedirectUrl = null,
    accountType = null,
    endUserId = null,
    accessToken = null,
    showConsentExplanation = null,
    destinationAlias = null,
    destinationAvatar = null,
    customerMetadata = null,
    leanListener = /* ... */
)

.pay()

Initiate a bank-to-bank payment.

Required: activity, exactly one of paymentIntentId or bulkPaymentIntentId.

lean.pay(
    activity = this,
    paymentIntentId = "PAYMENT_INTENT_ID",
    bulkPaymentIntentId = null,
    accountId = null,
    bankIdentifier = null,
    showBalances = false,
    customization = null,
    failRedirectUrl = null,
    successRedirectUrl = null,
    endUserId = null,
    accessToken = null,
    destinationAlias = null,
    destinationAvatar = null,
    riskDetails = null,
    leanListener = /* ... */
)

.reconnect()

Restore a broken bank connection.

Required: activity, reconnectId.

lean.reconnect(
    activity = this,
    reconnectId = "RECONNECT_ID",
    customization = null,
    accessToken = null,
    destinationAlias = null,
    destinationAvatar = null,
    leanListener = /* ... */
)

.createBeneficiary()

Add a beneficiary to an existing payment source. On Android this is the current non-deprecated name for this flow.

Required: activity, customerId, paymentDestinationId, and one of paymentSourceId or entityId.

šŸ“˜

Naming note

On the web SDK v2 the primary name is updatePaymentSource and createBeneficiary is the deprecated alias. On Android it's reversed — createBeneficiary is primary and updatePaymentSource is marked @Deprecated. Both names call the same underlying flow. Naming parity is planned for a future release.

lean.createBeneficiary(
    activity = this,
    customerId = "CUSTOMER_ID",
    paymentSourceId = "PAYMENT_SOURCE_ID",
    paymentDestinationId = "PAYMENT_DESTINATION_ID",
    customization = null,
    failRedirectUrl = null,
    successRedirectUrl = null,
    accessToken = null,
    entityId = null,
    destinationAlias = null,
    destinationAvatar = null,
    leanListener = /* ... */
)

.checkout()

Open Finance guest payment — the customer authenticates at the bank and is redirected back to your successRedirectUrl / failRedirectUrl with status query parameters you feed into captureRedirect.

Required: activity, paymentIntentId, successRedirectUrl, failRedirectUrl.

lean.checkout(
    activity = this,
    paymentIntentId = "PAYMENT_INTENT_ID",
    customerName = null,
    bankIdentifier = null,
    accessToken = null,
    successRedirectUrl = "https://yourapp.com/payment-success",
    failRedirectUrl = "https://yourapp.com/payment-failure",
    customization = null,
    riskDetails = null,
    leanListener = /* ... */
)

.authorizeConsent()

Grant a long-lived Open Finance consent. Redirects to the bank and returns to your successRedirectUrl / failRedirectUrl.

Required: activity, customerId, consentId, successRedirectUrl, failRedirectUrl.

lean.authorizeConsent(
    activity = this,
    customerId = "CUSTOMER_ID",
    consentId = "CONSENT_ID",
    failRedirectUrl = "https://yourapp.com/consent-failure",
    successRedirectUrl = "https://yourapp.com/consent-success",
    customization = null,
    accessToken = null,
    destinationAlias = null,
    destinationAvatar = null,
    riskDetails = null,
    leanListener = /* ... */
)

.manageConsents()

Show a customer-facing consent management screen.

Required: activity, customerId.

lean.manageConsents(
    activity = this,
    customerId = "CUSTOMER_ID",
    accessToken = null,
    customization = null,
    leanListener = /* ... */
)

.captureRedirect()

Show the outcome screen after an Open Finance redirect. Extract the status query parameters Lean appends to your redirect URL (consentAttemptId, granularStatusCode, statusAdditionalInfo) and pass them in.

Required: activity, customerId.

lean.captureRedirect(
    activity = this,
    customerId = "<from_query_param>",
    accessToken = "<customer_scoped_access_token>",
    consentAttemptId = "<from_query_param>",
    granularStatusCode = "<from_query_param>",
    statusAdditionalInfo = "<from_query_param>",
    customization = null,
    leanListener = /* ... */
)

.verifyAddress()

Proof-of-address check.

Required: activity, customerId, customerName, permissions (typically arrayListOf(Lean.UserPermissions.IDENTITY)).

lean.verifyAddress(
    activity = this,
    customerId = "CUSTOMER_ID",
    customerName = "Jane Doe",
    permissions = arrayListOf(Lean.UserPermissions.IDENTITY),
    customization = null,
    accessToken = null,
    destinationAlias = null,
    destinationAvatar = null,
    leanListener = /* ... */
)

Deprecated methods

The following methods are marked @Deprecated in the Android SDK. They still work but will be removed in a future release.

.updatePaymentSource()

āš ļø

Deprecated on Android — use createBeneficiary(). Web SDK v2 uses the opposite naming convention; see the note on createBeneficiary above.

lean.updatePaymentSource(
    activity = this,
    customerId = "CUSTOMER_ID",
    paymentSourceId = "PAYMENT_SOURCE_ID",
    paymentDestinationId = "PAYMENT_DESTINATION_ID",
    customization = null,
    failRedirectUrl = null,
    successRedirectUrl = null,
    endUserId = null,
    accessToken = null,
    entityId = null,
    destinationAlias = null,
    destinationAvatar = null,
    leanListener = /* ... */
)

.createPaymentSource()

āš ļø

Deprecated — use connect() with permissions = arrayListOf(Lean.UserPermissions.PAYMENTS) instead.

Customisation

Construct a Lean.Customization and pass it on any method. Every field maps to the same key documented in Customisation (camelCase on Android).

val customization = Lean.Customization().apply {
    themeColor = "#0080ff"
    buttonTextColor = "#ffffff"
    linkColor = "#0080ff"
    overlayColor = "rgba(0, 0, 0, 0.8)"
    buttonBorderRadius = "8"
    dialogMode = "contained"

    // Dark-mode overrides
    themeColorDark = "#1a1a1a"
    buttonTextColorDark = "#ffffff"
}

lean.connect(
    activity = this,
    customerId = "CUSTOMER_ID",
    bankIdentifier = null,
    paymentDestinationId = "PAYMENT_DESTINATION_ID",
    permissions = arrayListOf(Lean.UserPermissions.IDENTITY, Lean.UserPermissions.ACCOUNTS),
    customization = customization,
    accessTo = null,
    accessFrom = null,
    failRedirectUrl = null,
    successRedirectUrl = null,
    accountType = null,
    endUserId = null,
    accessToken = null,
    showConsentExplanation = null,
    destinationAlias = null,
    destinationAvatar = null,
    customerMetadata = null,
    leanListener = /* ... */
)

Language

Pass "en" or "ar" to setLanguage(...) on the Builder. Arabic switches the UI to a full right-to-left layout.

Bank-list and account-selection shortcuts

Pass bankIdentifier to skip the bank-selection screen (Lean bank identifier — see Create your own bank list). Pass accountId on pay to skip the payment-source-selection screen.

Related