Sign in to Aptoide Services (Android SDK)
Signing in to Aptoide Services links the user's purchases to their Aptoide account. Once signed in, their pending and non-consumable purchases are retrievable via queryPurchasesAsync even after the host app's storage is cleared or the user switches devices - no backend is required on your side.
Account sign-in is remotely toggled and is off by default. Verify it is available before
exposing it with billingClient.isFeatureSupported(FeatureType.ACCOUNT_SIGN_IN) (a response code of
OK means it is enabled; SERVICE_UNAVAILABLE means the configuration is still loading - retry).
Sign in
Use signInToAptoideServices to launch the Aptoide account sign-in flow. It is asynchronous: the outcome is delivered to the AptoideSignInResponseListener as a BillingResult. Call it after the SDK connection is established (for example from a "Sign in" button).
- Kotlin
- Java
fun signIn(activity: Activity) {
billingClient.signInToAptoideServices(activity) { billingResult ->
runOnUiThread {
when (billingResult.responseCode) {
BillingResponseCode.OK -> restoreOwnedPurchases() // signed in (or already signed in)
BillingResponseCode.USER_CANCELED -> Log.i(TAG, "Sign-in dismissed by the user")
BillingResponseCode.FEATURE_NOT_SUPPORTED -> Log.i(TAG, "Sign-in is disabled")
BillingResponseCode.SERVICE_UNAVAILABLE -> Log.i(TAG, "Not ready yet - retry shortly")
else -> Log.e(TAG, "Sign-in error: ${billingResult.debugMessage}")
}
}
}
}
private void signIn(Activity activity) {
billingClient.signInToAptoideServices(activity, billingResult -> {
runOnUiThread(() -> {
switch (billingResult.getResponseCode()) {
case BillingResponseCode.OK:
restoreOwnedPurchases(); // signed in (or already signed in)
break;
case BillingResponseCode.USER_CANCELED:
Log.i(TAG, "Sign-in dismissed by the user");
break;
case BillingResponseCode.FEATURE_NOT_SUPPORTED:
Log.i(TAG, "Sign-in is disabled");
break;
case BillingResponseCode.SERVICE_UNAVAILABLE:
Log.i(TAG, "Not ready yet - retry shortly");
break;
default:
Log.e(TAG, "Sign-in error: " + billingResult.getDebugMessage());
}
});
});
}
The response codes returned to the listener are:
| Response code | Meaning |
|---|---|
OK | The user signed in, or was already signed in. Proceed to query owned purchases. |
USER_CANCELED | The user dismissed the sign-in screen or chose "don't show again". |
FEATURE_NOT_SUPPORTED | Account sign-in is disabled (feature flag off). |
SERVICE_UNAVAILABLE | The configuration is still loading (or failed to load) - retryable. |
ERROR | An unexpected error occurred. |
On OK, query the owned purchases to restore the entitlements (the result includes acknowledged
non-consumables - see Acknowledge a non-consumable purchase):
- Kotlin
- Java
private fun restoreOwnedPurchases() {
billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder()
.setProductType(ProductType.INAPP)
.build()
) { billingResult, purchases ->
if (billingResult.responseCode == BillingResponseCode.OK) {
purchases.forEach { grantEntitlement(it) }
}
}
}
private void restoreOwnedPurchases() {
billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder()
.setProductType(ProductType.INAPP)
.build(),
(billingResult, purchases) -> {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
for (Purchase purchase : purchases) {
grantEntitlement(purchase);
}
}
}
);
}
The sign-in screen is shown sparingly by the SDK (it is rate-limited and offers the user a "don't
show again" option), so calling signInToAptoideServices is safe - it simply returns without
showing the screen when appropriate.
Check the current sign-in state
Use isSignedInToAptoideServices to read the current state synchronously - for example, to decide whether to show a "Sign in" or "Log out" button when a screen opens.
- Kotlin
- Java
val signedIn = billingClient.isSignedInToAptoideServices()
boolean signedIn = billingClient.isSignedInToAptoideServices();
Listen for sign-in state changes
Sign-in and sign-out can also happen inside the payment WebView. Register an
AptoideAccountStateListener on the builder to be notified of any
state change, so you can refresh your UI and re-query purchases without the user restarting the app.
The state is one of AccountState: SIGNED_IN or SIGNED_OUT.
It is only fired on an actual state transition.
- Kotlin
- Java
billingClient = AptoideBillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.setAccountStateListener { state ->
runOnUiThread {
when (state) {
AccountState.SIGNED_IN -> restoreOwnedPurchases()
AccountState.SIGNED_OUT -> revokeAccountEntitlements()
}
}
}
.setPublicKey(publicKey)
.build()
billingClient = AptoideBillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.setAccountStateListener(state -> {
runOnUiThread(() -> {
if (state == AccountState.SIGNED_IN) {
restoreOwnedPurchases();
} else if (state == AccountState.SIGNED_OUT) {
revokeAccountEntitlements();
}
});
})
.setPublicKey(publicKey)
.build();
Sign out
Use signOutFromAptoideServices to sign the
user out. It clears the stored session and reverts all subsequent operations to the anonymous guest
flow. Any registered AptoideAccountStateListener is notified
with AccountState.SIGNED_OUT.
- Kotlin
- Java
billingClient.signOutFromAptoideServices()
billingClient.signOutFromAptoideServices();