Skip to content

Android: barcode scanner has no camera selection - always opens the default rear lens, which can be a fixed-focus one #71

Description

@AFT-syd

Summary

On a phone with several rear cameras the scanner opens a camera that cannot focus, and there is no way to switch to a different one. The barcode never becomes sharp, so scanning is impossible.

Environment

  • LibrisLog ghcr.io/codebude/librislog/librislog:latest, image built 2026-06-22 (API image same build date), self-hosted behind nginx with a trusted internal CA — HTTPS/secure context is fine, permission is granted and the camera starts
  • Huawei P30, Android
  • Vivaldi (Chromium) — also reproduced in Brave (Chromium)

The device is not the cause

Verified on the same phone, in the same browser:

Test Result
webrtc samples → devices/input-output switching between all cameras works; cameras 0, 2 and 3 (facing back) focus correctly
webrtc samples → pan-tilt-zoom zoom is exposed and works

Camera 4 (facing back) is the only one that cannot focus — evidently a fixed-focus auxiliary lens. So the browser exposes both camera selection and zoom on this device; the app just doesn't use them.

Root cause

The scanner requests the camera like this (/_app/immutable/chunks/BTxGinf0.js in the current image):

await navigator.mediaDevices.getUserMedia({
  audio: false,
  video: {
    facingMode: { ideal: "environment" },
    width:  { min: 640 },
    height: { min: 480 }
  }
})

Only facingMode is used, so the browser picks whichever rear camera it considers default and the user cannot influence it. On multi-camera Android phones that default is frequently an ultra-wide or a macro/depth sensor — and several of those are fixed-focus.

The bundled ZXing library does support deviceId: { exact: … } (it is right there in the same chunk), but this code path doesn't use it. No zoom or focusMode constraints are applied either.

Suggested fix

  1. enumerateDevices() → list the videoinput devices and let the user choose, persisting the choice (a phone's "best" lens is not guessable from the label alone).
  2. Request with deviceId: { exact: … }, and stop the previous track before switching — otherwise Android tends to hand back the old stream.
  3. Where track.getCapabilities() reports them, apply focusMode: "continuous" and expose zoom through applyConstraints().

A "switch camera" button that simply cycles through the available videoinput devices would already make the scanner usable on this class of phone.

Happy to test a build.

Metadata

Metadata

Assignees

Labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions