> For a complete page index, fetch https://docs.transak.com/llms.txt

# Android

The Transak Android integration allows you to embed a fully functional interface directly into your native Android application using Webview.

> **Error**
>
> Google Pay is not supported with Android webview integration.

> **Do not override the WebView user agent**
>
> Transak uses the default `User-Agent` to detect that the widget is running inside a native WebView, which determines the payment methods we offer. Replacing it strips those identifiers, so users may be shown methods that cannot complete in a WebView and our support team loses the signal needed to diagnose failures.
>
> Keep the default `User-Agent` unchanged. If you need to identify your app, use your platform's append-only option

#### Add Permissions in Manifest File

Update your `AndroidManifest.xml` to include required permissions for internet access and camera (for KYC verification):

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

#### Implement WebView in Activity

Configure your MainActivity to load the Transak widget URL using your preferred implementation:

**`Compose`**

```kotlin title="Compose"
import android.webkit.PermissionRequest
import android.webkit.WebChromeClient
import android.webkit.WebView
...

AndroidView(
    factory = {
        WebView(it).apply {

            this.layoutParams =
                ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )

            this.settings.javaScriptEnabled = true
            this.settings.domStorageEnabled = true

            this.webChromeClient = object : WebChromeClient() {
                override fun onPermissionRequest(request: PermissionRequest) {
                    request.grant(request.resources)
                }
            }
        }
    },
    update = {
        it.loadUrl(
            "https://global-stg.transak.com?apiKey=<YOUR_API_KEY>&sessionId=<YOUR_SESSION_ID>"
        )
    }
)
```

**`Kotlin`**

```kotlin title="Kotlin"
import android.webkit.PermissionRequest
import android.webkit.WebChromeClient
...

transakWidgetView.run {
  this.settings.javaScriptEnabled = true
  this.settings.domStorageEnabled = true

  this.webChromeClient = object : WebChromeClient() {
      override fun onPermissionRequest(request: PermissionRequest) {
          request.grant(request.resources)
      }
  }

  loadUrl("https://global-stg.transak.com?apiKey=<YOUR_API_KEY>&sessionId=<YOUR_SESSION_ID>")
}
```

**`Java`**

```java title="Java"
import android.webkit.WebView;
...

webView = (WebView) findViewById(R.id.transakWidgetView);

webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);

webView.setWebChromeClient(new WebChromeClient() {
   @Override
   public void onPermissionRequest(PermissionRequest request) {
      super.onPermissionRequest(request);
      request.grant(request.getResources());
   }
});

webView.loadUrl("https://global-stg.transak.com?apiKey=<YOUR_API_KEY>&sessionId=<YOUR_SESSION_ID>");
```

#### Configure XML Layout (Skip if using Compose)

Add the WebView to your `activity_main.xml` layout file:

```xml
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/transakWidgetView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
```

#### Create Widget URL (using Backend Only)

Call the [Create Widget URL](/api/public/create-widget-url) API from your backend to generate a secure widget url using

Query parameters

The response returns a `widgetUrl` that should be used to load Transak in Android Webview.

A `widgetUrl` is valid for 5 minutes and can only be used once. A new `widgetUrl` must be generated for every user flow.

**Example Request:**

```bash
curl --request POST \
  --url https://api-gateway-stg.transak.com/api/v2/auth/session \
  --header 'access-token: YOUR_ACCESS_TOKEN' \
  --header 'content-type: application/json' \
  --data '{
  "widgetParams": {
    "apiKey": "YOUR_API_KEY",
    "referrerDomain": "yourdomain.com"
  }
}'
```

## Use cases

Use the table below to choose the right approach for redirects, order data, and WebView events.

<table>
  <thead>
    <tr>
      <th>
        Feature
      </th>

      <th>
        Approach
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        How to redirect users back to your app after a transaction
      </td>

      <td>
        [Deeplink](#deeplinking)
      </td>
    </tr>

    <tr>
      <td>
        How to get order data (e.g. status, order ID, amount)
      </td>

      <td>
        [Deeplink](#deeplinking), [Events](#events)
      </td>
    </tr>

    <tr>
      <td>
        Listen to WebView events (order created, widget close, etc.)
      </td>

      <td>
        [Events](#events)
      </td>
    </tr>
  </tbody>
</table>

### Deeplink

Transak supports deeplinking through the use of the `redirectURL` query parameter to enable seamless navigation after the purchase/sell process is completed.

#### Register Deeplink in AndroidManifest File

Add an intent filter to your AndroidManifest.xml to handle the deeplink:

```xml
<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="myapp"
            android:host="transak-redirect" />
    </intent-filter>
</activity>
```

#### Handle Deeplink and Parse Parameters

Listen for the deeplink and parse the returned parameters in your Activity.

When Transak redirects back, it includes additional query parameters appended to deeplink URL mentioned [here](/customization/query-parameters#redirecturl-1).

```kotlin
override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    intent?.data?.let { uri ->
        val status = uri.getQueryParameter("status")
        val orderId = uri.getQueryParameter("order_id")
        val cryptoAmount = uri.getQueryParameter("cryptoAmount")
        // Handle more parameters
    }
}
```

#### Pass redirectURL in Create Widget URL API

Call the [Create Widget URL](/api/public/create-widget-url) API from your backend to generate a secure widget url using

Query parameters

along with `redirectURL` parameter.

The response returns a `widgetUrl` that should be used to load Transak in Android Webview.

A `widgetUrl` is valid for 5 minutes and can only be used once. A new `widgetUrl` must be generated for every user flow.

**Example Request:**

```bash
curl --request POST \
  --url https://api-gateway-stg.transak.com/api/v2/auth/session \
  --header 'access-token: YOUR_ACCESS_TOKEN' \
  --header 'content-type: application/json' \
  --data '{
  "widgetParams": {
    "apiKey": "YOUR_API_KEY",
    "referrerDomain": "yourdomain.com",
    "redirectURL": "myapp://transak-redirect"
  }
}'
```

### Events

Transak allows listening of in-widget events (like order creation, completion, and widget close) through native event handlers in Android WebViews.

Add a JavaScript interface to your WebView using the handler name

Android

to listen for all frontend events.

```kotlin
import android.webkit.PermissionRequest
import android.webkit.WebChromeClient
...

transakWidgetView.run {
  this.settings.javaScriptEnabled = true
  this.settings.domStorageEnabled = true
  this.addJavascriptInterface(WebAppInterface(this@MainActivity), "Android")

  this.webChromeClient = object : WebChromeClient() {
      override fun onPermissionRequest(request: PermissionRequest) {
          request.grant(request.resources)
      }
  }

  loadUrl("https://global-stg.transak.com?apiKey=<YOUR_API_KEY>&sessionId=<YOUR_SESSION_ID>")
}

class WebAppInterface(private val context: Context) {
    @JavascriptInterface
    fun postMessage(eventData: String) {
        Log.d("WebViewEvent", "postMessage: $eventData")
    }
}
```

#### Supported Events

<table>
  <thead>
    <tr>
      <th>
        Event Name
      </th>

      <th>
        Description
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        `TRANSAK_WIDGET_INITIALISED`
      </td>

      <td>
        Widget initialised with query params
      </td>
    </tr>

    <tr>
      <td>
        `TRANSAK_WIDGET_OPEN`
      </td>

      <td>
        Widget fully loaded
      </td>
    </tr>

    <tr>
      <td>
        `TRANSAK_ORDER_CREATED`
      </td>

      <td>
        Order created by user
      </td>
    </tr>

    <tr>
      <td>
        `TRANSAK_ORDER_SUCCESSFUL`
      </td>

      <td>
        Order is successful
      </td>
    </tr>

    <tr>
      <td>
        `TRANSAK_ORDER_CANCELLED`
      </td>

      <td>
        Order is cancelled
      </td>
    </tr>

    <tr>
      <td>
        `TRANSAK_ORDER_FAILED`
      </td>

      <td>
        Order is failed
      </td>
    </tr>

    <tr>
      <td>
        `TRANSAK_WIDGET_CLOSE`
      </td>

      <td>
        Widget is about to close
      </td>
    </tr>
  </tbody>
</table>