Skip to main content

Kotlin Multiplatform

What is RevenueCat?

RevenueCat provides a backend and a wrapper around StoreKit and Google Play Billing to make implementing in-app purchases and subscriptions easy. With our SDK, you can build and manage your app business on any platform without having to maintain IAP infrastructure. You can read more about how RevenueCat fits into your app or you can sign up free to start building.

Requirements

Android 5.0+ (API 21+)
iOS 13.0+

Installation

Adding the dependency

Purchases for Kotlin Multiplatform (Google Play and iOS App Store) is available on Maven Central and can be included via Gradle.

Release

Add the following coordinates to your libs.versions.toml.

[versions] 
purchases-kmp = "1.0.0+13.2.0"

[libraries]
# Required
purchases-core = { module = "com.revenuecat.purchases:purchases-kmp-core", version.ref = "purchases-kmp" }
# Optional: adds extension properties representing timestamps as kotlinx-datetime Instants.
purchases-datetime = { module = "com.revenuecat.purchases:purchases-kmp-datetime", version.ref = "purchases-kmp" }
# Optional: adds suspending functions that return Arrow's Either to indicate success / failure.
purchases-either = { module = "com.revenuecat.purchases:purchases-kmp-either", version.ref = "purchases-kmp" }
# Optional: adds suspending functions that return kotlin.Result to indicate success / failure.
purchases-result = { module = "com.revenuecat.purchases:purchases-kmp-result", version.ref = "purchases-kmp" }

You can now add the dependency to your commonMain source set in your module's build.gradle.kts.

kotlin {
// ...
sourceSets {
// ...
commonMain.dependencies {
// Add the purchases-kmp dependencies.
implementation(libs.purchases.core)
implementation(libs.purchases.datetime) // Optional
implementation(libs.purchases.either) // Optional
implementation(libs.purchases.result) // Optional
}
}
}

Opt in to ExperimentalForeignApi

Since the SDK uses generated Kotlin bindings for native code on iOS, you will need to opt in to ExperimentalForeignApi in your iOS source sets. To do so, add the following to your module's build.gradle.kts.

kotlin {
// ...
sourceSets {
// ...
named { it.lowercase().startsWith("ios") }.configureEach {
languageSettings {
optIn("kotlinx.cinterop.ExperimentalForeignApi")
}
}
}
}

Since the SDK depends on a native RevenueCat iOS framework, PurchasesHybridCommon, this will need to be linked to your existing iOS project. The approach depends on how you currently integrate your existing Kotlin Multiplatform code with your iOS project.

1. Directly as a local iOS framework

Follow these instructions if your Kotlin Multiplatform module is integrated directly with your iOS project as a local iOS framework. That is, Xcode is calling the embedAndSignAppleFrameworkForXcode Gradle task (or the old packForXcode task) as part of the build. At the time of writing, if you generated your Kotlin Multiplatform project using the online wizard, this is how it's set up.

In this scenario, you need to manually link the transitive dependency on PurchasesHybridCommon. One way to do so is using CocoaPods. This is useful if you're already using CocoaPods in your iOS app for dependencies other than your own Kotlin Multipatform module.

Add the following to your Podfile:

# This version must be equal to everything after the '+' in the purchases-kmp version.
pod 'PurchasesHybridCommon', '13.2.0'

2. Using Cocoapods

Follow these instructions if your Kotlin Multiplatform module is integrated with your iOS project using CocoaPods. That is, you've applied the kotlin("native.cocoapods") Gradle plugin, and set it up such that the Podfile specifies a dependency on your Kotlin Multiplatform module. (See also the Kotlin docs.)

In this scenario, you can specify the transitive dependency on PurchasesHybridCommon using Gradle. To do so, add the following to your libs.versions.toml:

[versions] 
# This version must be equal to everything after the '+' in the purchases-kmp version.
purchases-common = "13.2.0"

Now you can add the following to your module's build.gradle.kts:

kotlin {
// ...
cocoapods {
// Your existing Cocoapods options are here.

// Add the PurchasesHybridCommon dependency.
pod("PurchasesHybridCommon") {
version = libs.versions.purchases.common.get()
extraOpts += listOf("-compiler-option", "-fmodules")
}
}
}

Import Purchases

You should now be able to import Purchases.

import com.revenuecat.purchases.kmp.CustomerInfo
import com.revenuecat.purchases.kmp.Entitlement
import com.revenuecat.purchases.kmp.Offering
import com.revenuecat.purchases.kmp.Purchases
import com.revenuecat.purchases.kmp.models.Period
import com.revenuecat.purchases.kmp.models.Price
import com.revenuecat.purchases.kmp.models.StoreProduct
⚠️

On Android, Purchases uses AndroidX App Startup under the hood. Make sure you have not removed the androidx.startup.InitializationProvider completely in your manifest. If you need to remove specific initializers, such as androidx.work.WorkManagerInitializer, set tools:node="merge" on the provider, and tools:node="remove" on the meta-data of the initializer you want to remove.

 <provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>

Next Steps