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.
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 returnsINVALID. - 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.