Skip to main content
Version: v0.13 (Latest)

Sample Applications

We provide two sample applications demonstrating integration with the Kiwa eLicense Holder SDK. Each sample targets different use cases and demonstrates the SDK's flexibility.

Not for Production Use

These sample applications are provided for demonstration and learning purposes only. They are not intended to be used as production-ready templates. The samples prioritize clarity and simplicity over security hardening, error handling, and production best practices. Always implement proper security measures, input validation, and error handling when building production applications.

Sample AppPlatformsLanguageUse Case
Compose MultiplatformAndroid + iOSKotlin (KMP)Full-featured cross-platform apps
Swift SimpleiOS onlySwiftNative iOS apps, simple integrations
note

Both sample apps depend on the Kiwa eLicense Holder SDK, which is proprietary. See the Installation Guide for SDK setup instructions.

Compose Multiplatform App

The Compose Multiplatform sample demonstrates a full-featured e-license wallet application built with Kotlin Multiplatform (KMP). It shares business logic and UI code between Android and iOS while providing platform-native experiences.

Features

  • License Retrieval: Assigning and issuing licenses from Kiwa APIs
  • License Display: Rendering license data in a user-friendly format
  • License Verification: Validating license authenticity and validity
  • NFC Engagement: Presenting licenses via Near Field Communication
  • QR Code Engagement: Initiating verification sessions via QR codes
  • BLE Transfer: Transferring license data over Bluetooth Low Energy

Screenshots (Android)

License List

License List

License Details

License Details

Log View

Log View

QR Engagement

QR Engagement

NFC Engagement

NFC Engagement

Architecture

The Compose Multiplatform app uses:

  • Kotlin Multiplatform (KMP): Shared business logic across Android and iOS
  • Jetpack Compose / Compose Multiplatform: Shared UI components
  • Kotlin Inject + Anvil: Compile-time dependency injection
  • MVP with Molecule: Presenter framework for reactive state management
  • SKIE: Enhanced Swift interoperability for iOS

Project Structure

Located at example/holder/compose-sample-app/ in the kiwa-sample repository:

example/holder/compose-sample-app/
├── composeApp/ # Main KMP Compose module
│ └── src/
│ ├── commonMain/ # Shared code
│ ├── androidMain/ # Android-specific code
│ └── iosMain/ # iOS-specific code (Kotlin)
└── iosApp/ # iOS Xcode wrapper (minimal Swift)

example/holder/ui/ # Shared UI modules
├── auth/ # Authentication UI
├── card/ # Credential display
├── core/ # Core UI components
└── elicense/ # eLicense features

Prerequisites

  • Kiwa SDK Access: Nexus credentials for the Kiwa SDK repositories
  • Subscription Key: A valid KIWA_SUBSCRIPTION_KEY from Kiwa
  • Android Studio with Kotlin Multiplatform plugin
  • Xcode 15+ (for iOS builds)
  • Physical Device (recommended): For NFC and BLE testing

Building and Running

Clone the Repository

git clone https://github.com/Sphereon-Opensource/kiwa-sample.git
cd kiwa-sample

Configure Credentials

Create or update local.properties with your Nexus credentials:

nexusUsername=YOUR_NEXUS_USERNAME
nexusPassword=YOUR_NEXUS_PASSWORD

Set your subscription key via environment variable:

export KIWA_SUBSCRIPTION_KEY=your_subscription_key_here

Build for Android

./gradlew :example:holder:compose-sample-app:composeApp:assembleDebug

Build for iOS

First build the shared framework, then open the Xcode project:

./gradlew :example:holder:compose-sample-app:composeApp:linkDebugFrameworkIosSimulatorArm64
open example/holder/compose-sample-app/iosApp/iosApp.xcodeproj
warning

NFC and BLE features require a physical device. Engagement and presentation features will not work on emulators/simulators.


Swift Simple App

The Swift Simple sample demonstrates how to use the Kiwa SDK from native Swift code. Unlike the Compose app which uses Kotlin Multiplatform, this app uses the pre-built KiwaSdk.xcframework directly from Swift, making it ideal for teams working in pure Swift environments.

Features

  • License Activation: 8-digit PIN entry to activate licenses
  • License Storage: Local persistence of activated licenses
  • License Display: View license details including mDoc data (CBOR decoded)
  • User Onboarding: Email collection for user identification

Screenshots (iOS)

PIN Entry

PIN Entry

Activating License

Activating License

License Activated

License Activated

My Licenses

My Licenses

License Details

License Details (mDoc)

Architecture

The Swift Simple app uses:

  • Pure Swift: Native iOS development with SwiftUI
  • KiwaSdk.xcframework: Pre-built framework from the xcframework project
  • Apple Keychain: Secure key storage via Keychain Services
  • UserDefaults: Simple data persistence

Project Structure

Located at example/holder/swift-sample-app/ in the kiwa-sample repository:

