Docs contentsYaliyomo ya nyaraka

Quick start: Android

Add the Kotlin SDK, start it with your licence, run a verification from CameraX frames and send the result to your backend.

The Android SDK (tz.co.digid.sdk) is a Kotlin library over the digid engine. It gives you the engine, a CameraX analyzer and typed results; you build the screens. If you want ready-made screens in a native Android app, the Flutter flow can be embedded with Flutter's add-to-app: see Quick start: Flutter.

1. Add the SDK

The SDK is an Android library (AAR) in two variants:

  • bundled: the models are packed into the library. Start with this one.
  • nomodels: no models inside; you supply them from a directory (for example, downloaded with Play Asset Delivery).

Customers get the library from the customer portal: see Get the SDK. It needs minSdk 24 and Java 17, and the analyzer needs androidx.camera:camera-core in your app. The SDK has no network code and requests no permissions; your app asks for android.permission.CAMERA.

2. Start the engine with your licence

Create one engine per process, off the main thread (loading the models takes a second or more):

import tz.co.digid.sdk.*

val digid = Digid.create(context)              // models from the bundled variant
val status = digid.applyLicence(licenceToken)  // checked offline, never throws
if (status.isEvaluation) Log.w("digid", "evaluation mode: ${status.reason}")

The licence is checked against your app's package name and signing certificate, read from the running app. Without a valid licence the engine runs in evaluation mode. See Licences and renewal.

3. Run a verification

Open a session per attempt and feed it camera frames. NidaFrameAnalyzer converts CameraX frames and pushes them in:

val session = digid.newSession(Flow.CardThenSelfie(requireBack = false))

val analysis = ImageAnalysis.Builder()
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
    .build()

analysis.setAnalyzer(executor, NidaFrameAnalyzer(session, mirrored = false) { update ->
    runOnUiThread {
        guidanceText.text = Digid.guidanceText(update.guidance, Lang.EN)
        if (update.step == StepKind.SELFIE) switchToFrontCamera() // rebind with mirrored = true
    }
    update.result?.let { result -> onVerified(result, session.finishJson()) }
})
  • Use Flow.CardOnly() to read the card without a selfie.
  • When the step becomes SELFIE, switch to the front camera and create the analyzer with mirrored = true.
  • Digid.guidanceText gives the English or Swahili line for every guidance code.
  • digid.readCardImage(NidaImage.fromBitmap(bitmap)) reads a card from one photo instead of the camera.

More on sessions, steps and guidance: Custom screens on the engine.

4. Read the result

result is a KycResult:

when (result.overall) {
    Overall.PASS -> showDone()
    Overall.REVIEW -> showPendingReview()
    else -> showRetry()
}

result.evaluation is true without a valid licence. result.checks lists every check, and result.face holds the face match verdict.

5. Send the result to your backend

session.finishJson() returns the engine's result as JSON text, the same JSON every digid SDK produces. Send it as it is over your own authenticated connection:

val request = Request.Builder()
    .url("https://api.example.co.tz/kyc")
    .post(resultJson.toRequestBody("application/json".toMediaType()))
    .build()

The digid.kyc/1 document, with its tamper check, is built by the Flutter and Web SDKs. The native Android SDK hands you the engine result JSON, which carries the same card fields, checks, verdict and face match. Your backend should still apply the checks in Verify on your backend that do not depend on the document's tamper check.

6. Report usage

digid.usageSender = UsageSender { report -> postJson("https://digid.co.tz/api/v1/usage", """{"report":"$report"}""") }
digid.setUsageStore(myStore) // keeps the counts across restarts
digid.online()               // blocking: call off the main thread when the app is online

See Licences and renewal for the store, renewal and the "no report, no renewal" rule.