Back to Docs

Advanced Guide

Deeper patterns for b4xlib — custom UI, restore flows, caching, theming, and more. Read the Getting Started guide first.

Platform setup

Android — Manifest

Add the Google Play Billing library to your manifest (Project → Edit Manifest):

CreateResourceFromFile(Macro, GooglePlayBilling.GooglePlayBilling)

iOS — Provisioning Profile

Your provisioning profile must be based on an explicit (non-wildcard) App ID. In the Apple Developer Portal, create an explicit App ID (e.g. com.yourcompany.yourapp, not com.yourcompany.*) and generate a provisioning profile for it. In-App Purchase is included automatically.

Add provisioning profile before b4xlib

The b4xlib references the iStore library, so your B4i project will not compile without a valid provisioning profile based on an explicit (non-wildcard) App ID. Set up the profile first, then add the b4xlib.

Direct purchase (custom UI)

If you want your own purchase UI instead of the built-in screens, use PurchaseProduct or PurchaseSubscription directly. A processing overlay is shown automatically during validation.

' One-time purchase
Wait For (PurchaseManager.PurchaseProduct("premium_unlock")) Complete (Success As Boolean)

If Success Then
    Log("Purchase successful")
End If
' Subscription
Wait For (PurchaseManager.PurchaseSubscription("premium_monthly", "monthly-plan")) Complete (Success As Boolean)

If Success Then
    Log("Subscription activated")
End If

Restore purchases

Apple requires a Restore button. You can restore both purchases and subscriptions:

' Try purchases first
Wait For (PurchaseManager.RestorePurchases) Complete (Success As Boolean)

If Success Then
    Log("Purchase restored")
    Return
End If

' Then try subscriptions
Wait For (PurchaseManager.RestoreSubscriptions) Complete (Success As Boolean)

If Success Then
    Log("Subscription restored")
Else
    Log("Nothing to restore")
End If

Caching & validation

CheckStatus reads from the local cache instantly. If the cache has expired, a background server validation is triggered automatically — your UI is never blocked.

Cache expiry intervals

New purchases (first 14 days) — re-validated every 24 hours

Established purchases (after 14 days) — re-validated every 14 days

Active subscriptions — re-validated every 24 hours

No purchase history — no automatic checks (zero API calls)

To force an immediate live validation (bypasses cache, costs 1 credit):

Wait For (PurchaseManager.ValidateNow) Complete (Success As Boolean)

If Success Then
    PurchaseManager.CheckStatus  ' Refresh from updated cache
End If

Only use ValidateNow for manual "Refresh Status" buttons or debugging — let the automatic system handle routine checks.

Consumables

Consumables are tracked locally on-device. If you need cross-device support, sync with your own server using SetConsumableCount.

' Register a consumable product
PurchaseManager.AddConsumableProduct("coin_pack", "50 Coins", "A pack of 50 coins")

' After successful purchase, credit the consumables
Wait For (PurchaseManager.ShowInAppPurchase) Complete (Success As Boolean)
If Success Then
    PurchaseManager.AddConsumables(50)
End If

' Use consumables
If PurchaseManager.UseConsumables(1) Then
    Log("Used 1 coin")
Else
    Log("Not enough coins")
End If

' Check balance
Log("Coins: " & PurchaseManager.GetConsumableCount)

' Sync from your own server (e.g. on app launch)
PurchaseManager.SetConsumableCount(serverCount)

Theme customization

The built-in purchase and subscription screens support light and dark themes, plus custom colors.

' Dark mode
PurchaseManager.DarkMode = True

' Custom colors: Primary, Secondary, Accent, Background1, Background2
' Pass 0 for any color to keep the default
' Hex literals
PurchaseManager.SetThemeColors(0xFF6366F1, 0xFF8B5CF6, 0xFFEC4899, 0xFFFFFFFF, 0xFFF5F5F7)
' Or xui.Color_RGB
PurchaseManager.SetThemeColors(xui.Color_RGB(99, 102, 241), xui.Color_RGB(139, 92, 246), xui.Color_RGB(236, 72, 153), xui.Color_RGB(255, 255, 255), xui.Color_RGB(245, 245, 247))

Primary — buttons, title gradient start, feature icons

Secondary — button gradient end, title gradient end

Accent — title text gradient end color

Background1 / Background2 — screen background gradient

Custom privacy policy & terms

By default the library uses built-in templates. You can replace them with a URL or raw HTML — the library auto-detects which you're using.

' URL-based (recommended — update without resubmitting your app)
PurchaseManager.CustomPrivacyPolicyInapp = "https://myapp.com/privacy.html"
PurchaseManager.CustomTermsOfService = "https://myapp.com/terms.html"

' HTML-based (for offline apps)
PurchaseManager.CustomPrivacyPolicyInapp = File.ReadString(File.DirAssets, "privacy.html")

' You can mix and match
PurchaseManager.CustomPrivacyPolicySubscription = "https://myapp.com/privacy-sub.html"
PurchaseManager.CustomTermsOfService = File.ReadString(File.DirAssets, "terms.html")

To export the built-in templates as a starting point (debug builds only). The full HTML is logged directly to the B4X IDE log as a single copyable line — right-click → Copy Line → paste into your editor or LLM for instant customization:

PurchaseManager.ExportPrivacyPolicyInapp
PurchaseManager.ExportPrivacyPolicySubscription
PurchaseManager.ExportTermsOfService
' HTML is logged to the IDE log as a single line
' Right-click the HTML line → Copy Line → paste into editor or LLM
' Also saved to device directory as .html files

Back button handling

If a purchase or subscription screen is showing, intercept the back button to close it instead of leaving the page:

Sub B4XPage_CloseRequest As ResumableSub
    If PurchaseManager.IsActive Then
        PurchaseManager.HidePurchaseScreen
        Return False  ' Don't close the page
    End If
    Return True
End Sub

Resetting purchases for testing

During development you can reset purchases to test the flow again:

' Reset a one-time purchase
Wait For (PurchaseManager.ResetPurchaseForTesting("premium_unlock")) Complete (Success As Boolean)

' Reset a subscription
Wait For (PurchaseManager.ResetSubscriptionForTesting("premium_monthly")) Complete (Success As Boolean)

Android — consumes the purchase token so you can buy again

iOS— clears local cache only (Apple doesn't allow removing sandbox purchases). Use multiple sandbox accounts, or go to Settings → App Store → Sandbox Account → Clear Purchase History.