Other versions of this page
Barcode Detection
The Camera SDK has a built-in barcode detector that will help you identify different kind of barcodes in real-time.
We support the following set of barcodes, exposed through the Barcode.Kind
enumeration:
Value | Description |
---|---|
Barcode.Kind.QR Barcode.Kind.qr | Quick Response Code, a 2D matrix barcode. |
Barcode.Kind.MicroQR Barcode.Kind.microQr | Smaller version of QR code with reduced data capacity. |
Barcode.Kind.EAN13 Barcode.Kind.ean13 | European Article Number, 13-digit barcode. |
Barcode.Kind.EAN8 Barcode.Kind.ean8 | European Article Number, 8-digit barcode. |
Barcode.Kind.UPCA Barcode.Kind.upca | Universal Product Code A, 12-digit barcode. |
Barcode.Kind.UPCE Barcode.Kind.upce | Universal Product Code E, 6-digit barcode. |
Barcode.Kind.Code128 Barcode.Kind.code128 | Code128, high-density linear barcode. |
Barcode.Kind.DataMatrix Barcode.Kind.dataMatrix | DataMatrix 2D matrix barcode. |
Barcode.Kind.Aztec Barcode.Kind.aztec | Aztec 2D matrix barcode. |
If your barcode is not on the list, please let us know - we may provide more options in the future.
Configuration
Requirements
Barcode detection works on all devices. The only requirement is to declare your intention to use it during manager initialization.
We provide a special feature object called CameraFeature.Barcode
CameraFeature.barcode
.
Barcode detection doesn't need a visible preview. You may use the barcode feature without
CameraFeature.Preview
CameraFeature.preview
and it will work out of the box.
To interact with all barcode APIs, you'll use the BarcodeDetector
class:
swiftlet detector: BarcodeDetector = cameraManager.barcodeDetector
kotlinval detector: BarcodeDetector = cameraManager.barcodeDetector
Options
The BarcodeDetector.Options
class and the BarcodeDetector.options
field will let you configure the detection options,
which can affect performance, amount and type of symbols to be retrieved and more.
Value | Type | Default | Description |
---|---|---|---|
Options.count | Int | 1 | The maximum number of barcodes to return. A number higher than 1 means that if a barcode is found in the scene, the engine will keep looking for more in the same frame. |
Options.kinds | List of Barcode.Kind | [Kind.QR] [.qr] | The set of barcode kinds to detect. The processing time per frame grows with the number of kinds. |
Options.priority | Priority enum | Priority.Speed .speed | Choose between speed and accuracy. In accurate mode, the engine will spend more time and resources looking for barcodes. |
Options.surface | String? | First available surface | The name of a preview surface, so that barcodes can be easily drawn on the current screen. |
Options.interval | Long (ms)TimeInterval | 1 second | The time that the engine should wait after an unsuccessful frame, before requesting a new one. Doesn't apply to frames with barcodes: in that case, no time is wasted to update the barcode position smoothly. |
swiftlet detector: BarcodeDetector = cameraManager.barcodeDetector
detector.options = Options(count: 3, kinds: [.qr, .microQr])
kotlinval detector: BarcodeDetector = cameraManager.barcodeDetector
detector.options = Options(count = 3, kinds = listOf(QR, MicroQR))
Disabling detection
Detection can be disabled in a number of ways:
- The
CameraFeature.Barcode
CameraFeature.barcode
was not set - The
Options
value has a non-positivecount
- The
Options
value has a negativeinterval
- The
Options
value has an emptykinds
array - The
Options
value has a non-emptysurface
, but no surface with that name exists
Disabling detection can be useful to save resources (CPU and battery) when not needed, for example while recording videos.
Observing barcodes
Once the barcode feature is declared and the CameraDevice
is open, detection will start automatically. The barcode detector
will then provide you with a sequence of one or more Barcode
objects with the following properties:
Value | Type | Description |
---|---|---|
Barcode.kind | Barcode.Kind | The kind of detected barcode (QR code, UPC-A, ...). |
Barcode.content | String | The barcode contents as a String. Depending on the barcode kind the string may be contain only numbers, or it may have structured data (URL, Wi-Fi network and password, location, contacts, ...). |
Barcode.position | Polygon | The barcode position on the current preview surface (see Options.surface ), in normalized values in the 0...1 range. Use Polygon.points to draw the four corners, or Polygon.box to draw the bounding box. |
There are two ways to receive Barcode
updates:
- By reading barcode detector's state, which updates automatically
- By receiving barcode detection events
State
On every processed frame, BarcodeDetector
will update its barcodes
property which can be read to retrieve a list of Barcode
objects.
Note that in the majority of frames, the list will be empty. The list of barcodes can also be observed
through the provided coroutines Flow
the provided publisher:
kotlinval detector: BarcodeDetector = cameraManager.barcodeDetector
val flow: StateFlow<List<Barcode>> = detector.barcodes
swiftlet detector: BarcodeDetector = cameraManager.barcodeDetector
let publisher: AnyPublisher<[Barcode], Never> = detector.barcodesPublisher
The stateful APIs are the recommended way to receive barcode updates to update the UI (e.g. draw the barcode box on screen), because you'll be able to receive position updates for a barcode that was initially detected in previous frames.
Events
In addition, you can register an observer lambda that will be executed for any new barcode, as soon as it is found.
The difference with the previous approach is that you won't get duplicate updates: if a Barcode
is detected on frames
i, i + 1, .... i + 100
you'll only get the event on frame i
.
This mode can be useful if all you care about is the barcode contents. Remember to return true
to continue receiving
updates, and false
to remove the observer:
kotlinval detector: BarcodeDetector = cameraManager.barcodeDetector
detector.observe { barcode ->
// Handle barcode...
true // Keep observing
}
swiftlet detector: BarcodeDetector = cameraManager.barcodeDetector
detector.observe { barcode in
// Handle barcode...
return true // Keep observing
}