Demo

Setup

To run the demo app, you need to get the project and configure your API credentials:

Get the Demo Project
Open the Project in Android Studio
  • Open Android Studio
  • Select File > Open
  • Navigate to the koard-android folder and open it
  • Wait for Gradle sync to complete

The koard-android repository is fully standalone—no parent project or linked modules required. The demo app is the root Gradle module, and the SDK itself resolves from Maven Central as com.koard.

Configure Your Credentials

Open build.gradle.kts and set your API key for each build flavor via the API_KEY buildConfigField. The flavor's ENVIRONMENT field selects the matching KoardEnvironment at startup:

android {
    flavorDimensions += "environment"

    productFlavors {
        create("uat") {
            dimension = "environment"
            isDefault = true
            buildConfigField("String", "ENVIRONMENT", "\"UAT\"")
            buildConfigField("String", "API_KEY", "\"YOUR_API_KEY\"")
            applicationIdSuffix = ".uat"
        }
        create("prod") {
            dimension = "environment"
            buildConfigField("String", "ENVIRONMENT", "\"PROD\"")
            buildConfigField("String", "API_KEY", "\"YOUR_API_KEY\"")
        }
    }
}

Replace YOUR_API_KEY with your Koard API key.

The merchant code and PIN are not build config values — you enter them on the demo's login screen at runtime, where they are passed to sdk.login(merchantCode, merchantPin). The active location is selected in-app after login.

Important: For production use, externalize these credentials using secure storage or environment variables. Never commit actual credentials to version control.

Select Build Flavor

The demo app has two build flavors:

Flavor API Environment Application ID Suffix
uat UAT/Testing (default) .uat
prod Production (none)

In Android Studio:

  • Go to Build > Select Build Variant
  • Choose your desired flavor (e.g., uatDebug for testing)

There is no dev flavor. To point the demo at a development backend, switch the SDK to KoardEnvironment.Custom(...) in DemoApplication.

Build the Project

Build the project using one of these methods:

Via Android Studio:

  • Click Build > Make Project (⌘+F9 / Ctrl+F9)

Via Command Line:

# Build UAT flavor
./gradlew assembleUatDebug

# Build production flavor
./gradlew assembleProdRelease
Install on Physical Device

Physical Device Required: Tap to Pay on Android requires a physical device with NFC hardware. The emulator does not support NFC payments.

Prerequisites:

  • Physical Android device with NFC support (Android 12+)
  • Tap-to-pay kernel app installed on the device (see the Running Payments guide)
  • USB debugging enabled on the device

Install the app:

Via Android Studio:

  • Connect your device via USB
  • Click Run > Run 'app' (Shift+F10)

Via Command Line:

# Install UAT build
./gradlew installUatDebug

# Install production build
./gradlew installProdRelease

Running the Demo

Launch the App

Open the Koard Demo app on your device. You should see the main screen.

Authenticate Merchant

Enter your merchant code and PIN on the login screen — these are entered at runtime, not baked into the build — and submit. The demo calls sdk.login(merchantCode, merchantPin).

You will know authentication was successful if you see:

  • The app navigates past the login screen
  • The location selector and enrollment panel become available
Select Location

Tap the location selector in the top bar and choose your active location. The demo calls sdk.setActiveLocation(location.id) with your choice.

The selected location is used for all transactions, and enrollment cannot proceed without it.

Enroll the Device

Enrollment is not automatic. Nothing enrolls as a side effect of logging in or picking a location — you must press the button. Until enrollment completes, the demo's home screen shows the enrollment panel instead of the transaction form, and any tap API would throw KoardErrorType.NotReady.NotEnrolled.

While readinessState.enrollmentState is anything other than Enrolled, the demo's home screen renders an enrollment panel in place of the transaction form. Press Enroll Device to run sdk.enrollDevice().

Under the hood the demo:

  1. Checks the tap-to-pay kernel app is installed via sdk.isKernelAppInstalled(), and surfaces "Visa Kernel app is not installed." if it isn't
  2. Calls sdk.enrollDevice(), which generates device certificates and enrolls the device with Koard's payment services
  3. Treats the returned String as an error message if it contains "failed" or "error", and catches KoardException for typed failures

You will know enrollment was successful if you see:

  • The enrollment panel is replaced by the transaction form
  • readinessState.enrollmentState becomes Enrolled and the reader status banner clears
  • NFC transactions can be initiated

