Call the Kotlin Android facade from Java while preserving tenant/device binding and deterministic session cleanup.
Status
Evaluation
Integration
Embedded SDK
Distribution
Tenant download grant
Version
0.1.0-RC4
The Java guide uses the same customer outcome: integrate the SDK facade, scan the package, and return structured evidence.
Prerequisites
Android API 26 or newer
JDK 17
The tenant-delivered AAR
A backend-issued signed license JWS
1. Install the AAR
Install the AAR
// settings.gradle: repository extracted from the granted ZIP
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri('sdk-release/maven') }
}
}
// app/build.gradle
dependencies {
implementation 'com.visionscan.sdk:vision-scan-android-sdk:0.1.0-RC4'
}
Verify the complete ZIP SHA-256 against the authenticated catalog and retain Maven/POM/OpenCV dependencies. The Kotlin facade is callable through VisionScanSdk.INSTANCE.
2. Verify and apply the license
Verify and apply the license
// Worker: IDs are returned by trusted authenticated enrollment.
VisionScanSdk.INSTANCE.initializeLeaseStore(getNoBackupFilesDir(), deviceId);
VisionScanSdk.INSTANCE.initializeHardwareBinding(getApplicationContext());
EntitlementEvaluationResult entitlement = VisionScanSdk.INSTANCE.applySignedLicenseJws(
signedLicenseJws, tenantId, deviceId, Instant.now().getEpochSecond());
if (!entitlement.isAllowed()) {
throw new IllegalStateException(entitlement.getDenialReason());
}
Enroll the hardware installation key with a server challenge before bound lease admission. Tenant and device IDs are verified enrollment context, not manually invented fields. Configure trusted JWKS before applying a JWS. The deprecated object-taking license method fails closed; encrypted-key-only initialization is not shipped.
Use the CameraX YPlaneExtractor helper before processFrame when the source ImageProxy has padded rows.
Errors and recovery
Condition
Resolution
Java cannot find an overload
Pass every constructor and method argument shown; Kotlin default arguments do not create Java overloads automatically.
Session creation is denied
Apply a verified JWS for the exact tenant and device before constructing the session.
Production checklist
Treat the AAR and Java interoperability surface as the same RC2 artifact
Close sessions with try-with-resources
Preserve row and pixel stride when extracting CameraX luma
Test license denial paths
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.
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.
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
Input
Type
Required
Meaning
storageDir
File
Yes
A host-owned no-backup directory; do not use a shared or user-exportable location.
hostDeviceId
String
Yes
The 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.
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
Input
Type
Required
Meaning
width / height
Int
Yes
Positive pixel dimensions matching the normalized buffer.
format
Int
Yes
The SDK-supported image format code; CameraX integrations submit extracted luminance.
buffer
ByteArray
Yes
A stride-correct frame. Use YPlaneExtractor for padded CameraX Y planes.
profile
StillImageBatchScanProfile
No
Use 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
Input
Type
Required
Meaning
width / height
Int
Yes
Positive pixel dimensions matching the normalized buffer.
format
Int
Yes
The SDK-supported image format code; CameraX integrations submit extracted luminance.
buffer
ByteArray
Yes
A stride-correct frame. Use YPlaneExtractor for padded CameraX Y planes.
profile
StillImageBatchScanProfile
No
Use 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
Input
Type
Required
Meaning
targets
List<VisionScanTarget>
Yes
Zero 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.
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.
Caller-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.
Adapt live CameraX ImageProxy input without host pixel copying, tracking or decoder orchestration.
Inputs for MatrixScanAnalyzer(session: MatrixScanSession, listener: MatrixScanCameraListener): ImageAnalysis.Analyzer, AutoCloseable
Input
Type
Required
Meaning
session
MatrixScanSession
Yes
Borrowed authorized native session; analyzer never closes it.
listener
MatrixScanCameraListener
Yes
Worker 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.
Map only current stable native quads to PreviewView pixels through CameraX CoordinateTransform.
Inputs for MatrixScanCameraResult.mapVisibleTracks(previewTransform: OutputTransform): List<MatrixScanOverlay>
Input
Type
Required
Meaning
previewTransform
androidx.camera.view.transform.OutputTransform
Yes
Non-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.
Attach SDK-owned usage collection to subsequently created MatrixScan sessions, with independent bounded reporting work.
Inputs for VisionScanSdk.startMatrixTelemetry(options: MatrixTelemetryOptions, tokenProvider: () -> String): MatrixScanTelemetry
Input
Type
Required
Meaning
options
MatrixTelemetryOptions
Yes
Trusted HTTPS control-plane origin, actual SDK version, bounded interval/capacity and optional encrypted host storage.
tokenProvider
() -> String
Yes
Host-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.