> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://amer.developers.trustly.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://amer.developers.trustly.com/_mcp/server.

# Android

The Trustly Lightbox SDK for Android allows you to quickly build a bank authorization workflow in your Android app. Integrate the Select Bank Widget or the Trustly Lightbox to retrieve bank authorization data that can be used with other Trustly APIs.

To use an example project for testing and learning, see the [Android Example](https://github.com/TrustlyInc/trustly-android-example) in GitHub.

If you need help with your integration, contact your Trustly representative or send your request to <a href="mailto:us.integrations@trustly.com">[us.integrations@trustly.com](mailto:us.integrations@trustly.com)</a>.

`PayWithMyBank` references are deprecated. If your app is using `PayWithMyBank`, you must change it to `Trustly`.

## Prerequisites

* [Android 5.0 (API level 21)](https://developer.android.com/tools/releases/platforms#5.0) or later
* [AndroidX](https://developer.android.com/jetpack/androidx/)
* [Gradle 8](https://docs.gradle.org/8.0/release-notes.html) or later

**Android 15:** Edge-to-edge display mode is the default behavior for Android 15 (API level 35) and later. If your app wasn’t designed for edge-to-edge display mode, critical elements of your app can be obscured. To ensure your app remains functional, you may need to use [Window Insets](https://developer.android.com/develop/ui/views/layout/insets) to apply padding or margins to your layouts.

## Authentication flow

The following diagram illustrates how the Trustly SDK manages the secure transition between your application, the SDK, and the banking institution.

```mermaid
sequenceDiagram
    participant User
    participant App
    participant SDK as Trustly SDK
    participant System as Android System / Bank

    User->>App: Start
    App->>SDK: Initialize
    SDK-->>System: Open Auth [A]
    
    Note right of System: Login
    
    System-->>App: Redirect [B]
    App->>SDK: Verify
    SDK-->>App: Callback [C]
    App-->>User: Success
```

| Step  | Description                                                                                                                                                                                                                                    |
| :---- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **A** | **Authentication launch**<br />The SDK launches a secure browser overlay (Chrome Custom Tabs) or performs a direct App-to-App switch if the user has the target bank app installed.                                                            |
| **B** | **Deep Link return**<br />The bank redirects the user back to your application using the App Link defined in `metadata.deepLinkUrl`. Android verifies the domain via Digital Asset Links and brings your `LightboxActivity` to the foreground. |
| **C** | **SDK resumption**<br />Your `onRestart` override calls `proceedToChooseAccount`, prompting the SDK to verify the transaction status and trigger the `onReturn` callback.                                                                      |

## Configure Gradle and Android dependencies

1. To add the Trustly SDK and the AndroidX Browser Library with [Chrome Custom Tabs](https://developer.chrome.com/docs/android/custom-tabs/integration-guide/) to your project, open your `build.gradle` file and add the following dependencies:

   ```groovy
   // build.gradle
   dependencies {
       implementation 'net.trustly:trustly-android-sdk:4.2.0'
       implementation 'androidx.browser:browser:1.8.0'
       implementation 'com.google.code.gson:gson:2.13.1'
       // ...
   }
   ```

2. Sync your project to enable the dependency changes.

3. If your app does not have internet permissions enabled, open the `AndroidManifest.xml` file and add the `INTERNET` permission:

   ```xml
   <uses-permission android:name="android.permission.INTERNET" />
   ```

4. Configure an App Link for your app. Pass your App Link URL in `metadata.deepLinkUrl` when building `establishData`. Without it, customers are not automatically returned to your app after authenticating with their bank. See [Set up App Links](#set-up-app-links) below.

## Define Establish Data with a Request Signature

To ensure communications between the Trustly Lightbox SDK and the Trustly API are secure, use a `requestSignature`. You must generate a signature on your server using your access key and pass it to the Android app before rendering the Select Bank Widget or Trustly Lightbox.

Create a helper object in a new file named `EstablishData.kt` to hold your configuration:

```kotlin
package com.myapp

object EstablishData {

    fun getEstablishDataValues(): Map<String, String> {
        val establishDataValues: MutableMap<String, String> = HashMap()
        establishDataValues["accessId"] = "YOUR_ACCESS_ID"
        establishDataValues["merchantId"] = "YOUR_MERCHANT_ID"
        establishDataValues["requestSignature"] = "GENERATED_HASH"
        establishDataValues["description"] = "transaction description"
        establishDataValues["merchantReference"] = "ABCDREF"
        establishDataValues["currency"] = "USD"
        establishDataValues["amount"] = "0.00"
        establishDataValues["paymentType"] = "Deferred"
        establishDataValues["metadata.deepLinkUrl"] = "intent://yourdomain.com#Intent;scheme=https;end"
        
        // establishDataValues["env"] = "sandbox"
        return establishDataValues
    }
}
```

When testing in the sandbox environment, set the `env` property to `sandbox`. You must remove the `env` property before publishing your production application.

To generate a `requestSignature`, see [Generate request signatures](/integrate/api-fundamentals/secure-requests-and-signature-validation/generate-request-signatures). For a full list of parameters, see [About OAuth authentication](/integrate/api-fundamentals/authentication-and-oauth).

## Display the Select Bank Widget

Trustly recommends rendering the Select Bank Widget for an optimal customer experience.

1. In your activity's layout XML (for example, `activity_main.xml`), add the `TrustlyView`:

   ```xml
   <androidx.constraintlayout.widget.ConstraintLayout>
       <net.trustly.android.sdk.views.TrustlyView
           android:id="@+id/trustlyWidgetView"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           app:layout_constraintEnd_toEndOf="parent"
           app:layout_constraintStart_toStartOf="parent"
           app:layout_constraintTop_toTopOf="parent" />

   </androidx.constraintlayout.widget.ConstraintLayout>
   ```

2. In your activity's `onCreate` method, initialize the widget and handle the bank selection event. Use `onBankSelected` to update your `establishData` with the customer's choice:

   ```kotlin
   // MainActivity.kt
   val establishData = EstablishData.getEstablishDataValues().toMutableMap()

   val trustlyWidget = findViewById<TrustlyView>(R.id.trustlyWidgetView)

   trustlyWidget.selectBankWidget(establishData).onBankSelected { callback, data ->
       establishData["paymentProviderId"] = data["paymentProviderId"].toString()
   }
   ```

## Launch the Lightbox

1. Add a button to your activity's layout XML (for example., `activity_main.xml`) to launch the payment flow:

   ```xml
   <androidx.appcompat.widget.AppCompatButton
       android:id="@+id/btnConnectWithMyBank"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="@string/connect_my_bank"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent" />
   ```

2. Configure the button listener to launch a new activity. For example, `LightboxActivity` and pass the `establishData`:

   ```kotlin
   // MainActivity.kt
   val connectTrustlyButton = findViewById<AppCompatButton>(R.id.btnConnectWithMyBank)

   connectTrustlyButton.setOnClickListener {
       val intent = Intent(this@MainActivity, LightboxActivity::class.java)
       intent.putExtra(LightboxActivity.ESTABLISH_DATA, establishData as Serializable)
       startActivity(intent)
   }
   ```

3. In your `LightboxActivity`, call `establish` to open the Lightbox:

   ```kotlin
   class LightboxActivity : AppCompatActivity() {

       private lateinit var lightboxView: TrustlyView
       
       companion object {
           const val ESTABLISH_DATA = "establish_data"
       }

       override fun onCreate(savedInstanceState: Bundle?) {
           super.onCreate(savedInstanceState)
           setContentView(R.layout.activity_light_box)

           val establishData = intent.getSerializableExtra(ESTABLISH_DATA) as Map<String, String>
           lightboxView = findViewById(R.id.lightBoxWidget)
           lightboxView.establish(establishData)
       }
   }
   ```

4. Optional. If your application doesn't specify a screen orientation, add the `android:configChanges` attribute to your `AndroidManifest.xml` to handle rotation gracefully. For example:

   ```xml
   <activity android:name=".LightboxActivity"
           android:configChanges="screenSize|orientation" />

   ```

   For more information about handling configuration changes in Android apps, see [Handle configuration changes](https://developer.android.com/guide/topics/resources/runtime-changes).

## Add callback functions

The Trustly Lightbox provides two callback functions to handle transaction results:

* **`onReturn`**: Called when the customer successfully authorizes the transaction.
* **`onCancel`**: Called if the customer exits the process or the authorization fails.

Chain these callbacks to the `establish` method to handle the transaction result.

In the following example, a `redirectToScreen` helper function is used to prompt the customer when their transaction is successfully or unsuccessfully authorized:

```kotlin
lightboxView.establish(establishData)
    .onReturn(
        TrustlyCallback { lightboxView: Trustly?, returnData: Map<String, String> ->
            // TODO: Handle success (for example, navigate to a success screen).
            // redirectToScreen(Callback.RETURN)
            Log.d("Trustly", "Transaction successful: $returnData")
        }
    ).onCancel(
        TrustlyCallback { lightboxView: Trustly?, cancelData: Map<String, String> ->
             // TODO: Handle cancellation (for example, show a toast or stay on current screen).
             // redirectToScreen(Callback.CANCEL)
             Log.d("Trustly", "Transaction cancelled")
        }
    )
```

Your application should retrieve data provided in the `onReturn` callback (such as the transaction ID) and pass it to your server for validation.

## Add an OAuth transition handler

To support the transition from an external OAuth login (such as a bank app) back to the Lightbox, add an `onRestart` override to your `LightboxActivity`. This ensures the Lightbox resumes correctly after the user returns to your app from a bank login.

```kotlin
// LightboxActivity.kt

override fun onRestart() {
    super.onRestart()

    lightboxView.proceedToChooseAccount()
}
```

## Set up App Links

If your app does not already have an App Link configured, you must set one up. Without it, users will not be automatically redirected to your app after logging in on a mobile banking app.

[Android App Links](https://developer.android.com/training/app-links) use standard HTTPS URLs to return users directly to your app after bank authentication. Pass your App Link URL as `metadata.deepLinkUrl` in `establishData`. Unlike custom URL schemes, App Links are verified against your domain via Digital Asset Links, preventing other apps from intercepting them, and fall back to your website if the app isn't installed.

#### Define the digital asset links

Create a JSON file named `assetlinks.json` and host it at: `https://yourdomain.com/.well-known/assetlinks.json`

Server requirements:

* Served over HTTPS.
* `Content-Type` header set to `application/json`.

```json
[
  {
    "relation": [
      "delegate_permission/common.handle_all_urls"
    ],
    "target": {
      "namespace": "android_app",
      "package_name": "com.yourcompany.yourapp",
      "sha256_cert_fingerprints": [
        "4A:34:B4:72:DE:F7:..."
      ]
    }
  }
]
```

| Key                        | Description                                                                                                                                       |
| :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |
| `relation`                 | Permissions being granted. Use `delegate_permission/common.handle_all_urls` for deep links.                                                       |
| `namespace`                | The namespace of your application. Typically `android_app`.                                                                                       |
| `package_name`             | The unique application ID defined in your `build.gradle` file.                                                                                    |
| `sha256_cert_fingerprints` | The SHA-256 fingerprint of your app's signing certificate. Retrieve it with `keytool` or via the **signingReport** Gradle task in Android Studio. |

Verify your server returns the correct `Content-Type`:

```bash
curl -I https://yourdomain.com/.well-known/assetlinks.json
```

#### Configure the manifest

Add an intent filter with `autoVerify="true"` to your `AndroidManifest.xml`. Android uses the following attributes to handle App Links:

* **`android:exported="true"`** — Required to allow your activity to be started by external app links.
* **`android:autoVerify="true"`** — Instructs Android to verify your domain ownership by checking `assetlinks.json` at install time.
* **`<data>` elements** — Define the HTTPS scheme, domain, and path that trigger your activity.

```xml
<!-- Overriding the SDK's default redirect activity allows you to handle the redirect in your own way. -->
<activity
    android:name="net.trustly.android.sdk.views.TrustlyRedirectActivity"
    android:exported="true">

    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="https" />
        <data android:host="yourdomain.com" />
        <data android:pathPrefix="/trustly-return" />
    </intent-filter>

</activity>
```

#### Handle incoming App Links

Update `onCreate` in your `LightboxActivity` to detect whether it was started by a normal launch or by an App Link. Also add `onNewIntent` so the same handler runs when the activity is already in the back stack. Add the following methods to your existing `LightboxActivity` class:

```kotlin
// LightboxActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_light_box)

    if (intent?.action == Intent.ACTION_VIEW) {
        // Launched from an App Link — handle the deep link instead of establish().
        handleIntent(intent)
    } else {
        // Normal launch — read establishData and open the Lightbox.
        val establishData = intent.getSerializableExtra(ESTABLISH_DATA) as Map<String, String>
        lightboxView = findViewById(R.id.lightBoxWidget)
        lightboxView.establish(establishData)
    }
}

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    handleIntent(intent)
    setIntent(intent)
}

private fun handleIntent(intent: Intent?) {
    if (intent?.action == Intent.ACTION_VIEW) {
        intent.data?.let { uri -> handleAppLink(uri) }
    }
}

private fun handleAppLink(uri: Uri) {
    val transactionId = uri.getQueryParameter("transactionId")
    // Route the user and resume the Lightbox as needed.
}
```

For apps that support both App Links and legacy custom URL schemes during a migration period, see [Migrate from custom schemes (Android)](/sdks/mobile/migrate-from-custom-schemes-android) for a unified router pattern that handles both link types through a single navigation flow.

#### Configure your deep link strategy (optional)

App Links function without a fallback. However, Trustly recommends having a default deep link strategy configured for your merchant account. This ensures your application has a consistent fallback behavior if a strategy isn't explicitly provided within the `metadata.deepLinkUrl` object in your code.

Any settings passed to the `establishData` object in your code override the default configurations stored in your Trustly account profile.

Because this setup requires internal configuration, you'll need to contact your Customer Success Manager (CSM) or [Trustly Support](mailto:us.support@trustly.com) to enable this fallback for your account.

When you submit your request, you must provide the following information:

* **Deep link strategy**: Specify `deeplink-url`.
* **App Link**: Provide your fully qualified domain (for example, `https://yourdomain.com/`).