Android SDK guide for version 1.x

Learn how to use the Android version of our mobile SDK to quickly integrate our Payments product into your app.

If you're using a legacy version of the Android SDK - anything prior to version 2.0.0 - then this page guides you through how to set up and use the SDK in your app.

If you're using version 2.0.0 or above, please see the latest guide.

Before you begin

Before you can use the SDK, you have to:

  1. Create a payment using the Payments API v3.
  2. Register a redirect_uri from our developer console. Use at the end of the payment journey to redirect back to your website or application.

Step 1: Install the SDK

Before you add the SDK to our project, make sure that your build.gradle configuration is configured to support minSdk 24 or higher as well the packagingOptions below:

android {
    defaultConfig {
        applicationId "com.example.myapp"
        minSdk 24 // Sdk 24 or higher supported
    }


    packagingOptions {
        resources {
            pickFirsts += ['META-INF/LICENSE-MIT']
        }
    }
}

To add the SDK to your project, simply include TrueLayer Payments SDK to your dependencies.

// Add to your projects `build.gradle`.
implementation "com.truelayer.payments:ui:1.2.1"

Step 2: Initialise the SDK

To use the SDK, you have to first initialise it before invoking any other SDK method. The following code sample is an example of initialising the SDK:

import com.truelayer.payments.core.domain.configuration.Environment
import com.truelayer.payments.core.domain.configuration.HttpConnectionConfiguration
import com.truelayer.payments.core.domain.configuration.HttpLoggingLevel
import com.truelayer.payments.ui.TrueLayerUI

// Initialize the SDK with your application context.
TrueLayerUI.init(context = applicationContext) {
    // optionally choose which environment you want to use: PRODUCTION or SANDBOX
    environment = Environment.PRODUCTION
    // Make your own custom http configuration, stating custom timeout and http request logging level
    httpConnection = HttpConnectionConfiguration(
        timeoutMs = 5000,
        httpDebugLoggingLevel = HttpLoggingLevel.None
    )
}

Step 3: Process a payment

Depending on your preferred approach, you can choose to integrate the SDK into your payment process with either AndroidX Activity, with the older Android Activity or with Jetpack Compose.

In both cases, you'll need the paymentId and the resourceToken obtained from the backend. The fields mentioned earlier will be passed to the SDK via PaymentContext. There is little more to know about this object. The following kdoc explains all available parameters:

/**
 * Payment context to identify payment to be processed
 *
 * @property paymentId payment identifier obtained from create payment API
 * @property resourceToken resource token obtained from create payment API
 * @property redirectUri uri that will be invoked once payment authorization is completed
 * @property preferences object containing various preferences that allow to override default SDK
 *                     behaviour in certain aspects.
 */
data class PaymentContext(
    val paymentId: String,
    val resourceToken: String,
    val redirectUri: String,
    val preferences: Preferences? = null
)

/**
 * Preferences class that allows to set preferences and override default SDK behaviour
 * in certain aspects.
 *
 * @property preferredCountryCode (optional) in case there are available payment providers from
 *               multiple countries the SDK will try select most appropriate one automatically.
 *               You may want to override that behaviour.
 *               By setting the preferredCountryCode (ISO 3166-1 alpha-2, example: "GB" or "FR"),
 *               the SDK will try first to select preferred country before falling back to the
 *               auto selection.
 */
data class Preferences(
    val preferredCountryCode: String? = null
) : Parcelable

Option 1: Process a payment with an AndroidX Activity integration

import android.widget.Toast
import com.truelayer.payments.ui.models.PaymentContext
import com.truelayer.payments.ui.screens.coordinator.FlowCoordinatorActivityContract
import com.truelayer.payments.ui.screens.coordinator.FlowCoordinatorResult

// Register for the end result.
val contract = FlowCoordinatorActivityContract()
val flowResult = registerForActivityResult(contract) {
    val text = when (it) {
        is FlowCoordinatorResult.Failure -> {
            "Failure ${it.reason}"
        }
        is FlowCoordinatorResult.Successful -> {
            "Successful ${it.step}"
        }
    }
    // present the final result
    Toast.makeText(this, text, Toast.LENGTH_LONG).show()
}

// Obtain your payment context from your backend
val paymentContext = PaymentContext(
    paymentId =  "your-payment-identifier",
    paymentToken = "payment-resource-token",
    redirectUri = "redirect-uri-that-will-be-invoked-when-coming-back-from-bank"
)

// 🚀 Launch the payment flow.
flowResult.launch(paymentContext)

Option 2: Process a payment with an Android Activity integration

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import com.truelayer.payments.core.domain.configuration.Environment
import com.truelayer.payments.ui.TrueLayerUI
import com.truelayer.payments.ui.models.PaymentContext
import com.truelayer.payments.ui.screens.coordinator.FlowCoordinatorActivityContract
import com.truelayer.payments.ui.screens.coordinator.FlowCoordinatorResult

class ActivityIntegration : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Initialise the payments configuration
        TrueLayerUI.init(context = applicationContext) {
            environment = Environment.PRODUCTION
            httpConnection = HttpConnectionConfiguration(
                timeoutMs = 5000,
                httpDebugLoggingLevel = HttpLoggingLevel.None
            )
        }
        
        // Obtain your payment context from your backend
        val paymentContext = PaymentContext(
            paymentId =  "your-payment-identifier",
            paymentToken = "payment-resource-token",
            redirectUri = "redirect-uri-that-will-be-invoked-when-coming-back-from-bank"
        )
        // Create an intent to launch the SDK
        val intent = FlowCoordinatorActivityContract().createIntent(this, paymentContext)
        // Launch the SDK
        startActivityForResult(intent, 0)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        // Act on the SDK result
        val text = when (val result = FlowCoordinatorResult.unwrapResult(data)) {
            is FlowCoordinatorResult.Failure -> "Failure ${result.reason}"
            is FlowCoordinatorResult.Successful -> "Successful ${result.step}"
            null -> "Activity result failed."
        }
        Toast.makeText(this, text, Toast.LENGTH_LONG).show()
    }
}

Option 3: Process a payment with a Jetpack Compose integration

You have to make sure that you have setDecorFitsSystemWindows(window, false) and window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) set for the Activity that will be hosting SDK Compose code. The following example shows how to process a payment with a Jetpack Compose integration:

// place the following code in your `onCreate` method of the activity hosting compose code
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // The following lines are required for the accompanist-ui-insets
    // to work properly
    WindowCompat.setDecorFitsSystemWindows(window, false)
    @Suppress("DEPRECATION")
    window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)

}

// Your payments custom theme or use the provided defaults as below
val theme = TrueLayerTheme(
    lightPalette = LightColorDefaults,
    darkPalette = DarkColorDefaults,
    typography = TypographyDefaults
)

// Obtain your payment context from your backend
val paymentContext = PaymentContext(
    paymentId =  "your-payment-identifier",
    paymentToken = "payment-resource-token",
    redirectUri = "redirect-uri-that-will-be-invoked-when-coming-back-from-bank"
)

setContent {
    Theme(
        theme = theme
    ) {
        FlowCoordinator(
            paymentContext = paymentContext,
            onSuccess = { successStep ->
                // action on success
            },
            onFailure = { failureReason ->
                // action on failure
            },
        )
    }
}

Customise colours

Currently, colour customisation is only available when integrating via Jetpack Compose. To change colours or typography, you have to provide your own version of LightColorDefaults, DarkColorDefaults, TypographyDefaults. You can use .copy() to override just a single colour. For example:

TrueLayerTheme(
    lightPalette = LightColorDefaults.copy(primary = Color.Red),
    darkPalette = DarkColorDefaults.copy(primary = Color.DarkGray),
    typography = TypographyDefaults
)

To find a full list of colours you can override, you can check out the details of androidx.compose.material3.ColorScheme in the Android reference documentation.