Migration from Google Play Billing SDK to Aptoide Billing SDK

This page helps the developers to migrate from the Google Play Billing SDK to Aptoide Billing SDK

Overview

This document provides a focused, step-by-step guide to migrate your application from Google Play Billing SDK (com.android.billingclient:billing) to the Aptoide Billing SDK (com.aptoide:android-aptoide-billing) for handling One-Time Products (consumables).

The Aptoide Billing SDK is structurally similar to Google Play Billing, which allows for an efficient migration with only a few targeted code changes. This guide will walk you through exactly what needs to be replaced or refactored.


Migration example

...
// Update the imports from Google Play package to Aptoide package
import android.app.Activity
import android.content.Context
import android.util.Log
-import com.android.billingclient.api.AcknowledgePurchaseResponseListener
-import com.android.billingclient.api.BillingClient
-import com.android.billingclient.api.BillingClient.BillingResponseCode
-import com.android.billingclient.api.BillingClient.ProductType
-import com.android.billingclient.api.BillingClientStateListener
-import com.android.billingclient.api.BillingFlowParams
-import com.android.billingclient.api.BillingResult
-import com.android.billingclient.api.ConsumeParams
-import com.android.billingclient.api.ConsumeResponseListener
-import com.android.billingclient.api.ProductDetails
-import com.android.billingclient.api.Purchase
-import com.android.billingclient.api.PurchasesUpdatedListener
-import com.android.billingclient.api.QueryProductDetailsParams
-import com.android.billingclient.api.QueryProductDetailsParams.Product
-import com.android.billingclient.api.QueryProductDetailsResult
-import com.android.billingclient.api.QueryPurchasesParams
+import com.aptoide.sdk.billing.AptoideBillingClient
+import com.aptoide.sdk.billing.AptoideBillingClient.BillingResponseCode
+import com.aptoide.sdk.billing.AptoideBillingClient.FeatureType
+import com.aptoide.sdk.billing.AptoideBillingClient.ProductType
+import com.aptoide.sdk.billing.BillingFlowParams
+import com.aptoide.sdk.billing.BillingResult
+import com.aptoide.sdk.billing.ConsumeParams
+import com.aptoide.sdk.billing.ProductDetails
+import com.aptoide.sdk.billing.Purchase
+import com.aptoide.sdk.billing.PurchasesUpdatedListener
+import com.aptoide.sdk.billing.QueryProductDetailsParams
+import com.aptoide.sdk.billing.QueryProductDetailsParams.Product
+import com.aptoide.sdk.billing.QueryProductDetailsResult
+import com.aptoide.sdk.billing.QueryPurchasesParams
+import com.aptoide.sdk.billing.listeners.AptoideBillingClientStateListener
+import com.aptoide.sdk.billing.listeners.ConsumeResponseListener
...

// Change the type of billingClient to AptoideBillingClient
-var billingClient: BillingClient
+val billingClient: AptoideBillingClient

...
// Update billingClientStateListener to AptoideBillingClientStateListener
-val billingClientStateListener: BillingClientStateListener
+val aptoideBillingClientStateListener: AptoideBillingClientStateListener
  get() =
