> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/classic-push-provisioning/developer-guide/sdk-configuration/android.md).

# Android

Push Provisioning SDK is used to tokenize cards for Google Pay and Samsung Pay. This SDK handles communication with the Google Pay and Samsung Pay SDKs. It also simplifies the Tokenization flow for issuer applications.

This section is for Android issuer application developers who want to integrate Push Provisioning SDK into their application.

### Available services <a href="#available-services" id="available-services"></a>

Thales Push Provisioning SDK provides the following services:

* Enable you to integrate an issuer application with Push Provisioning SDK APIs, such as `isCardDigitized` and `addCard` (Google Pay and Samsung Pay).
* Reduce the need to understand Google Pay and Samsung Pay SDKs.
* Reuse Push Provisioning SDK services in existing projects.
* Enroll the FPAN in Google Pay or Samsung Pay.
* Access TSH server APIs.

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* Java version: 11
* Android Studio version: Chipmunk or later.
* A device with Google Play Services (for Google Pay).

> <i class="fa-info-circle">:info-circle:</i>
>
> For full functionality of Google Pay, it is recommended to run it on mobile devices.

### Integrating with issuer app <a href="#integrating-with-issuer-app" id="integrating-with-issuer-app"></a>

* Create a folder named `libs` inside the module (usually 'app') directory, as shown in the following figure:

<figure><img src="/files/5CyRTyvmgomFz94mwiOs" alt=""><figcaption></figcaption></figure>

* Copy the Push Provisioning SDK AAR file into the `libs` folder.
* Since Push Provisioning SDK v1.12.2, copy Samsung Pay SDK JAR file into the  `libs` folder.
* Open the app's `build.gradle` or `build.gradle.kts` and add the following dependencies:

{% tabs %}
{% tab title="Groovy" %}

```groovy
android {
  defaultConfig {
    ndk {
      abiFilters 'arm64-v8a', 'x86_64', 'armeabi-v7a', 'x86'
    }
  }
  buildTypes {
        debug {
            // for Samsung Pay
            manifestPlaceholders = [DEBUG_MODE: 'Y', SPAY_API_LEVEL: 2.22]
        }
        release {
            // for Samsung Pay
            manifestPlaceholders = [DEBUG_MODE: 'N' , SPAY_API_LEVEL: 2.22]
        }
    }
}

dependencies {
    debugImplementation 'com.squareup.okhttp3:logging-interceptor:4.9.1' // debug contains logger
    releaseImplementation 'com.squareup.okhttp3:okhttp:4.9.1'
    implementation "com.google.android.gms:play-services-base:18.5.0"
    implementation "com.google.android.gms:play-services-basement:18.5.0"
    implementation files('libs/tpcsdk.aar') // Use the latest Push Provisioning SDK file name 
    implementation files('lib/samsungpay_2.22.00.jar') // since SDK v1.12.2
    implementation 'net.java.dev.jna:jna:5.17.0@aar'
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
android {
  defaultConfig {
    ndk {
      abiFilters += listOf("arm64-v8a", "x86_64", "armeabi-v7a", "x86")
    }
  }
}

dependencies {
    debugImplementation ("com.squareup.okhttp3:logging-interceptor:4.9.1") // debug contains logger
    releaseImplementation ("com.squareup.okhttp3:okhttp:4.9.1")
    implementation ("com.google.android.gms:play-services-base:18.2.0")
    implementation (files("libs/tpcsdk.aar")) // Use the latest Push Provisioning SDK file name 
    implementation ("net.java.dev.jna:jna:5.17.0@aar")
}
```

{% endtab %}
{% endtabs %}

> <i class="fa-info-circle">:info-circle:</i>
>
> #### Note <a href="#note" id="note"></a>
>
> * Since Push Provisioning SDK V1.7.0, the JNA library is used as a dependency. It is recommended to use JNA V5.5.0 because other versions are not guaranteed to work with Push Provisioning SDK.
> * Since Push Provisioning SDK V1.12.0, it is mandatory to use JNA V5.17.0 to support 16 KB page sizes.

* To import a file-tree dependency into the Gradle build, open the app's `build.gradle` or `build.gradle.kts` and add the following dependency:

{% tabs %}
{% tab title="Groovy" %}

```groovy
dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
dependencies {
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
}
```

{% endtab %}
{% endtabs %}

* Refer to the sample app and Java documentation to learn how to use the Push Provisioning SDK APIs.

> <i class="fa-exclamation-circle">:exclamation-circle:</i>
>
> #### Supporting 16 KB page sizes <a href="#supporting-16-kb-page-sizesbr" id="supporting-16-kb-page-sizesbr"></a>
>
> Starting Nov 1, 2025, all newly developed apps and updates to existing apps submitted to Google Play, and intended for Android 15+ devices, must support 16 KB page sizes. This support is available for Push Provisioning SDK V1.12.0 and later.
>
> When building an APK that supports 16 KB page sizes:
>
> * Upgrade to Push Provisioning SDK V1.12.0 or later.
> * Upgrade the JNA dependency to 5.17.0 or later. For JNA 5.17.0, the required Android Gradle Plugin (AGP) version is 8.0.2 or later. If you use AGP earlier than 8.0.2, you may encounter compilation issues.
> * When the AGP version is 8.5.1 or later, the app is automatically aligned to 16 KB page sizes. If it is earlier than 8.5.1, set the [legacy packaging options](https://developer.android.com/guide/practices/page-sizes#agp_version_85_or_lower) in the `build.gradle` file.

### Configuration <a href="#configuration" id="configuration"></a>

Use the following snippet to configure Push Provisioning SDK in your mobile application:

> <i class="fa-info-circle">:info-circle:</i>
>
> #### Note <a href="#note-1" id="note-1"></a>
>
> Since Push Provisioning SDK V1.9.0, your application can set an application `Context` instead of an `Activity` when configuring Push Provisioning SDK for Google Pay and Samsung Pay. An `Activity` is only required by the new API, `addCard(Activity activity, CardInfo cardInfo, TPCSDKListener<T> listener)`, for Google Pay push provisioning.

{% tabs %}
{% tab title="Java" %}

```java
protected static final int HTTP_TIMEOUT = 60;

protected CountDownLatch mCountDownLatch;

protected void awaitCountDownLatch() {
    try {
        mCountDownLatch.await(HTTP_TIMEOUT, TimeUnit.SECONDS);
    } catch (Exception e) { // Ignored.
    }
}

protected void resetCountDownLatch() {
    mCountDownLatch = new CountDownLatch(1);
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); 
    Config config = new Config();
    config.setIssuerId("ISSUERID");
    config.setUrl("URL"); // respective URL
    
    // The list can be updated accordingly. For example, you may only need to have one type of OEMPayType.
    List<OEMPayType> oemPayTypes = Arrays.asList(
        OEMPayType.NONE,
        OEMPayType.GOOGLE_PAY,
        OEMPayType.SAMSUNG_PAY,
        OEMPayType.HUAWEI_PAY);

    for (OEMPayType oemPayType:oemPayTypes) {
        if (oemPayType == OEMPayType.SAMSUNG_PAY) {
            config.setContext(getApplicationContext());
            config.setServiceId("SERVICEID");
            config.setVisaClientAppId("VisaClientAppID");
        } else if (oemPayType == OEMPayType.HUAWEI_PAY) {
            String callbackUrl = "tpcsdk://com.thalesgroup.tpc.demo/tokenRequestorsPage";
            config.setCallbackUrl(callbackUrl);
            config.setActivity(getActivity());
        } else if (oemPayType == OEMPayType.GOOGLE_PAY) {
            //Since Push Provisioning SDK V1.9.0, Application may set `Context` instead of `Activity` during Push Provisioning SDK configuration for Google Pay
            config.setContext(getApplicationContext());
        } else if (oemPayType == OEMPayType.NONE) {
            //Since Push Provisioning SDK V1.9.0, Application may set `Context` instead of `Activity` during Push Provisioning SDK configuration for Scheme Provisioning
            config.setContext(getApplicationContext());
        }
        configSdk(oemPayType, config);
    }
}

public void configSdk(OEMPayType oemPayType, Config configs) throws InterruptedException {
    // for push to scheme
    configs.setOemPayType(oemPayType);
    resetCountDownLatch();
    TPCManager.getInstance().config(configs, new TPCSDKListener<Boolean>() {
        @Override
        public void onStart() {
        }

        @Override
        public void onSuccess(TPCResult<Boolean> result) {
            Log.d("CONFIG_SDK", "Configuration successful..." + oemPayType.getOemType());
            mCountDownLatch.countDown();
        }

        @Override
        public void onError(TPCSDKException exception) {
            Log.e("CONFIG_SDK", "Configuration setup failed with error: " + exception.getMessage());
            mCountDownLatch.countDown();
        }
    });
    awaitCountDownLatch();
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
class MainViewModel : ViewModel() {
    fun configureMultipleOEM(activity: Activity){
        viewModelScope.launch {
            val config = Config()
            config.issuerId = "ISSUERID"
            config.url = "URL" // respective URL

            // The list can be updated accordingly. For example, you may only need to have one type of OEMPayType.
            val oemPayTypes: List<OEMPayType> = listOf(
                OEMPayType.NONE,
                OEMPayType.GOOGLE_PAY,
                OEMPayType.SAMSUNG_PAY,
                OEMPayType.HUAWEI_PAY
            )
            for (oemPayType in oemPayTypes) {
                when (oemPayType) {
                    OEMPayType.SAMSUNG_PAY -> {
                        config.serviceId = "SERVICEID"
                        config.context = applicationContext
                        config.visaClientAppId = "VisaClientAppID";
                    }
                    OEMPayType.HUAWEI_PAY -> {
                        val callbackUrl = "tpcsdk://com.thalesgroup.tpc.demo/tokenRequestorsPage"
                        config.callbackUrl = callbackUrl
                        config.activity = activity
                    }
                    OEMPayType.GOOGLE_PAY -> {
                        //Since Push Provisioning SDK V1.9.0, Application may set `Context` instead of `Activity` during Push Provisioning SDK configuration for Google Pay
                        config.context = applicationContext
                    }
                    OEMPayType.NONE -> {
                        //Since Push Provisioning SDK V1.9.0, Application may set `Context` instead of `Activity` during Push Provisioning SDK configuration for Scheme Provisioning
                        config.context = applicationContext
                    }
                }
                configSdk(oemPayType, config).collect{
                    println(it)
                }
            }
        }
    }

    private fun configSdk(oemPayType: OEMPayType, configs: Config): Flow<TPCResult<Boolean>> =  callbackFlow {
        val callBack = object : TPCSDKListener<Boolean?> {
            override fun onStart() {}
            override fun onSuccess(result: TPCResult<Boolean?>) {
                Log.d("CONFIG_SDK", "Configuration successful..." + oemPayType.oemType)
                channel.close()
            }

            override fun onError(exception: TPCSDKException) {
                Log.e("CONFIG_SDK", "Configuration setup failed with error: " + exception.message)
                channel.close()

            }
        }
        TPCManager.getInstance().config(configs, callBack)
        
    }
}
```

{% endtab %}
{% endtabs %}

#### Samsung Pay configuration <a href="#samsung-pay-configurations" id="samsung-pay-configurations"></a>

Starting with Android R (target SDK 30), you must declare `<queries>` in the Android manifest file.

```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools" 
  package="xxx.xxx.xxx.xxx">
  
  <application>
    <!-- for Samsung Pay -->
    <meta-data
      android:name="debug_mode"
      android:value="${DEBUG_MODE}" />
    <!-- for Samsung Pay -->
    <meta-data
      android:name="spay_sdk_api_level"
      android:value="${SPAY_API_LEVEL}" />
  </application>
  
  <queries>
    <package android:name="com.samsung.android.spay" />
    <package android:name="com.samsung.android.samsungpay.gear" />
  </queries>
```

### Obfuscation <a href="#obfuscation" id="obfuscation"></a>

If your app has ProGuard issues with Samsung Pay, use the following rules:

```
# Samsung Pay
-keep class com.samsung.android.sdk.** { *; }
-keep interface com.samsung.android.sdk.** { *; }
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.payments.thalescloud.io/classic-push-provisioning/developer-guide/sdk-configuration/android.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
