Integration Guide

PAK OCR SDK for Android (Kotlin)

A drop-in, fully on-device CNIC scanning SDK. Add one Gradle dependency, activate with a license key, and start scanning — no server round-trip is needed for the scan itself.

Latest version: 1.0.0 View release notes →

1 Get a license key

Every integration is bound to a license key + your app's package name. Register an account, then create a license key from your dashboard.

Create a free account or log in to generate a license key for your app's package name.

2 Add the SDK to your project

Add the PAK OCR Maven repo to your project, then add the SDK as a dependency.

settings.gradle.kts

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://pakocr.itcians.com/maven") }
    }
}

app/build.gradle.kts

dependencies {
    implementation("com.itcians.ocrsdk:ocrsdk:{{ LATEST_VERSION }}")

    // or always pick up the newest published release automatically:
    // implementation("com.itcians.ocrsdk:ocrsdk:+")
}

Replace {{ LATEST_VERSION }} with 1.0.0 (the current latest), or check GET https://pakocr.itcians.com/v1/sdk/releases/latest at build time.

3 Initialize the SDK

Call initialize() once at app startup (e.g. in your Application class or splash screen). This activates your license key against your app's package name and caches an entitlement token on-device.

import com.itcians.ocrsdk.CnicScanner
import com.itcians.ocrsdk.LicenseException

class App : Application() {
    override fun onCreate() {
        super.onCreate()

        CnicScanner.initialize(
            context = this,
            licenseKey = "PK-XXXX-XXXX-XXXX" // from your dashboard
        ) { result ->
            result.onSuccess {
                // Entitlement cached. Safe to call prepareModels() now.
                CnicScanner.prepareModels(this) { progress ->
                    // progress: Float in 0f..1f while eng/urd packs download
                }
            }.onFailure { error ->
                when (error) {
                    is LicenseException -> when (error.reason) {
                        LicenseException.Reason.INVALID -> { /* key/package mismatch */ }
                        LicenseException.Reason.EXPIRED -> { /* subscription lapsed */ }
                        LicenseException.Reason.REVOKED -> { /* key disabled */ }
                        LicenseException.Reason.QUOTA_EXCEEDED -> { /* device limit hit */ }
                        LicenseException.Reason.SERVER -> { /* unexpected server error */ }
                    }
                    else -> { /* network error — cached token used if within grace window */ }
                }
            }
        }
    }
}

Notes

  • initialize() is not called on every app start — the SDK reuses a cached entitlement token until it expires (~24h).
  • The license key is bound to your app's package name (applicationId). Activating from a different package returns INVALID.
  • If your server is unreachable, a cached token still works inside its grace window (default 72h past expiry).

4 Launch a scan

Once models are prepared, launch the built-in scan UI via the ScanContract activity result API and read the result.

import com.itcians.ocrsdk.ScanContract
import com.itcians.ocrsdk.ScanResult

class MainActivity : AppCompatActivity() {

    private val scanLauncher = registerForActivityResult(ScanContract()) { result ->
        when (result) {
            is ScanResult.Success -> {
                val cnic = result.data
                // cnic.name, cnic.cnicNumber, cnic.dateOfBirth, cnic.dateOfExpiry, ...
            }
            is ScanResult.Failed -> {
                // result.reason — engine/camera failure, unreadable card, etc.
            }
            is ScanResult.Cancelled -> {
                // user pressed back / closed the camera
            }
        }
    }

    private fun startScan() {
        scanLauncher.launch(Unit)
    }
}

5 Telemetry

The SDK automatically reports daily scan counts (success / failed / cancelled) back to your dashboard via a background worker — no integration work required. Per-license usage is visible on your dashboard.

Error reference

Reason Cause What to do
INVALID Unknown key, or key not registered for this package name Check the key and applicationId match what's on your dashboard
EXPIRED Subscription / plan has lapsed Renew or switch plans from your dashboard
REVOKED Key disabled server-side Generate a new license key
QUOTA_EXCEEDED Device/activation limit reached for this key Each key activates on one device; create another key for additional devices
SERVER Unexpected 4xx/5xx from the activation endpoint Retry — the SDK falls back to a cached token if available

Need help?

Check release notes for version-specific integration notes and breaking changes.

View Release Notes