-   object : BillingClientStateListener {
+   object : AptoideBillingClientStateListener {
      override fun onBillingSetupFinished(billingResult: BillingResult) {
        ...
      }

      override fun onBillingServiceDisconnected() {
        ...
      }
    }

...
// Initialize the SDK with the AptoideBillingClient Builder
// by setting the Public Key and
// remove enablePendingPurchases
fun setupSdkConnection(context: Context) {
- billingClient = BillingClient.newBuilder(context)
+ billingClient = AptoideBillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
-   .enablePendingPurchases()
+   .setPublicKey(PUBLIC_KEY)
    .build()
- billingClient.startConnection(billingClientStateListener)
+ billingClient.startConnection(aptoideBillingClientStateListener)
}
...
// Update the Payment initialization by launching it from a background Thread
fun launchPayment(activity: Activity, obfuscatedAccountId: String, productDetailsParamsList: List<BillingFlowParams.ProductDetailsParams>) {
  val billingFlowParams = BillingFlowParams.newBuilder()
     .setProductDetailsParamsList(productDetailsParamsList)
     .setObfuscatedAccountId(obfuscatedAccountId)
     .build()

-  billingClient.launchBillingFlow(activity, billingFlowParams)
+  Thread {
+    billingClient.launchBillingFlow(activity, billingFlowParams)
+  }.start()
}
...

Migration Steps Summary

To successfully migrate your one-time product integration, apply the following changes:

  1. Update SDK Dependency
    Replace the Google Play Billing SDK dependency with the Aptoide Billing SDK in your build.gradle.

  2. Update Imports
    Update all class imports that reference Google Play Billing to the corresponding Aptoide Billing SDK classes.

  3. Refactor Billing Client Initialization
    Replace BillingClient with AptoideBillingClient, and provide a public key via .setPublicKey().

  4. Update Purchase Flow
    Use the same billing flow structure but ensure that the call to launchBillingFlow() is done on a background thread to support Aptoide WebPayments.


1. Update SDK Dependency

What to do:
Remove the dependency on Google Play Billing from your build.gradle file and add the Aptoide Billing SDK instead.

You should also sync your project and ensure your app is using the latest stable Aptoide billing version.

Google Play SDK:

implementation("com.android.billingclient:billing:8.0.0")  

Aptoide SDK:

implementation("com.aptoide:android-aptoide-billing:1.+")  

2. Update Imports

Replace all references to classes from com.android.billingclient.api with the corresponding Aptoide Billing SDK classes from com.aptoide.sdk.billing.

Most class names remain the same (Purchase, ProductDetails, BillingFlowParams, etc.) but come from different packages.

Google Play Imports:

import com.android.billingclient.api.BillingClient  
import com.android.billingclient.api.Purchase  
import com.android.billingclient.api.ProductDetails  
import com.android.billingclient.api.QueryProductDetailsParams  
import com.android.billingclient.api.BillingFlowParams  
import com.android.billingclient.api.BillingClient; 
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.ProductDetails;  
import com.android.billingclient.api.QueryProductDetailsParams;  
import com.android.billingclient.api.BillingFlowParams;

Aptoide Imports:

import com.aptoide.sdk.billing.AptoideBillingClient  
import com.aptoide.sdk.billing.Purchase  
import com.aptoide.sdk.billing.ProductDetails  
import com.aptoide.sdk.billing.QueryProductDetailsParams  
import com.aptoide.sdk.billing.BillingFlowParams  
import com.aptoide.sdk.billing.AptoideBillingClient;  
import com.aptoide.sdk.billing.Purchase;  
import com.aptoide.sdk.billing.ProductDetails;  
import com.aptoide.sdk.billing.QueryProductDetailsParams;  
import com.aptoide.sdk.billing.BillingFlowParams;

3. Refactor Billing Client Initialization

Replace the instantiation of BillingClient with AptoideBillingClient. Unlike Google Play Billing, the Aptoide SDK requires you to set the public key via .setPublicKey() and to use startConnection() with an AptoideBillingClientStateListener.

You can retrieve your public key from Aptoide Connect.

Google Play Initialization:

val billingClientStateListener: BillingClientStateListener
		get() =
  			object : BillingClientStateListener {
						...
      	}

val billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
  	.build()

billingClient.startConnection(billingClientStateListener)
BillingClientStateListener billingClientStateListener = new BillingClientStateListener() {
		...
};

BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .build();

billingClient.startConnection(billingClientStateListener);

Aptoide Initialization:

val aptoideBillingClientStateListener: AptoideBillingClientStateListener
		get() =
  			object : AptoideBillingClientStateListener {
						...
      	}

val billingClient = AptoideBillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .setPublicKey(MY_PUBLIC_KEY)
    .build()

billingClient.startConnection(aptoideBillingClientStateListener)
AptoideBillingClientStateListener aptoideBillingClientStateListener = new AptoideBillingClientStateListener() {
		...
};

AptoideBillingClient billingClient = AptoideBillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .setPublicKey(MY_PUBLIC_KEY)
    .build();

billingClient.startConnection(aptoideBillingClientStateListener);

4. Update Purchase Flow

The logic to create and pass ProductDetailsParams is the same as in Google. However, Aptoide requires the call to launchBillingFlow() to be made from a background thread, not the UI thread. This ensures compatibility with Aptoide’s WebPayment fallback when the native Wallet app is not installed.

Google Play Purchase Flow:

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(listOf(
        BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .build()
    ))
    .build()

billingClient.launchBillingFlow(activity, billingFlowParams)
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(List.of(
        BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .build()
    ))
    .build();

billingClient.launchBillingFlow(activity, billingFlowParams);

Aptoide Purchase Flow:

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(listOf(
        BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .build()
    ))
    .build()

Thread {
    val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
    runOnUiThread {
        // Handle billingResult
    }
}.start()
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(List.of(
        BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .build()
    ))
    .build();

new Thread(() -> {
    BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams); 
    activity.runOnUiThread(() -> {
        // Handle billingResult
    });
}).start();

Changes Comparison Table

FeatureGoogle Play BillingAptoide Billing SDK
SDK Dependencycom.android.billingclientcom.aptoide:android-aptoide-billing
ImportsGoogle Play classes (com.android.billingclient.api)Aptoide Billing classes (com.aptoide.sdk.billing)
Billing Client namingBillingClientAptoideBillingClient
Public Key Requirement.setPublicKey(...) required
Billing Flow launch in specific threadUI/Main Thread✅ Must use background thread for WebPayments

FAQ

Where can I find the entire Aptoide Billing SDK Integration documentation?

Our entire documentation for the Aptoide Billing SDK Integration can be found in here. It contains the most important steps to have a complete and successful integration of our Billing system.


Where can I find the Public Key of my application?

In order to obtain the Public Key of your application and use it to initialize the Billing Client, follow this guide.


My application contains Subscriptions, are there any differences?

Subscription follow a different structure in the Aptoide Billing SDK which require some additional changes to correctly integrate them. Follow our complete integration guide since it contains all the necessary steps.

If you have any additional questions or doubts, contact our official support channels.