Enrollment is rejected outright if developer mode is on, if no active location is set, or if the device is already enrolled. To re-enroll, use Unenroll Device on the Settings screen (which calls sdk.unenrollDevice()) first.

Disable Developer Mode

IMPORTANT: Turn Off Developer Mode

Before processing any tap to pay transactions, you MUST disable developer mode on your Android device:

  1. Go to Settings > System > Developer Options
  2. Toggle Developer Mode to OFF
  3. Restart your device (recommended)

Tap to Pay transactions will fail if developer mode is enabled. This is a security requirement from the payment processor.

Developer Workflow:

  • Enable Developer Mode → Install/update app → Disable Developer Mode → Run transactions
Process Sample Transaction

Test a contactless payment:

  1. Tap Process Transaction or New Payment
  2. Enter a sample dollar amount (e.g., $10.00)
  3. Select transaction type (Sale or Preauth)
  4. Tap Start or Continue
Complete Tap to Pay Transaction

Complete the payment flow:

  1. Prompt the customer to tap their card or phone
  2. Hold the card/phone against the device's NFC reader
  3. Wait for the transaction to process
  4. View the transaction result (approved/declined)

Transaction details will include:

  • Transaction ID
  • Authorization code
  • Card type and last 4 digits
  • Amount charged
  • Transaction status
View Transaction History

Navigate to Transaction History to:

  • View all completed transactions
  • Filter by date or status
  • View detailed transaction information
  • Send receipts via email or SMS

Demo App Features

The demo app showcases the following SDK capabilities:

Merchant Authentication

  • Login with merchant code and PIN
  • Session management
  • Automatic token refresh

Device Enrollment

  • NFC configuration with Koard's tap-to-pay services
  • Certificate management
  • Device provisioning status

Location Management

  • Retrieve all merchant locations
  • Select active location
  • Location-based transaction processing

Transaction Processing

  • Sale transactions (immediate capture)
  • Preauthorization (auth hold)
  • Capture (settle preauth)
  • Refund processing
  • Transaction reversal
  • Tip adjustment

Transaction History

  • List all transactions
  • View transaction details
  • Filter and search
  • Transaction status tracking

Digital Receipts

  • Send receipts via email
  • Send receipts via SMS
  • Receipt customization

Project Structure

The demo app structure:

koard-android/
├── src/
│   └── main/
│       ├── java/com/koard/android/
│       │   ├── DemoApplication.kt          # SDK initialization
│       │   ├── MainActivity.kt             # NFC register/unregister in onResume/onPause
│       │   ├── navigation/                 # Tab navigation (History, Home, Settings)
│       │   └── ui/
│       │       ├── LoginScreen.kt / LoginViewModel.kt
│       │       ├── MainScreen.kt / MainScreenViewModel.kt
│       │       ├── SettingsScreen.kt
│       │       ├── TransactionDetailsScreen.kt
│       │       └── TransactionHistoryScreen.kt
│       ├── res/
│       │   └── xml/nfc_tech_filter.xml     # IsoDep tech filter for TECH_DISCOVERED
│       └── AndroidManifest.xml
├── build.gradle.kts                # Build configuration + SDK coordinate
├── settings.gradle.kts             # google() + mavenCentral() only
└── README.md

SDK Integration

The demo resolves the SDK straight from Maven Central — there is no bundled AAR and no local repository to configure:

// build.gradle.kts
implementation("com.koard:koard-android-sdk:1.0.6")

The published artifact is a shaded fat AAR: it bundles the tap-to-pay engine (KiC) and relocates OkHttp, Okio, Retrofit, kotlinx.serialization, and Ktor under com.koardlabs.*, so those never clash with your app's own versions. It also means they are not transitive dependencies — see Installing the SDK for what you must declare yourself.

The environment (UAT vs. PROD) is chosen at runtime from the flavor's ENVIRONMENT buildConfigField, not by swapping artifacts:

  • UAT buildsKoardEnvironment.UAT
  • Prod buildsKoardEnvironment.PROD

How the Demo Initializes the SDK

DemoApplication.onCreate() maps BuildConfig.ENVIRONMENT to a KoardEnvironment and initializes the SDK on a worker thread, passing the API key from BuildConfig:

val environment = when (BuildConfig.ENVIRONMENT) {
    "PROD" -> KoardEnvironment.PROD
    "UAT" -> KoardEnvironment.UAT
    else -> KoardEnvironment.UAT
}

