> 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="https://2043783750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC22AqJs7fn1cZC7pAaOE%2Fuploads%2FaVZ5xunluNKEoqgRwQ63%2FDev-Guide_SDK-conf_01.png?alt=media&amp;token=d21c8dad-b05a-421f-9153-1227e3e0c7a1" 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.
* Since Push Provisioning SDK v2.0.0, copy Google Pay SDK AAR 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('libs/samsungpay_2.22.00.jar') // since SDK v1.12.2
    implementation files('libs/play-services-tapandpay-18.7.0.aar') // since SDK v2.0.0
    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/samsungpay_2.22.00.jar') // since SDK v1.12.2
    implementation files('libs/play-services-tapandpay-18.7.0.aar') // since SDK v2.0.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); 
    // Configure SDK for scheme push provisioning
    // Since Push Provisioning SDK V2.0.0, only set OEMPayType when performing OEM Wallet provisioning. Leave OEM type unset otherwise.
    Config schemeConfig = new Config();
    schemeConfig.setIssuerId("ISSUERID");
    schemeConfig.setUrl("URL"); // respective URL
    // Since Push Provisioning SDK V1.9.0, Application may set `Context`
    // instead of `Activity` during Push Provisioning SDK configuration
    // for Scheme Provisioning
    schemeConfig.setContext(getApplicationContext());
    configSdkForScheme(schemeConfig);
    
    // Configure SDK for OEM push provisioning
    Config oemConfig = new Config();
    oemConfig.setIssuerId("ISSUERID");
    oemConfig.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(
        //Since Push Provisioning SDK V2.0.0, OEMPayType.NONE is no longer supported
        OEMPayType.GOOGLE_PAY,
        OEMPayType.SAMSUNG_PAY,
        OEMPayType.HUAWEI_PAY);

    for (OEMPayType oemPayType:oemPayTypes) {
        if (oemPayType == OEMPayType.SAMSUNG_PAY) {
            oemConfig.setContext(getApplicationContext());
            oemConfig.setServiceId("SERVICEID");
            oemConfig.setVisaClientAppId("VisaClientAppID");
        } else if (oemPayType == OEMPayType.HUAWEI_PAY) {
            String callbackUrl = "tpcsdk://com.thalesgroup.tpc.demo/tokenRequestorsPage";
            oemConfig.setCallbackUrl(callbackUrl);
            oemConfig.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
            oemConfig.setContext(getApplicationContext());
        }
        configSdk(oemPayType, oemConfig);
    }
}

public void configSdkForScheme(Config configs) throws InterruptedException {
    // Since Push Provisioning SDK V2.0.0, for scheme push provisioning, do not set OEMPayType
    resetCountDownLatch();
    TPCManager.getInstance().config(configs, new TPCSDKListener<Boolean>() {
        @Override
        public void onStart() {
        }

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

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

public void configSdk(OEMPayType oemPayType, Config configs) throws InterruptedException {
    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 {
            // Configure SDK for scheme push provisioning
            // Since Push Provisioning SDK V2.0.0, only set OEMPayType when performing OEM Wallet provisioning. Leave OEM type unset otherwise.
            val schemeConfig = Config()
            schemeConfig.issuerId = "ISSUERID"
            schemeConfig.url = "URL" // respective URL
            // Since Push Provisioning SDK V1.9.0, Application may set `Context`
            // instead of `Activity` during Push Provisioning SDK configuration
            // for Scheme Provisioning
            schemeConfig.context = applicationContext

            configSdkForScheme(schemeConfig).collect {
                println(it)
            }

            // Configure SDK for OEM push provisioning
            val oemConfig = Config()
            oemConfig.issuerId = "ISSUERID"
            oemConfig.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(
                //Since Push Provisioning SDK V2.0.0, OEMPayType.NONE is no longer supported
                OEMPayType.GOOGLE_PAY,
                OEMPayType.SAMSUNG_PAY,
                OEMPayType.HUAWEI_PAY
            )
            for (oemPayType in oemPayTypes) {
                when (oemPayType) {
                    OEMPayType.SAMSUNG_PAY -> {
                        oemConfig.serviceId = "SERVICEID"
                        oemConfig.context = applicationContext
                        oemConfig.visaClientAppId = "VisaClientAppID";
                    }
                    OEMPayType.HUAWEI_PAY -> {
                        val callbackUrl = "tpcsdk://com.thalesgroup.tpc.demo/tokenRequestorsPage"
                        oemConfig.callbackUrl = callbackUrl
                        oemConfig.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
                        oemConfig.context = applicationContext
                    }
                }
                configSdk(oemPayType, oemConfig).collect{
                    println(it)
                }
            }
        }
    }

    private fun configSdkForScheme(configs: Config): Flow<TPCResult<Boolean>> = callbackFlow {
        // Since Push Provisioning SDK V2.0.0, for scheme push provisioning, do not set OEMPayType
        val callBack = object : TPCSDKListener<Boolean?> {
            override fun onStart() {}

            override fun onSuccess(result: TPCResult<Boolean?>) {
                Log.d("CONFIG_SDK", "Scheme configuration successful...")
                channel.close()
            }

            override fun onError(exception: TPCSDKException) {
                Log.e("CONFIG_SDK", "Scheme configuration failed with error: " + exception.message)
                channel.close()
            }
        }
        TPCManager.getInstance().config(configs, callBack)
    }

    private fun configSdk(oemPayType: OEMPayType, configs: Config): Flow<TPCResult<Boolean>> =  callbackFlow {
        configs.oemPayType = oemPayType;
        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:

<pre><code># Samsung Pay
-keep class com.samsung.android.sdk.** { *; }
<strong>-keep interface com.samsung.android.sdk.** { *; }
</strong></code></pre>

Following are Google's recommended obfuscation rules:

{% code overflow="wrap" %}

```
# Google Pay
# Preserve the TapAndPay SDK client classes and interfaces
-keep class com.google.android.gms.tapandpay.** { *; }

# Prevent stripping or renaming of SafeParcelable classes and their CREATOR fields
-keep class * implements com.google.android.gms.common.internal.safeparcelable.SafeParcelable {
    public static final android.os.Parcelable$Creator *;
}

# Preserve standard Parcelable creator fields
-keepclassmembers class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator CREATOR;
}

```

{% endcode %}


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
