Kotlin quickstart
Add Voidhash to a native Android app and show your first paywall.
This guide takes an existing Android app from installation to a paywall and access check.
Requires minSdk 23, AGP 8.9.0, and Kotlin 2.0.21.
Install the SDK
The SDK ships as a Gradle module inside the npm package @voidhash/android. Add it to your build
by pointing at the installed package directory:
includeBuild("node_modules/@voidhash/android")dependencies {
implementation("com.voidhash.sdk")
}Or vendor the sources and include them directly:
include(":voidhash-core", ":voidhash-sdk")
project(":voidhash-core").projectDir = file("third_party/voidhash/core")
project(":voidhash-sdk").projectDir = file("third_party/voidhash/sdk")Add the billing permission — the SDK contributes INTERNET through its own manifest:
<uses-permission android:name="com.android.vending.BILLING" />Play Billing 8.0.0, Play Services Base, OkHttp 4.x, and kotlinx-coroutines must be on the runtime classpath.
Configure the client
Configure in your Application class with the project's publishable key:
import com.voidhash.sdk.Voidhash
import com.voidhash.sdk.VoidhashOptions
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
class App : Application() {
override fun onCreate() {
super.onCreate()
val voidhash = Voidhash.configure(
context = this,
publishableKey = "vh_pk_...",
options = VoidhashOptions(debug = BuildConfig.DEBUG),
)
ProcessLifecycleOwner.get().lifecycleScope.launch {
voidhash.initialize()
}
}
}The publishable key is safe to include in the app. Never ship vh_sk_... secret keys.
configure is synchronous and cheap; initialize() connects to Google Play, resolves the project
schema, and reconciles anything the store still reports as unfinished. It is safe to call
repeatedly — only the first successful call does work, and a failed call can be retried. The client
is also reachable as Voidhash.shared.
Configure one test offer in Studio
Create the smallest complete catalog:
- Create a perk such as
premium. - Create a product, choose its billing duration, and attach the perk.
- Create a paywall that includes the product, then publish it.
- Create a paywall location such as
onboardingand assign the published paywall.
Connect Google Play Console before testing a release build — see Store setup. See Products and perks and Paywalls for the model behind these steps.
Present the paywall
Resolve the paywall by location and present it from an activity:
voidhash.presentPaywall(activity, location = "onboarding", listener = object : PaywallListener {
override fun onPurchaseCompleted(transaction: VoidhashTransaction) = unlockPremium()
override fun onEvent(name: String, properties: Map<String, Any?>) = track(name, properties)
override fun onDismiss() = Unit
})It returns false when the backend has no published paywall for the location — fall back to your
own screen instead of leaving the customer with nothing.
The SDK presents the paywall fullscreen and speaks the paywall bridge protocol natively: purchases, restores, close, and external links are handled for you; custom events and logs are forwarded to the listener.
Check access
Gate features on an active perk grant from the person snapshot:
val person = voidhash.getCurrentPerson()
val hasPremium = person?.activePerkIds?.contains("premium") == trueThe snapshot refreshes after a successful purchase or restore. See Check access for caching behavior and failure handling.
Run a test purchase
Build and run on a device signed into an account in a Play testing track, then buy through the presented paywall. Purchases sync server-side and are acknowledged only after validation succeeds; consumables are consumed instead.