Call order in Android SDK
Adapty.activate() must finish before you call any other Adapty SDK method. Until it completes, the SDK has no state. Any call issued before or in parallel with activate() fails with ADAPTY_NOT_INITIALIZED.
If your app authenticates users and you collect a customer user ID after launch, call Adapty.identify() at that point. Don’t call user-action methods until identify’s completion callback fires. Calls that race against it either return an error in their callback, or land on the anonymous profile created at activation. When this happens, attribution, MMP IDs like appsflyer_id, and install ownership don’t always transfer to the identified profile. If your app doesn’t authenticate users, skip identify and keep working with the anonymous profile.
MMP and analytics SDKs (AppsFlyer, Adjust, Branch, PostHog) follow the same rule. Initialize them first and wait for their UID callbacks before calling Adapty.activate. Otherwise the MMP ID lands on a brief anonymous profile and isn’t always transferred to the identified one. For AppsFlyer specifics, see AppsFlyer.
The correct order
Your path depends on two things: when you know the customer user ID, and whether you use an MMP or analytics SDK.
- Steps 2 and 5: Mandatory for every app. Activate the SDK, then call SDK methods.
- Steps 1 and 3: Required only if you integrate an MMP or analytics SDK (AppsFlyer, Adjust, Branch, PostHog).
- Step 4: Required only if your app authenticates users and collects the customer user ID after launch.
If you have the customer user ID at app launch, pass it into the AdaptyConfig.Builder before calling activate() (step 2a). This path never creates an anonymous profile, so step 4 is unnecessary.
| Step | Call | When | Notes |
|---|---|---|---|
| 1 | Initialize your MMP or analytics SDK (AppsFlyer, Adjust, PostHog, Branch) | App launch, first | Wait for the MMP’s UID callback, for example getAppsFlyerUID. |
| 2a | Adapty.activate(context, AdaptyConfig.Builder("KEY").withCustomerUserId(...).build()) | App launch, after step 1, if you have the customer user ID | Recommended. No anonymous profile is ever created. |
| 2b | Adapty.activate(context, AdaptyConfig.Builder("KEY").build()) without customerUserId | App launch, after step 1, if you don’t have the customer user ID (or never collect one) | Adapty creates an anonymous profile. |
| 3 | Adapty.setIntegrationIdentifier("appsflyer_id", uid) for each MMP | After step 2, before any user-action call | Required so MMP IDs land on the correct profile. |
| 4 | Adapty.identify("YOUR_USER_ID") { error -> ... } | After step 3 (or step 2 if no MMP), before step 5 — only on path 2b with authentication | Use the completion callback. Concurrent calls during identify may land on the anonymous profile. |
| 5 | getPaywall, getPaywallProducts, restorePurchases, makePurchase, updateAttribution, updateProfile | After step 4 if you call identify; otherwise after step 3 (or step 2 if no MMP) | These calls need a stable profile. |
Skipping these steps causes lost premium access for returning users, missing appsflyer_id on profiles, and paywalls returned against the wrong audience.
Web2app and web-funnel installs
If users buy on a web checkout (Stripe, Paddle) and later install the native app, the device’s first activate() creates a new anonymous profile. This profile isn’t linked to the web profile. If you can resolve the customer user ID before app launch (from your auth flow or install referrer), pass it into the AdaptyConfig.Builder directly. Otherwise the web purchase is invisible on the device until you call identify("YOUR_USER_ID") and then restorePurchases.
For the metadata to send with each web checkout, see: