Skip to main content

Android with Kotlin

Integrate the tenant-delivered Android AAR, activate a device-bound signed license, and submit stride-safe CameraX frames.

Status
Evaluation
Integration
Embedded SDK
Distribution
Tenant download grant
Version
0.1.0-RC4
Android Kotlin SDK scan flow from barcode capture through Vision Scan processing to a verified result
The Kotlin SDK path stays focused on the customer workflow: capture a barcode, process it with Vision Scan, and render a verified result.

Prerequisites

  • Android API 26 or newer
  • JDK 17
  • An authenticated tenant and activated device
  • A tenant download grant for the RC2 evaluation ZIP

1. Install from the granted Maven repository

Install from the granted Maven repository
// settings.gradle.kts: repository extracted from the granted ZIP
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("sdk-release/maven") }
    }
}
// app/build.gradle.kts
dependencies {
    implementation("com.visionscan.sdk:vision-scan-android-sdk:0.1.0-RC4")
}

Compare the complete ZIP SHA-256 with the authenticated catalog, then extract its Maven repository. Keep the bundled OpenCV wrapper and POM dependencies; the SDK AAR alone is incomplete. Server HMAC signing keys are never customer inputs.

2. Apply the backend-signed license

Apply the backend-signed license
// Worker: IDs come from trusted authenticated enrollment, not user entry.
VisionScanSdk.initializeLeaseStore(noBackupFilesDir, deviceId)
// Requires the previously enrolled hardware installation key.
VisionScanSdk.initializeHardwareBinding(applicationContext)
val result = VisionScanSdk.applySignedLicenseJws(
    jws = signedLicenseJws,
    expectedTenantId = tenantId,
    expectedDeviceId = deviceId
)
check(result.isAllowed) { result.denialReason ?: "License denied" }

Resolve tenantId from the authenticated tenant and deviceId from device activation. Enroll the SDK hardware proof with a server-issued challenge first; then fetch the bound JWS and trusted JWKS through authenticated control-plane networking. Signed claims are verified against this enrollment context, never treated as self-authorizing decoded data. Encrypted-key-only initialization is not an RC2 API.

3. Create a live session

Create a live session
VisionScanSdk.createSession(tenantId, siteId, ScanMode.LIVE_STREAM).use { session ->
    val yPlane = YPlaneExtractor.extractYPlane(imageProxy)
    val result = session.processFrame(imageProxy.width, imageProxy.height, 1, yPlane)
    val observations = result.observations
}

Close each ImageProxy in a finally block. The full CameraX analyzer is in the Android first-scan guide.

Errors and recovery

ConditionResolution
License is deniedRefresh the signed JWS and confirm tenant, device, feature, expiry, revision, and trusted key bindings.
No observations are returnedConfirm the native bridge is packaged, use the correct scan mode, and inspect frame quality without treating an empty result as an error.

Production checklist

  • Verify the complete ZIP against the authenticated catalog SHA-256
  • Keep bearer tokens and license JWS values out of logs
  • Exercise revoked, expired, missing-feature, and offline-grace failures
  • Benchmark on the target device for the full work window

Scan modes

The three Android evaluation workflows. Mode is set on VisionSessionConfig.scanMode and paired with a frame profile; use a separate appropriately licensed session for dense rescue or batch receiving.

Android evaluation workflows
WorkflowModeProfileEntitlement
Live sweepLIVE_STREAMliveSweep()barcode-intelligence
Tap or focused rescueHIGH_DENSITY_RESCUEstillImageDense(1)multi-barcode-dense
Image batch receivingSTILL_IMAGE_BATCHstillImageDense(expectedCount)multi-barcode-dense

Mode behavior in receiving operations: Scan & Count (live-sweep dedup) · Focused Rescue (tap/focused rescue).

GS1 decode contract

Every decode flows through the same deterministic path: the real native decoder and the deterministic GS1 parser produce the observations, and the host only reads them.

Return type
VisionSession.getLatestObservations(): List<BarcodeObservation> — the immutable observations produced by the most recently accepted frame. An empty list is a valid no-decode result.
Observation fields
rawPayload, symbology, GTIN, dependent lot/expiry/serial evidence, OCR provenance, and confidence. GTIN is the primary identity; lot, expiration, and serial remain GTIN-scoped dependent evidence.
OCR rescue
isOcrRescue marks OCR-derived evidence. OCR-only GTIN or serial evidence requires review and must never auto-commit.
Malformed input
Malformed native observations fail deterministically instead of producing sample data. Native absence, malformed decoder output, entitlement denial, or an undecoded frame never produces a sample GTIN.

Public contract reference

These are the callable methods and HTTP operations used by this guide. Inputs, results, lifecycle rules, and denial behavior are part of the versioned customer contract.

Hardware enrollment proof and bound lease admission

PRXV-0132-S10: Android hardware-only installation keys, current app signers and signed lease binding. Wire contract: contracts/json/sdk-hardware-binding.schema.json. Backend attestation and atomic activation remain release gates.

VisionScanSdk.createEnrollmentProof(context: Context, challenge: VisionScanEnrollmentChallenge): VisionScanHardwareBindingProof

method

Create an app-scoped non-exportable hardware P-256 key and signed enrollment evidence.

Inputs for VisionScanSdk.createEnrollmentProof(context: Context, challenge: VisionScanEnrollmentChallenge): VisionScanHardwareBindingProof
InputTypeRequiredMeaning
contextContextYesReal application context supplies package and current signing identity.
challengeVisionScanEnrollmentChallengeYesTrusted server-issued bounded nonce and origin; no caller-generated enrollment authority.
Result
Restricted proof JSON containing public SPKI, DER signature and bounded attestation chain; never a private key.
Lifecycle
Worker only; once per approved installation. Existing keys are never overwritten; recovery requires admin approval.
Trust boundary
No networking. Server validates chain trust, revocation, app identity and challenge and consumes it atomically. Client labels are not authority; no proof in logs or telemetry.
Failure behavior
  • VisionScanBindingException.code: malformed/expired challenge, worker required, existing key, unavailable attestation or hardware key.

VisionScanSdk.createLicenseBindingProof(context: Context, challenge: VisionScanEnrollmentChallenge): VisionScanHardwareBindingProof

method

Prove possession of the existing installation key for lease renewal.

Inputs for VisionScanSdk.createLicenseBindingProof(context: Context, challenge: VisionScanEnrollmentChallenge): VisionScanHardwareBindingProof
InputTypeRequiredMeaning
contextContextYesReal application context.
challengeVisionScanEnrollmentChallengeYesFresh server challenge bound to approved origin and public license ID.
Result
Signed proof with empty attestation chain; server uses previously verified enrollment.
Lifecycle
Worker only. Missing keys never regenerate silently.
Trust boundary
Public-key hash is SHA-256 of DER SPKI, not JWK thumbprint. Renewal signature does not establish new attestation trust.
Failure behavior
  • Malformed/expired challenge, missing key or hardware provider failure fail closed.

VisionScanSdk.initializeHardwareBinding(context: Context)

method

Require signed app/signer/key matching before commercial lease admission.

Inputs for VisionScanSdk.initializeHardwareBinding(context: Context)
InputTypeRequiredMeaning
contextContextYesPlatform app context reads the existing installation key and current signers.
Result
Strict binding mode, with old process admission cleared even if setup fails.
Lifecycle
Call on a worker after lease-store initialization and before applying a bound lease. Store reinitialization retains strict mode.
Trust boundary
Legacy unconfigured hosts remain compatible. This is not an encrypted-key activation API. Unsupported Swift/C++ hosts reject bound leases rather than ignore them.
Failure behavior
  • Missing/non-hardware key rejects setup; signed binding absence/mismatch rejects admission; key loss or signer change stops feature checks.

Android license lifecycle

The host stores only a verified device-bound lease and never constructs entitlement claims.

VisionScanSdk.initializeLeaseStore(storageDir: File, hostDeviceId: String): Unit

method

Configure device-bound persistence used for offline grace and anti-rollback checks.

Inputs for VisionScanSdk.initializeLeaseStore(storageDir: File, hostDeviceId: String): Unit
InputTypeRequiredMeaning
storageDirFileYesA host-owned no-backup directory; do not use a shared or user-exportable location.
hostDeviceIdStringYesThe stable device identifier activated for the authenticated tenant.
Result
Replaces the process entitlement manager with one backed by the device-bound lease store.
Lifecycle
Call once after authenticated device enrollment and before applying or refreshing a license.
Trust boundary
Store verified leases only; bearer tokens remain in host-owned secure credential storage.
Failure behavior
  • Blank or unstable device identity prevents a durable binding.
  • Unreadable storage causes later lease persistence or offline checks to fail closed.

VisionScanSdk.refreshPaidLicense(controlPlaneOrigin, tenantId, deviceId, bearerToken): LicenseRefreshResult

method

Fetch the fixed license and JWKS routes, verify the compact JWS, persist it, and activate it for the process.

Inputs for VisionScanSdk.refreshPaidLicense(controlPlaneOrigin, tenantId, deviceId, bearerToken): LicenseRefreshResult
InputTypeRequiredMeaning
controlPlaneOriginHTTPS originYesScheme and authority only; paths, queries, fragments, cleartext HTTP, and untrusted redirects are rejected.
tenantIdStringYesThe tenant resolved from the authenticated session.
deviceIdStringYesThe already activated device bound to a reserved seat.
bearerTokenStringYesA short-lived access token kept out of source, resources, intents, and logs.
Result
LicenseRefreshResult with activated=true only after signature and claim verification succeeds.
Lifecycle
Run on an I/O worker at login, foreground, entitlement revision changes, reassignment, and before lease expiry.
Trust boundary
The client cannot select arbitrary license routes or weaken the allowlisted signing algorithms.
Failure behavior
  • Network, HTTP, JWKS, signature, claim, tenant, device, expiry, revision, and persistence failures return activated=false.
  • The method never falls back to caller-created claims.

VisionScanSdk.applySignedLicenseJws(jws, expectedTenantId, expectedDeviceId, nowEpochSeconds): EntitlementEvaluationResult

method

Verify and apply a backend-issued compact JWS already fetched by authenticated host networking.

Inputs for VisionScanSdk.applySignedLicenseJws(jws, expectedTenantId, expectedDeviceId, nowEpochSeconds): EntitlementEvaluationResult
InputTypeRequiredMeaning
jwscompact JWSYesA backend-signed license envelope; never a caller-created claims object.
expectedTenantIdStringYesThe authenticated tenant that must match the signed tenant claim.
expectedDeviceIdStringYesThe activated device that must match the signed device claim.
nowEpochSecondsLongNoCurrent Unix time; callers normally use the default and inject time only in tests.
Result
EntitlementEvaluationResult describing allow/deny state, plan, remediation, and correlation identifier.
Lifecycle
Apply before session creation and refresh when the signed lease approaches expiry or the entitlement revision changes.
Trust boundary
The legacy object-taking applySignedLicense overload is permanently fail-closed.
Failure behavior
  • Unknown key, disallowed algorithm, invalid signature, issuer/audience mismatch, invalid timestamps, wrong tenant/device, rollback revision, revocation, expiry, or offline-grace expiry deny access.

Android session and frame lifecycle

A session is a tenant-scoped, entitlement-gated, AutoCloseable native processing lifecycle.

VisionScanSdk.createSession(config: VisionSessionConfig): VisionSession

method

Create a native scanning session for one tenant, site, and execution mode.

Inputs for VisionScanSdk.createSession(config: VisionSessionConfig): VisionSession
InputTypeRequiredMeaning
config.sessionIdStringYesA non-empty identifier unique to the host workflow.
config.tenantIdStringYesMust match the cryptographically verified active license.
config.siteIdStringYesThe authenticated facility or location scope.
config.scanModeScanModeYesLIVE_STREAM, STILL_IMAGE_BATCH, or HIGH_DENSITY_RESCUE.
Result
A ready VisionSession that owns native resources and must be closed.
Lifecycle
Create after license admission; close on workflow completion, logout, or lifecycle stop.
Trust boundary
Batch and rescue modes require both barcode-intelligence and multi-barcode-dense features.
Failure behavior
  • Invalid identifiers throw IllegalArgumentException.
  • Missing, unverified, wrong-tenant, expired, revoked, or feature-incomplete entitlement throws VisionScanEntitlementDeniedException.
  • A missing native bridge throws VisionScanNativeUnavailableException.

VisionSession.submitFrame(width, height, format, buffer, profile?): Int

method

Compatibility entry point that submits one bounded luminance frame to the native pipeline, optionally with an explicit preprocessing profile.

Inputs for VisionSession.submitFrame(width, height, format, buffer, profile?): Int
InputTypeRequiredMeaning
width / heightIntYesPositive pixel dimensions matching the normalized buffer.
formatIntYesThe SDK-supported image format code; CameraX integrations submit extracted luminance.
bufferByteArrayYesA stride-correct frame. Use YPlaneExtractor for padded CameraX Y planes.
profileStillImageBatchScanProfileNoUse liveSweep for responsive camera work or stillImageDense for licensed rescue/batch input.
Result
A native status code. It is not a barcode count; prefer processFrame for same-frame observations.
Lifecycle
Submit only while the session is open. Live mode may drop stale frames; accepted batch input must not be silently dropped.
Trust boundary
The host must bound decoded image size and must not retain or upload image bytes without policy and consent.
Failure behavior
  • Closed sessions throw IllegalStateException.
  • Invalid dimensions, format, buffer, entitlement, or native state return or throw a deterministic failure.

VisionSession.processFrame(width, height, format, buffer, profile?): VisionFrameProcessResult

method

Process one bounded luminance frame through the SDK-owned native scan pipeline and return the status plus observations from that same accepted frame.

Inputs for VisionSession.processFrame(width, height, format, buffer, profile?): VisionFrameProcessResult
InputTypeRequiredMeaning
width / heightIntYesPositive pixel dimensions matching the normalized buffer.
formatIntYesThe SDK-supported image format code; CameraX integrations submit extracted luminance.
bufferByteArrayYesA stride-correct frame. Use YPlaneExtractor for padded CameraX Y planes.
profileStillImageBatchScanProfileNoUse liveSweep for responsive camera work or stillImageDense for licensed rescue/batch input.
Result
VisionFrameProcessResult(status, observations, tracking), where observations are native-decoded evidence from the same accepted frame and tracking contains native stable tracks, active/distinct/stable counts, duplicate-payload physical track count, dense-selection hints, exact target matches, pick state, and overlay-ready quadrilaterals.
Lifecycle
Use for new live and batch capture integrations. Live mode may drop stale frames by policy; accepted batch input must not be silently dropped.
Trust boundary
The host must bound decoded image size and must not retain or upload image bytes without policy and consent.
Failure behavior
  • Closed sessions throw IllegalStateException.
  • Invalid dimensions, format, buffer, entitlement, or native state return or throw a deterministic failure.

VisionSession.setFindTargets(targets: List<VisionScanTarget>): Unit

method

Install exact decoded-payload targets for SDK-owned find/pick matching.

Inputs for VisionSession.setFindTargets(targets: List<VisionScanTarget>): Unit
InputTypeRequiredMeaning
targetsList<VisionScanTarget>YesZero or more payload labels with required stable observation counts. Empty clears targets.
Result
Targets are applied to the native session tracker; subsequent processFrame results update tracking.targetMatchCount and per-track targetMatched/targetLabel.
Lifecycle
Call after session creation and before or during scanning. Targets are session-local and cleared on close.
Trust boundary
Matching is exact against deterministic decoder payloads; geometry and OCR-only rescue never synthesize a target value.
Failure behavior
  • Closed sessions throw IllegalStateException.
  • A missing native target matcher throws VisionScanNativeUnavailableException.

VisionSession.setTrackPickState(trackId: Long, state: VisionPickState): Boolean

method

Update one native tracked barcode's pick state for MatrixScan Pick-style workflows.

Inputs for VisionSession.setTrackPickState(trackId: Long, state: VisionPickState): Boolean
InputTypeRequiredMeaning
trackIdLongYesA positive native track ID returned in VisionTrackedBarcode.trackId.
stateVisionPickStateYesTO_PICK, PICKED, or IGNORED.
Result
True when the native session updated a known track; false when the track is stale or unknown.
Lifecycle
Call only while the session is open. The state is session-local and returned on subsequent tracking results.
Trust boundary
Pick state is workflow metadata only; receipt commit and quantity authority remain outside the scanner SDK.
Failure behavior
  • Closed sessions throw IllegalStateException.
  • Non-positive track IDs throw IllegalArgumentException.
  • A missing native pick-state bridge throws VisionScanNativeUnavailableException.

Android decoded observation contract

Decoded evidence is read separately from frame admission and remains GTIN-first.

VisionSession.getLatestObservations(): List<BarcodeObservation>

method

Return immutable observations produced by the most recently accepted frame.

Result
Zero or more BarcodeObservation values containing rawPayload, symbology, GTIN, dependent lot/expiry/serial evidence, OCR provenance, and confidence.
Lifecycle
Read after submitFrame succeeds and before the session is closed.
Trust boundary
OCR-only GTIN or serial evidence requires review and must never auto-commit; backend receipt validation remains authoritative.
Failure behavior
  • An empty list is a valid no-decode result.
  • Closed sessions throw IllegalStateException.
  • Malformed native observations fail deterministically instead of producing sample data.

Native MatrixScan sessions

PRXV-0122-S01: one native session owns bounded location/decode, tracks and state. Result schema: contracts/schemas/matrix-scan-result.schema.json; formats: contracts/matrix-scan-capabilities.json.

VisionScanSdk.createMatrixScanBatch(config: VisionSessionConfig, formats: Set<MatrixSymbology> = emptySet()): MatrixScanBatch

method

Accept each stable identity once and suppress repeats.

Inputs for VisionScanSdk.createMatrixScanBatch(config: VisionSessionConfig, formats: Set<MatrixSymbology> = emptySet()): MatrixScanBatch
InputTypeRequiredMeaning
configVisionSessionConfigYesVerified tenant context. Barcode intelligence and dense scan entitlement are rechecked on every operation.
formatsSet<MatrixSymbology>NoOnly declared native capabilities; Codabar/ITF require opt-in.
Result
MatrixScanResult: status, input-pixel geometry, tracks, accepted, count and bounded scheduler diagnostics.
Lifecycle
Off camera/UI threads. Monotonic input timestamps. close() releases session. Capacity is explicit; a new operation requires a new session.
Trust boundary
Signed tenant license required by the public Android facade. Physical scan counts are not pharmacy quantities or backend receipt commits.
Failure behavior
  • Invalid/truncated/oversized frame rejected.
  • Decoder failure, cancellation and capacity reached are explicit.
  • Decode time budget is cooperative between backend calls; it does not interrupt an in-flight decoder.

VisionScanSdk.createMatrixScanAR(config: VisionSessionConfig, formats: Set<MatrixSymbology>): MatrixScanAR

method

Publish persistent decoder-confirmed quadrilaterals.

Inputs for VisionScanSdk.createMatrixScanAR(config: VisionSessionConfig, formats: Set<MatrixSymbology>): MatrixScanAR
InputTypeRequiredMeaning
configVisionSessionConfigYesVerified tenant context. Barcode intelligence and dense scan entitlement are rechecked on every operation.
formatsSet<MatrixSymbology>NoOnly declared native capabilities; Codabar/ITF require opt-in.
Result
MatrixScanResult: status, input-pixel geometry, tracks, accepted, count and bounded scheduler diagnostics.
Lifecycle
Off camera/UI threads. Monotonic input timestamps. close() releases session. Capacity is explicit; a new operation requires a new session.
Trust boundary
Signed tenant license required by the public Android facade. Physical scan counts are not pharmacy quantities or backend receipt commits.
Failure behavior
  • Invalid/truncated/oversized frame rejected.
  • Decoder failure, cancellation and capacity reached are explicit.
  • Decode time budget is cooperative between backend calls; it does not interrupt an in-flight decoder.

VisionScanSdk.createMatrixScanCount(config: VisionSessionConfig, formats: Set<MatrixSymbology>): MatrixScanCount

method

Count stable physical tracks; identical payloads at distinct locations remain separate.

Inputs for VisionScanSdk.createMatrixScanCount(config: VisionSessionConfig, formats: Set<MatrixSymbology>): MatrixScanCount
InputTypeRequiredMeaning
configVisionSessionConfigYesVerified tenant context. Barcode intelligence and dense scan entitlement are rechecked on every operation.
formatsSet<MatrixSymbology>NoOnly declared native capabilities; Codabar/ITF require opt-in.
Result
MatrixScanResult: status, input-pixel geometry, tracks, accepted, count and bounded scheduler diagnostics.
Lifecycle
Off camera/UI threads. Monotonic input timestamps. close() releases session. Capacity is explicit; a new operation requires a new session.
Trust boundary
Signed tenant license required by the public Android facade. Physical scan counts are not pharmacy quantities or backend receipt commits.
Failure behavior
  • Invalid/truncated/oversized frame rejected.
  • Decoder failure, cancellation and capacity reached are explicit.
  • Decode time budget is cooperative between backend calls; it does not interrupt an in-flight decoder.

VisionScanSdk.createMatrixScanFind(config: VisionSessionConfig, formats: Set<MatrixSymbology>): MatrixScanFind

method

Find exact byte targets only after stable decode evidence.

Inputs for VisionScanSdk.createMatrixScanFind(config: VisionSessionConfig, formats: Set<MatrixSymbology>): MatrixScanFind
InputTypeRequiredMeaning
configVisionSessionConfigYesVerified tenant context. Barcode intelligence and dense scan entitlement are rechecked on every operation.
formatsSet<MatrixSymbology>NoOnly declared native capabilities; Codabar/ITF require opt-in.
Result
MatrixScanResult: status, input-pixel geometry, tracks, accepted, count and bounded scheduler diagnostics.
Lifecycle
Off camera/UI threads. Monotonic input timestamps. close() releases session. Capacity is explicit; a new operation requires a new session.
Trust boundary
Signed tenant license required by the public Android facade. Physical scan counts are not pharmacy quantities or backend receipt commits.
Failure behavior
  • Invalid/truncated/oversized frame rejected.
  • Decoder failure, cancellation and capacity reached are explicit.
  • Decode time budget is cooperative between backend calls; it does not interrupt an in-flight decoder.

VisionScanSdk.createMatrixScanPick(config: VisionSessionConfig, formats: Set<MatrixSymbology>): MatrixScanPick

method

Find targets and retain per-track pick transitions.

Inputs for VisionScanSdk.createMatrixScanPick(config: VisionSessionConfig, formats: Set<MatrixSymbology>): MatrixScanPick
InputTypeRequiredMeaning
configVisionSessionConfigYesVerified tenant context. Barcode intelligence and dense scan entitlement are rechecked on every operation.
formatsSet<MatrixSymbology>NoOnly declared native capabilities; Codabar/ITF require opt-in.
Result
MatrixScanResult: status, input-pixel geometry, tracks, accepted, count and bounded scheduler diagnostics.
Lifecycle
Off camera/UI threads. Monotonic input timestamps. close() releases session. Capacity is explicit; a new operation requires a new session.
Trust boundary
Signed tenant license required by the public Android facade. Physical scan counts are not pharmacy quantities or backend receipt commits.
Failure behavior
  • Invalid/truncated/oversized frame rejected.
  • Decoder failure, cancellation and capacity reached are explicit.
  • Decode time budget is cooperative between backend calls; it does not interrupt an in-flight decoder.

Android native MatrixScan camera integration

PRXV-0122-S04: SDK-owned stride extraction, deterministic frame release and native-quad preview mapping. Host retains permission, camera binding, UI, secure storage and backend commit.

MatrixScanSession.processFrame(luma: ByteArray, width: Int, height: Int, stride: Int = width, timestampNs: Long = System.nanoTime()): MatrixScanResult

method

Submit one full unrotated luminance frame to the native session.

Inputs for MatrixScanSession.processFrame(luma: ByteArray, width: Int, height: Int, stride: Int = width, timestampNs: Long = System.nanoTime()): MatrixScanResult
InputTypeRequiredMeaning
frameByteArray + dimensions + stride + monotonic nanosecondsYesCaller-owned readable luma; fixed dimensions per session; no concurrent mutation. Maximum axis 8192 and 32000000 pixels.
Result
Typed MatrixScanResult with industry-neutral byte payloads and input-pixel quads. visibleTracks excludes lost/unstable tracks and failed-frame boxes.
Lifecycle
Synchronous worker call. Native state is session-owned; close after the operation. Do not feed accepted still/burst inputs through dropping live adapters.
Trust boundary
Verified license checked on every call. Payload is not necessarily UTF-8; counts are not backend receipt quantity.
Failure behavior
  • Invalid frame and decoder/capacity/cancellation statuses are explicit.
  • Incompatible native JSON version, encoding, mode or malformed typed result raises a redacted IllegalStateException.

MatrixScanAnalyzer(session: MatrixScanSession, listener: MatrixScanCameraListener): ImageAnalysis.Analyzer, AutoCloseable

type

Adapt live CameraX ImageProxy input without host pixel copying, tracking or decoder orchestration.