example/holder/swift-sample-app/
├── kiwa-swift-sample.xcodeproj/ # Xcode project
├── kiwa-swift-sample/ # Main app source
│ ├── KiwaSwiftSampleApp.swift # App entry point
│ ├── KiwaManager.swift # SDK initialization and management
│ ├── OnboardingView.swift # First-launch email collection
│ ├── LicenseListView.swift # Main screen with stored licenses
│ ├── LicenseStore.swift # License persistence and CBOR decoding
│ ├── PinEntryView.swift # PIN entry for license activation
│ └── UserPreferences.swift # UserDefaults wrapper
└── kiwa-swift-sample.entitlements # Keychain entitlements

Prerequisites

  • Xcode 16.2 or later
  • iOS 18.2+ deployment target
  • KiwaSdk.xcframework (built from the xcframework project or downloaded from Nexus)
  • Kiwa SDK Access: Valid subscription credentials

SDK Framework Setup

Before building the Swift app, you need the KiwaSdk.xcframework. See the iOS Installation Guide for detailed instructions on:

  • Installing via CocoaPods
  • Direct XCFramework download from Nexus
  • Building the XCFramework from source

Building and Running

Open in Xcode

cd example/holder/swift-sample-app
open kiwa-swift-sample.xcodeproj

Build via Command Line

xcodebuild -project kiwa-swift-sample.xcodeproj \
-scheme kiwa-swift-sample build \
-destination 'platform=iOS Simulator,name=iPhone 16'

SDK Integration Pattern

The Swift Simple app demonstrates a clean SDK integration pattern:

import KiwaSdk

class KiwaManager: ObservableObject {
let appComponent: KiwaSdkAppComponentMerged

init() {
// 1. Configure KMS (Key Management Service) properties
DefaultPrincipalMapPropertySource.shared.addProperties(map: [
"test.app.testing.kms.providers.kiwa.id": "kiwa",
"test.app.testing.kms.providers.kiwa.type": "software",
"test.app.testing.kms.providers.kiwa.autocreatecertificate": "true",
"test.app.testing.kms.providers.kiwa.keystore.id": "kiwa",
"test.app.testing.kms.providers.kiwa.keystore.type": "apple",
"test.app.testing.kms.providers.kiwa.keystore.keyvisibility": "public",
"test.app.testing.kms.providers.kiwa.keystore.overwritealias": "true",
])

// 2. Configure tenant/API environment
DefaultTenantMapPropertySource.shared.addProperties(map: [
"kiwa.api.environment": "acceptance",
"kiwa.subscription.key.acc": "your-subscription-key",
])

// 3. Initialize SDK app component
let application = UIApplication.shared
self.appComponent = KiwaSdkAppComponent.companion.doInit(
application: application,
appId: "my-app",
profile: "testing",
version: "1.0.0"
)
}

func setupUserContext(email: String) {
// 4. Create user context from email
let tenant = extractDomain(from: email)
let userInstance = appComponent.userContextManager.createOrGetFromInputs(
tenantInput: DefaultTenantInputString(tenant: tenant),
principalInput: DefaultPrincipalInputString(principal: email),
makeActive: true
)

// 5. Create session for API access
let sessionInstance = userInstance?.sessionContextManager.createOrGetFromId(
sessionId: "main-session",
makeActive: true
)

// 6. Access Kiwa services
let kiwaServices = sessionInstance?.getKiwaServices()
}
}

License Activation Flow

The app demonstrates the complete license activation flow:

  1. Get Wallet Certificate - Request mTLS certificate for secure communication
  2. Assign License - Associate license with user using activation code + email
  3. Confirm License - Verify assignment was successful
  4. Issue License - Download the license and decode CBOR response
  5. Store License - Persist locally for offline access

Comparison: When to Use Which

CriteriaCompose MultiplatformSwift Simple
Target platformsAndroid + iOSiOS only
Team expertiseKotlin/KMPSwift
Code sharingShared business logic + UIiOS only
Build complexityHigher (Gradle + Xcode)Lower (Xcode only)
Startup timeSlower (KMP init)Faster (native)
NFC/BLE supportBuilt-inManual implementation
Best forProduction cross-platform appsSimple iOS integrations, prototypes

Source Code

Both sample applications are available on GitHub:

Repository: github.com/Sphereon-Opensource/kiwa-sample

SamplePath in Repository
Compose Multiplatformexample/holder/compose-sample-app/
Swift Simpleexample/holder/swift-sample-app/
XCFramework buildexample/holder/xcframework/

The sample app code is released under the Apache 2.0 License, allowing you to use it as a reference for your own implementations.

Troubleshooting

Build Failures

  • Verify Nexus credentials are correct
  • Ensure you have SDK access permissions
  • Check for network connectivity to Nexus

Runtime Errors

  • Verify KIWA_SUBSCRIPTION_KEY is set (Compose app)
  • Check you're using the correct environment (DEV/TEST/ACC/PROD)
  • Review logs for detailed error messages

NFC/BLE Issues

  • Enable NFC and Bluetooth in device settings
  • Grant required permissions when prompted
  • Use a physical device, not an emulator/simulator

Swift App: Framework Not Found

  • Ensure KiwaSdk.xcframework is properly linked
  • Check "Embed & Sign" is selected in build settings
  • Clean build folder and rebuild

Next Steps

After exploring the sample apps:

  1. Review the Getting Started Guide
  2. Study the Holder Functions for API details
  3. Check Installation for integration options
  4. Explore the API Reference