Case Study 5 min read

SmileID and CameraX: ResolutionSelector, Backpressure and 18,000+ Device Types for On-Device Liveness

On Nov 11, 2026 the Android Developers Blog published a case study on SmileID, an identity-verification SDK vendor in Africa, and how moving its Android SDKs to CameraX changed its numbers. Beyond the headline figures, the article shows a compact, reusable camera configuration for face capture on weak hardware. All figures below are SmileID's own, as reported in that post.

18,000+
Android device types supported
4x
selfie/liveness pixels, same upload size
160M+
verifications processed

1. The problem: fragmented hardware

Android represents 85% of SmileID's target device market share, including entry-level phones, obscure regional models and ruggedized POS terminals. Under Camera1 and Camera2 they hit three recurring problems:

Adoption growth was limited to 2-3x, and many verifications fell back to uploading a static photo over REST instead of running real-time on-device liveness.

2. The pipeline: Preview plus ImageAnalysis

SmileID rebuilt its SDKs on two CameraX use cases: Preview to show a correctly proportioned live feed, and ImageAnalysis to run liveness and face-in-frame detection locally and pull out the verified selfie frame. The key is how ImageAnalysis is configured: a ResolutionSelector with a target size and a fallback rule, plus a backpressure strategy.

fun configureCameraX(
    cameraProvider: ProcessCameraProvider,
    lifecycleOwner: LifecycleOwner,
    surfaceProvider: Preview.SurfaceProvider,
    executor: Executor,
    analyzer: ImageAnalysis.Analyzer,
) {
    val resolutionSelector = ResolutionSelector.Builder()
        .setResolutionStrategy(
            ResolutionStrategy(
                Size(1200, 900),
                ResolutionStrategy.FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER
            )
        )
        .setAspectRatioStrategy(AspectRatioStrategy.RATIO_4_3_FALLBACK_AUTO_STRATEGY)
        .build()

    val imageAnalysis = ImageAnalysis.Builder()
        .setResolutionSelector(resolutionSelector)
        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
        .build()
        .also { it.setAnalyzer(executor, analyzer) }

    val preview = Preview.Builder().build().also { it.surfaceProvider = surfaceProvider }

    try {
        cameraProvider.unbindAll()
        cameraProvider.bindToLifecycle(
            lifecycleOwner, CameraSelector.DEFAULT_FRONT_CAMERA, preview, imageAnalysis
        )
    } catch (exc: Exception) {
        // surface the binding failure to the caller
    }
}

This mirrors the sample in the post. Two choices matter. FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER prioritizes sharpness when 1200x900 is not supported; the post says to use FALLBACK_RULE_CLOSEST_LOWER_THEN_HIGHER instead if you need to cap memory. And STRATEGY_KEEP_ONLY_LATEST drops older frames while the analyzer is still busy, which keeps the pipeline responsive on slow processors.

Why the 4x matters: SmileID crops the face region and compresses it on-device, so the upload size stayed identical to the previous system. Sharper input for the ML models, no extra cellular data cost for users.

3. Why it works across 18,000+ devices

4. Reported results

These are vendor-reported results from a Google-published case study. Treat the adoption multiples as directional; the portable lesson is the configuration, not the percentages.

5. The CameraX Skill

The post also points to a CameraX Skill for AI coding agents, covering Camera1 migration, lifecycle binding, ConcurrentCamera and MlKitAnalyzer, and both PreviewView and CameraXViewfinder. Add it with android skills add camerax in the Android CLI.

Takeaways for your own camera code

Source: "How SmileID Scaled Identity Verification to 18,000+ Android Device Types with CameraX", Android Developers Blog, Nov 11, 2026, retrieved Nov 12, 2026.

Comments 0

No comments yet. Be the first to leave one!

Leave a comment