Inputs for MatrixScanAnalyzer(session: MatrixScanSession, listener: MatrixScanCameraListener): ImageAnalysis.Analyzer, AutoCloseable
InputTypeRequiredMeaning
sessionMatrixScanSessionYesBorrowed authorized native session; analyzer never closes it.
listenerMatrixScanCameraListenerYesWorker callbacks onResult(MatrixScanCameraResult) and onError(MatrixScanCameraError). Keep callbacks short; callback exceptions propagate after release.
Result
One typed snapshot per processed frame, no retained camera buffer. Every delivered ImageProxy is closed.
Lifecycle
YUV_420_888, KEEP_ONLY_LATEST, single worker. Concurrent/closed live calls are released without decoding. close stops new work; admitted work still delivers its worker callback/evidence. Host stops/unbinds, closes session on worker, then shuts down executor. Discard stale UI painting only.
Trust boundary
No logging or media persistence. Borrowed session keeps license checks; analyzer adds no Scandit dependency.
Failure behavior
  • INVALID_IMAGE, ENTITLEMENT_DENIED and PROCESSING_FAILED carry no raw exception/payload.
  • Native result statuses remain available in frame.result; no decode is a normal empty result.

MatrixScanCameraResult.mapVisibleTracks(previewTransform: OutputTransform): List<MatrixScanOverlay>

method

Map only current stable native quads to PreviewView pixels through CameraX CoordinateTransform.

Inputs for MatrixScanCameraResult.mapVisibleTracks(previewTransform: OutputTransform): List<MatrixScanOverlay>
InputTypeRequiredMeaning
previewTransformandroidx.camera.view.transform.OutputTransformYesNon-null PreviewView transform from the same ViewPort and camera binding as this frame.
Result
MatrixScanOverlay(track: MatrixTrack, quad: List<MatrixPoint>): original native track and four mapped preview-pixel points; original track.quad unchanged.
Lifecycle
Map/render on UI after preview layout. Discard previous-binding callbacks; do not rotate or crop mapped geometry twice. Raw frame timestamp is frame.timestampNs.
Trust boundary
Transforms do not infer payload, identity, target matching or count.
Failure behavior
  • Invalid/non-invertible/non-finite transform fails; never substitute guessed rectangles.
  • Wrong camera binding/ViewPort is caller misuse; clear overlays and rebind rather than painting stale geometry.

Licensed native MatrixScan usage reporting

PRXV-0132-S04: opt-in, content-free native acceptance/processing deltas to the existing tenant-authenticated ingestion API. Metrics schema: contracts/json/matrix-scan-usage.schema.json. Live staging delivery and analytics projections remain validation/downstream gates.

VisionScanSdk.startMatrixTelemetry(options: MatrixTelemetryOptions, tokenProvider: () -> String): MatrixScanTelemetry

method

Attach SDK-owned usage collection to subsequently created MatrixScan sessions, with independent bounded reporting work.

Inputs for VisionScanSdk.startMatrixTelemetry(options: MatrixTelemetryOptions, tokenProvider: () -> String): MatrixScanTelemetry
InputTypeRequiredMeaning
optionsMatrixTelemetryOptionsYesTrusted HTTPS control-plane origin, actual SDK version, bounded interval/capacity and optional encrypted host storage.
tokenProvider() -> StringYesHost-owned enrolled tenant access token with telemetry permission; worker-only, never raw license/JWS.
Result
Lifecycle handle with typed status, queued/dropped/rejected counters, flushAsync, close, isStopped and awaitStopped.
Lifecycle
Verified UUID-device license first; reporting before native session creation. Close on logout/switch, then awaitStopped on a cleanup worker before reusing storage or restarting. One reporter/file writer.
Trust boundary
No tenant authority in request body; server checks claims and device licensing. No barcode value, image, quad, track ID, key/token or arbitrary diagnostic text. Opt-in, no redirects; five fixed mode buckets. Telemetry is not a billing or receiving authority.
Failure behavior
  • Invalid origin/version/bounds or missing verified UUID-device license rejects start.
  • Transport failure retains stable IDs; only matching per-event outcomes retire events.
  • Queue saturation delays new counters in fixed buckets; shutdown overflow and terminal rejections expose statistics losses, never receipt loss.
  • Corrupt/foreign encrypted spool stops delivery without overwriting it.

Review the release support matrix before deployment. Support status and contract failure behavior remain authoritative even when an example is copied.