Skip to main content

VIN Scanner UI Components | Android Document Scanner


The Scanbot SDK provides the ability to scan and verify Vehicle Identification Numbers (VIN).

The VIN scanner is available both as an RTU UI and as a classic component (types of components are explained here).


Take a look at our Example Apps to see how to integrate the VIN scanner.

Add Feature as a Dependency

VinScanner is available with SDK Package 2. You have to add the following dependencies for it:


Initialize the SDK

Add the OCR training data file (.traineddata) for the desired language to the assets. See Optical Character Recognition.

Add a call of .prepareOCRLanguagesBlobs(true) method in ScanbotSDKInitializer.

override fun onCreate() {

.license(this, licenseKey)
// TODO: other configuration calls

Please do not use multiple scanners at the same time. For example, do not combine generic document scanner, health insurance scanner, text data scanner, etc. at the same time! Each scanner instance requires a lot of memory, GPU, and processor resources. Using multiple scanners will lead to performance issues for the entire application.

Ready-To-Use UI Component

Ready-To-Use UI Component (activity) that is responsible for scanning VIN is VinScannerActivity.

alt text

Have a look at our end-to-end working example of the RTU components usage here.

Starting and configuring RTU VIN scanner

First of all, you have to add the SDK package and feature dependencies as described here.

Initialize the SDK as described here. More information about the SDK license initialization can be found here.

To use any of the RTU UI components you need to include the corresponding dependency in your build.gradle file:


Get the latest $scanbotSdkVersion from the Changelog.

To start the RTU UI VIN scanner you only have to start a new activity and be ready to process its result later.


Starting from version 1.90.0, the SDK RTU components contain predefined AndroidX Result API contracts. They handle part of the boilerplate for starting the RTU activity component and mapping the result once it finishes.

If your code is bundled with Android's deprecated startActivityForResult API - check the other approach we offer for this case.

val vinScannerResultLauncher: ActivityResultLauncher<VinScannerConfiguration>


vinScannerResultLauncher = registerForActivityResult(VinScannerActivity.ResultContract()) { resultEntity: VinScannerActivity.Result ->
if (resultEntity.resultOk) {
Toast.makeText(this@MainActivity, formatResult(resultEntity.result), Toast.LENGTH_LONG).show()


myButton.setOnClickListener {
val configuration = VinScannerConfiguration()

We offer some syntactic sugar for handling the result from RTU components via AndroidX Result API:

  • every RTU component's activity contains a Result class which, in turn, along with the resultCode value exposes a Boolean resultOk property. This will be true if resultCode equals Activity.RESULT_OK;

  • when you only expect Activity.RESULT_OK result code - you can use the AppCompatActivity.registerForActivityResultOk extension method instead of registerForActivityResult - it will be triggered only when there is a non-nullable result entity present.


Always use the corresponding activity's static newIntent method to create intent when starting the RTU UI activity using deprecated startActivityForResult approach. Creating android.content.Intent object using its constructor (passing the activity's class as a parameter) will lead to the RTU UI component malfunctioning.

An instance of VinScannerConfiguration is required for starting the RTU UI activity. It allows configuration changes through methods it exposes:

val configuration = VinScannerConfiguration()
configuration.setGuidanceText("Scan VIN code")

All parameters in VinScannerConfiguration are optional.

API references for all of these methods can be found on this page.

Handling the result

Below is a simple example of presenting the result: VinScanResult fields separated by a newline character, shown in a Toast notification.

val scannedVinString = StringBuilder()
.append("VIN code: ${result.rawText}")
.append("\nConfidence: ${result.confidenceValue}")
.append("\nValidation success: ${result.validationSuccessful}")
Toast.makeText(this@MainActivity, scannedVinString, Toast.LENGTH_LONG).show()

Full API references for the result class are available here.

Classic component

Try our VIN Scanner Example or check the following step by step integration instructions.

VinScanner can only be used in conjunction with ScanbotCameraXView for live detection with preview. Let's have a look at an example.

Add feature depedencies and initialize the SDK

First of all, you have to add the SDK package and feature dependencies as described here.

Initialize the SDK as described here. More information about the SDK license initialization can be found here.

Add ScanbotCameraXView to layout

android:layout_height="match_parent" />

Get VinScanner instance from ScanbotSDK, and attach it to ScanbotCameraXView

val scanbotSdk = ScanbotSDK(this)
val vinScanner = scanbotSdk.createVinScanner()
val vinScannerFrameHandler = VinScannerFrameHandler.attach(cameraView, vinScanner)

Add a result handler for VinScannerFrameHandler:

Add a frame handler which observes successful recognition status and, for example, sets the scanned data to a properly formatted resultTextView.

vinScannerFrameHandler.addResultHandler(VinScannerFrameHandler.ResultHandler { result ->
val resultText: String = when (result) {
is FrameHandlerResult.Success -> {
if (result.value.validationSuccessful) {
} else {
"VIN not found"
is FrameHandlerResult.Failure -> "Check your setup or license"

// NOTE: 'handle' method runs in background thread - don't forget to switch to main before touching any Views
runOnUiThread { resultTextView.text = resultText }


As the result of scanning, the user gets the VinScanResult class instance, which contains a raw scanned text, a recognition confidence value and a flag indicating that scanned value was successfully validated.

Using Finder Overlay

It is important to add a finder overlay because of the scanner's underlying implementation. By doing so, the camera is directed to the VIN area and recognition is limited to only a small portion of the preview frame. This should greatly improve performance and accuracy of recognition.

Details about applying finder view logic in the layout and in the code can be found here.

Want to scan longer than one minute?

Generate your free "no-strings-attached" Trial License and properly test the Scanbot SDK.

Get your free Trial License

What do you think of this documentation?