KoardMerchantSdk.initialize(
    application = this@DemoApplication,
    apiKey = BuildConfig.API_KEY,
    environment = environment,
    timeoutSeconds = 30L
)

Merchant credentials are supplied later, on the login screen, via sdk.login(merchantCode, merchantPin).

To shave first-tap latency, you can warm the reader up after init by collecting sdk.prepare() in the background and keying off the KoardPrepareStatus.Done emission. See Running Payments for details.

Build Commands Reference

# Clean build
./gradlew clean

# Build all flavors
./gradlew build

# Build specific flavor
./gradlew assembleUatDebug
./gradlew assembleProdRelease

# Install on device
./gradlew installUatDebug
./gradlew installProdRelease

# Uninstall from device
./gradlew uninstallUatDebug
./gradlew uninstallProd

# Run tests
./gradlew test

# Generate APK
./gradlew assembleDebug
./gradlew assembleRelease

Troubleshooting

Common Issues

App crashes on startup

Solution:

  • Verify credentials are configured correctly in build.gradle.kts
  • Check that you're not using placeholder values (YOUR_API_KEY_HERE)
  • Review Logcat for specific error messages

"Device not provisioned" error

Solution:

  • Ensure the tap-to-pay kernel app is installed (see the Running Payments guide for setup steps)
  • Confirm you selected a location and then pressed Enroll Device — enrollment never runs on its own
  • Check NFC hardware is functioning
  • Verify the kernel app is up to date

NFC not working

Solution:

  • Confirm device has NFC hardware
  • Enable NFC in device settings
  • Verify device enrollment was successful
  • Test with a physical payment card
  • IMPORTANT: Ensure developer mode is DISABLED on the device

"Transaction failed" or "NFC error" during tap to pay

Solution:

  • Disable developer mode - This is the most common cause of transaction failures
  • Go to Settings > System > Developer Options and toggle OFF
  • Restart your device after disabling developer mode
  • Ensure the tap-to-pay kernel app is running and up to date
  • Check that NFC is enabled in device settings

Build errors

Solution:

  • Verify JDK 21 is configured
  • Check minimum SDK is set to 31
  • Clean and rebuild: ./gradlew clean build
  • Invalidate caches: File > Invalidate Caches / Restart

Network errors

Solution:

  • Check device has internet connection
  • Verify API key and credentials are correct
  • Ensure you're using the correct build flavor for your environment (uat/prod)

Debugging Tips

Enable verbose logging:

SDK log verbosity is set once, at initialization — there is no runtime setter. Pass a KoardLogLevel in DemoApplication.onCreate():

import com.koardlabs.merchant.sdk.domain.KoardLogLevel

KoardMerchantSdk.initialize(
    application = this@DemoApplication,
    apiKey = BuildConfig.API_KEY,
    environment = environment,
    timeoutSeconds = 30L,
    logLevel = KoardLogLevel.VERBOSE
)

Levels are VERBOSE, DEBUG, INFO, WARN, ERROR, and NONE. The default is DEBUG in debug builds and NONE in release, and the level applies in release builds too if you opt in. Secrets — API key and token headers, device certificates, and enrollment key material — are never logged at any level.

Check Logcat:

The SDK logs under the fixed tag KoardSDK:

adb logcat -s KoardSDK

Verify SDK version:

Check which SDK version the demo is using:

./gradlew dependencies | grep koard

Security Notes

  • Never commit actual credentials to version control
  • Use environment variables or secure credential management for production
  • The build.gradle.kts credentials are for demo purposes only
  • Consider using Android Keystore for sensitive data in production apps
  • Keep the demo app on devices used exclusively for testing

Updating the SDK

Updating the SDK is a one-line change — bump the Maven coordinate in build.gradle.kts and rebuild:

implementation("com.koard:koard-android-sdk:<version>")

There is no AAR to download or copy: the artifact resolves from mavenCentral(), which settings.gradle.kts already declares.

1.0.6 changed bytecode signatures (initialize, getTransactions, and sale gained defaulted parameters) and replaced the leaked Visa ButtonProperties type with KoardButtonProperties. Always do a clean rebuild after bumping the version rather than dropping a new artifact onto pre-compiled call sites.

Next Steps

After running the demo app successfully:

Support

For technical support or questions: