Develop

In-App Purchases sample overview

Updated: May 8, 2026

Overview

This sample demonstrates how to integrate In-App Purchases (IAP) using the Horizon Platform SDK for Android, covering product catalogs, user purchases, checkout flows, and purchase consumption.
Note: The Horizon Platform SDK is currently at version 0.2.0 and is in early release. APIs and patterns may evolve in future versions. View the sample source code on GitHub.

What you will learn

  • Initialize the Horizon Platform SDK and instantiate the IAP API
  • Retrieve products by SKU using the SDK’s paged results pattern
  • Query a user’s existing purchases
  • Launch the checkout flow and consume purchases
  • Structure IAP logic using MVVM architecture with Jetpack Compose and StateFlow

Requirements

  • Meta Quest device with Developer Mode enabled
  • Android Studio with Kotlin support
  • Application ID from the Meta developer dashboard
For SDK installation and build prerequisites, see the Platform SDK setup guide.

Get started

Clone the Horizon Platform SDK samples repository and open the iap directory in Android Studio. Replace the APPLICATION_ID property in MainActivity.kt with your actual Application ID — if you skip this step, the sample throws an IllegalStateException when initializing the SDK connection. Build and deploy the sample to your Quest device. For detailed build and deployment steps, see the sample’s README.

Explore the sample

FileWhat it demonstratesKey concepts
MainActivity.kt
Entry point, SDK initialization, and Compose UI
HorizonServiceConnection.connect(), IapScreen composable
IapViewModel.kt
IAP business logic and state management
Iap() instantiation, four API methods, StateFlow with IapUiState data class
IapViewModelTest.kt
Unit tests for ViewModel state
Default state validation, immutable state copy behavior
app/build.gradle.kts
Build configuration
psdk-core and psdk-iap dependencies, SDK levels

Runtime behavior

When you run the sample, you see a title and a row of placeholder SKU chips (SKU-sub-1, sku-consumable-1, sku-dur-1, sku-dur-2, sku1, sku2). Select one or more SKUs, then tap Get Products to retrieve product details including name and price. Tap Get Purchases to query your existing purchases. To test the checkout flow, select exactly one SKU and tap Launch Checkout — after completing the flow, the purchase JSON appears in the output area. Tap Consume Purchase to consume a consumable item. Results and errors appear in the output area with errors displayed in red.

Key concepts

SDK initialization

The sample initializes the Horizon Platform SDK in MainActivity.onCreate() before setting up the Compose UI:
HorizonServiceConnection.connect(
    APPLICATION_ID, applicationContext, lifecycleScope
)

IAP API instantiation

The IapViewModel creates the IAP client with a no-argument constructor:
private val iap = Iap()
No context or application ID is needed — the IAP client reuses the connection established by HorizonServiceConnection.connect().

Paged results pattern

Retrieving products by SKU uses a three-step paged results pattern common across the SDK:
val pagedResults = iap.getProductsBySku(viewModelScope, skus)
pagedResults.fetchInitialPage().get()
val products = pagedResults.getFetchedPages()
    .firstOrNull()?.getContents() ?: emptyList()
This same pattern appears in the Leaderboards and Rich Presence samples.

State management

The sample uses an IapUiState data class exposed through StateFlow for reactive state management. All API calls run on Dispatchers.IO and update state through the immutable copy pattern:
_uiState.update {
    it.copy(isLoading = false, resultMessage = text)
}

Extend the sample

  • Use real SKUs: Replace the placeholder SKU list with product SKUs from your app’s catalog in the Meta developer dashboard.
  • Add purchase type handling: Differentiate between consumable, durable, and subscription purchases.
  • Combine with other SDK features: Integrate IAP with Leaderboards to reward purchases with leaderboard unlocks.