Skip to content

Building an Android ISBN Scanner in Kotlin

Kevin February 26, 2025 8 mins read
app store

In this tutorial, we’ll build an Android app for scanning ISBN barcodes using Kotlin, Android Studio, and the Scanbot Android Barcode Scanner SDK.

First, we’ll implement the underlying barcode scanning interface. Then, we’ll adapt the scanner functionality further to optimize it for ISBN codes.

Scanning an ISBN with barcode mapping using our Android ISBN Scanner

We’ll achieve this in five steps:

  1. Preparing the project
  2. Initializing the SDK
  3. Setting up the main screen
  4. Implementing the barcode scanner
  5. Setting up ISBN scanning

All you need is the latest version of Android Studio and you’re good to go.

Step 1: Prepare the project

Create a new Empty Views Activity and name the project (e.g., “Android ISBN Scanner”).

When your project is ready, go to settings.gradle.kts and add the Maven repositories for the Scanbot SDK:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()

        // Add the repositories here:
        maven(url = "https://nexus.scanbot.io/nexus/content/repositories/releases/")
        maven(url = "https://nexus.scanbot.io/nexus/content/repositories/snapshots/")
    }
}

Now go to app/build.gradle.kts and add the dependencies for the Scanbot SDK and the RTU UI:

dependencies {
    implementation("io.scanbot:scanbot-barcode-scanner-sdk:6.2.1")
    implementation("io.scanbot:rtu-ui-v2-barcode:6.2.1")

Sync the project.

💡 We use Barcode Scanner SDK version 6.2.1 in this tutorial. You can find the latest version in the changelog.

Since we need to access the device camera to scan ISBN codes, let’s also add the necessary permissions in AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />

    <application
    ...

💡 Later in this tutorial, we’ll access a web URL to fetch an image file. If you want to follow along, also add a permission to access the internet:

<uses-permission android:name="android.permission.INTERNET" />

Step 2: Initialize the SDK

Before we can use the Barcode Scanner SDK, we need to initialize it. The recommended approach is to do it in your Application implementation. This ensures the SDK is correctly initialized even when the app’s process is restored after being terminated in the background.

First, we need to create an Application subclass by right-clicking on the folder app/kotlin+java/com.example.androidbarcodescanner, selecting New > Kotlin Class/File, and naming it (e.g., “ExampleApplication”).

In the resulting ExampleApplication.kt, let’s first add the necessary imports:

import android.app.Application
import io.scanbot.sdk.barcode_scanner.ScanbotBarcodeScannerSDKInitializer

Then make ExampleApplication extend the Application class by adding : Application() and add the code for initializing the SDK inside it:

class ExampleApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        ScanbotBarcodeScannerSDKInitializer()
            // Optional: uncomment the next line if you have a license key.
            // .license(this, LICENSE_KEY)
            .initialize(this)
    }
}

💡 Without a license key, our SDK only runs for 60 seconds per session. This is more than enough for the purposes of our tutorial, but if you like, you can generate a license key. Just make sure to change your applicationId in app/build.gradle.kts to io.scanbot.androidbarcodescanner and use that ID to generate the license.

Finally, we need to register the ExampleApplication class in AndroidManifest.xml:

<application
   android:name=".ExampleApplication"
   ...

Step 3: Set up the main screen

We’re going to build a rudimentary UI so we can quickly access the scanning interface in our app.

You can copy the following code for a simple one-button layout into app/res/layout/activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_isbn_scanning"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Scan ISBN Barcode"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.5" />

</androidx.constraintlayout.widget.ConstraintLayout>

Step 4: Implement the barcode scanner

Now we’ll connect the button with the RTU UI’s single-barcode scanning mode.

Go to MainActivity.kt and add the necessary imports:

import android.widget.Button
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import io.scanbot.sdk.ui_v2.barcode.BarcodeScannerActivity
import io.scanbot.sdk.ui_v2.common.activity.registerForActivityResultOk
import io.scanbot.sdk.ui_v2.barcode.configuration.*

In the MainActivity class, add a private property that we’ll use to launch the barcode scanner.

private val barcodeResultLauncher: ActivityResultLauncher<BarcodeScannerConfiguration> =
        registerForActivityResultOk(BarcodeScannerActivity.ResultContract()) { resultEntity ->
        // Barcode Scanner result callback:
        // Get the first scanned barcode from the result object...
        val barcodeItem = resultEntity.result?.items?.first()
        // ... and process the result as needed. For example, display as a Toast:
        Toast.makeText(
            this,
            "Scanned: ${barcodeItem?.text} (${barcodeItem?.type})",
            Toast.LENGTH_LONG
        ).show()
    }

Next, in the onCreate() method, we set up an OnClickListener for our Scan ISBN Barcode button. When the button is clicked, it should launch barcodeResultLauncher using a configuration object we’ll set up in the next step:

findViewById<Button>(R.id.btn_isbn_scanning).setOnClickListener {
    barcodeResultLauncher.launch(config)
}

Now paste the configuration for single-barcode scanning above barcodeResultLauncher.launch(config):

findViewById<Button>(R.id.btn_isbn_scanning).setOnClickListener {
    val config = BarcodeScannerConfiguration().apply {
        // Initialize the use case for single scanning.
        this.useCase = SingleScanningMode().apply {
            // Enable the confirmation sheet.
            this.confirmationSheetEnabled = true
        }
    }
    barcodeResultLauncher.launch(config)
}

Feel free to run the app and try the single-barcode scanning feature before we move on to adapting the functionality to ISBN barcodes specifically.

Scanning any barcode with our Android ISBN Scanner

Step 5: Set up ISBN scanning

We’ll now further tweak the scanner configuration to streamline scanning ISBN barcodes.

First, add one more import to MainActivity.kt:

import io.scanbot.sdk.ui_v2.barcode.common.mappers.getName

Since the ISBN barcode is a sub-symbology of EAN-13, we’ll configure the scanner so it ignores any other symbologies. This prevents unintended scans and improves the scanner’s performance, as it doesn’t need to check each supported symbology.

this.recognizerConfiguration.barcodeFormats = listOf(BarcodeFormat.EAN_13)

By default, the scanner has a square viewfinder. An ISBN barcode is generally wider than it is high, which we can convey to the user by adjusting the viewfinder’s aspect ratio accordingly.

this.viewFinder.aspectRatio.height = 1.0
this.viewFinder.aspectRatio.width = 1.5

Since an ISBN is a unique identifier for a single book, you might want to show the user information about that book as they scan the barcode. You can achieve this with the SDK’s Barcode Mapping feature.

Of course, you’ll need to fetch the data from somewhere, e.g., an online database or your server. This is entirely up to you. For this tutorial, we’ll hardcode an example so you can see what this feature will look like in the finished app, but feel free to experiment with your own solution.

class CustomMapper() : BarcodeItemMapper {
    override fun mapBarcodeItem(
        barcodeItem: BarcodeItem,
        result: BarcodeMappingResult
    ) {
        // Instead of using static values, implement your own solution here when building your app.
        val title = "The Ultimate Guide to Scanning Barcodes"
        val subtitle = barcodeItem.type?.getName() ?: "Unknown"
        val image = "https://scanbot.io/wp-content/uploads/2025/02/isbn-scanner-example-book.png"

        if (barcodeItem.textWithExtension == "Error occurred!") {
            result.onError()
        } else {
            result.onResult(
                BarcodeMappedData(
                    title = title,
                    subtitle = subtitle,
                    barcodeImage = image,
                )
            )
        }
    }
}

The result should look something like this:

findViewById<Button>(R.id.btn_isbn_scanning).setOnClickListener {
    val config = BarcodeScannerConfiguration().apply {
        // Initialize the use case for single scanning.
        this.useCase = SingleScanningMode().apply {
            // Enable and configure the confirmation sheet.
            this.confirmationSheetEnabled = true

            class CustomMapper() : BarcodeItemMapper {
                override fun mapBarcodeItem(
                    barcodeItem: BarcodeItem,
                    result: BarcodeMappingResult
                ) {
                    // Instead of using static values, implement your own solution here when building your app.
                    val title = "The Ultimate Guide to Scanning Barcodes"
                    val subtitle = barcodeItem.type?.getName() ?: "Unknown"
                    val image = "https://scanbot.io/wp-content/uploads/2025/02/isbn-scanner-example-book.png"

                    if (barcodeItem.textWithExtension == "Error occurred!") {
                        result.onError()
                    } else {
                        result.onResult(
                            BarcodeMappedData(
                                title = title,
                                subtitle = subtitle,
                                barcodeImage = image,
                            )
                        )
                    }
                }
            }
            this.barcodeInfoMapping.barcodeItemMapper = CustomMapper()
        }
        // Restrict scanning to EAN-13 codes
        this.recognizerConfiguration.barcodeFormats = listOf(BarcodeFormat.EAN_13)

        // Define the viewfinder's aspect ratio.
        this.viewFinder.aspectRatio.height = 1.0
        this.viewFinder.aspectRatio.width = 1.5
    }
    barcodeResultLauncher.launch(config)
}

Now build and run your app again and scan an ISBN barcode…

… to test your scanner!

Scanning an ISBN with barcode mapping using our Android ISBN Scanner

Conclusion

🎉 Congratulations! You can now scan ISBN barcodes and preview the associated data right in the viewfinder.

If this tutorial has piqued your interest in integrating barcode scanning functionalities into your Android app, make sure to take a look at our SDK’s other neat features in our documentation – or run our example project for a more hands-on experience.

Should you have questions about this tutorial or run into any issues, we’re happy to help! Just shoot us an email via tutorial-support@scanbot.io.

Happy scanning! 🤳