Android – Making Purchases

Learn how to make and restore mobile purchases using Adapty Android SDK. Adapty handles server-side validation, including renewals and grace periods

To make the purchase, you have to call .makePurchase() method:

Adapty.makePurchase(activity, product) { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val profile = result.value              
            //NOTE: profile is null in case of cross-grade with DEFERRED proration mode
            
            // successful purchase
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
Adapty.makePurchase(activity, product, result -> {
    if (result instanceof AdaptyResult.Success) {
        AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue();
        //NOTE: profile is null in case of cross-grade with DEFERRED proration mode
        
        // successful purchase
    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
    }
});

Request parameters:

Response parameters:

  • Profile: an AdaptyProfile object. This model contains info about access levels, subscriptions, and non-subscription purchases. Generally, you have to check only access level status to determine whether the user has premium access to the app.

🚧

Make sure you've uploaded Service Account Key File in Adapty Dashboard, without it, we can't validate purchases.

Below is a complete example of making the purchase and checking the user's access level.

Adapty.makePurchase(activity, product) { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val profile = result.value
            //NOTE: profile is null in case of cross-grade of DEFERRED proration mode
            
            if (profile?.accessLevels?.get("premium")?.isActive == true) {
                // grant access to premium features
            }
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
Adapty.makePurchase(activity, product, result -> {
    if (result instanceof AdaptyResult.Success) {
        AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue();
        //NOTE: profile is null in case of cross-grade with DEFERRED proration mode
        
        if (profile != null) {
            AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("premium");
            
            if (premium != null && premium.isActive()) {
                // grant access to premium features
            }
        }
    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
    }
});

🚧

Make sure to set up Real-time Developer Notifications (RTDN) to receive subscription updates without significant delays.

Change subscription

If you need a subscription to be replaced with another one, you have to call .makePurchase() method with additional parameter:

Adapty.makePurchase(activity, product, subscriptionUpdateParams) { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val profile = result.value              
            //NOTE: profile is null in case of cross-grade with DEFERRED proration mode
            
            // successful cross-grade
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
Adapty.makePurchase(activity, product, subscriptionUpdateParams, result -> {
    if (result instanceof AdaptyResult.Success) {
        AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue();
        //NOTE: profile is null in case of cross-grade with DEFERRED proration mode
        
        // successful cross-grade
    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
    }
});

Additional request parameter:

You can read more about proration modes here.

📘

Please read recommendations from Google for proration modes.

📘

IMMEDIATE_AND_CHARGE_PRORATED_PRICE proration mode is available only for a subscription upgrade, where the price per unit of time increases.

📘

If you use DEFERRED proration mode, in case of success, profile in the callback is null since real subscription change will occur only when current subscription's billing period ends.

Restoring purchases

To restore purchases, you have to call .restorePurchases() method:

Adapty.restorePurchases { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val profile = result.value
            // check the access level
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
Adapty.restorePurchases(result -> {
    if (result instanceof AdaptyResult.Success) {
        AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue();
        // check the access level
      
    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
    }
});

Response parameters:

  • Profile: an AdaptyProfile object. This model contains info about access levels, subscriptions, and non-subscription purchases. Generally, you have to check only access level status to determine whether the user has premium access to the app.

In Observer mode, after any purchase or restore in your application, you should call .restorePurchases() method to record the action in Adapty.


What’s Next