Skip to content

How to integrate our Android Document Scanner SDK – a step-by-step tutorial

Ildar January 21, 2025 8 mins read
app store

In this tutorial, we’ll use Android Studio and the Scanbot Android Document Scanner SDK to create a simple app with a fully functional document scanner that can export documents as PDFs.

We’ll achieve this in five steps:

  1. Preparing the project
  2. Initializing the SDK
  3. Setting up the main screen
  4. Implementing the scanning feature
  5. Implementing the PDF export feature

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 Document Scanner”).

When your project is ready, go to settings.gradle.kts and add the Maven repositories for our 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:sdk-package-1:6.1.2")
    implementation("io.scanbot:rtu-ui-v2-bundle:6.1.2")
    implementation("io.scanbot:sdk-multitasktext-assets:6.1.2")

Sync the project.

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

Unfortunately, a breaking change in the ConstraintLayout library version 2.2.0, which is used in templates in the latest Android Studio version, makes it incompatible with our SDK. We’ll address this in the upcoming versions of the RTU UI.

For now, please downgrade the ConstraintLayout library to version 2.1.4. To do this, replace the existing ConstraintLayout version in libs.versions.toml with the following:

constraintlayout = "2.1.4"

We need to access the device camera to scan documents. Therefore, 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">

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

    <application
    ...

Step 2: Initialize the SDK

Before we can use the Scanbot Document 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.androiddocumentscanner, 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.ScanbotSDKInitializer

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

class ExampleApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        ScanbotSDKInitializer()
            // 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.androiddocumentscanner and use that ID for generating 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 start a document scanner from the main screen.

For this tutorial, we’re going to go with a single-button layout, which you can copy and paste 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_scan_document"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:text="Scan document"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


</androidx.constraintlayout.widget.ConstraintLayout>

Next, we’ll connect the button with our RTU UI’s scanning screen.

Step 4: Implement the scanning feature

Go to MainActivity.kt and add the necessary imports:

import android.widget.Button
import androidx.activity.result.ActivityResultLauncher
import io.scanbot.sdk.ScanbotSDK
import io.scanbot.sdk.docprocessing.Document
import io.scanbot.sdk.ui_v2.common.activity.registerForActivityResultOk
import io.scanbot.sdk.ui_v2.document.DocumentScannerActivity
import io.scanbot.sdk.ui_v2.document.configuration.DocumentScanningFlow

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

class MainActivity : AppCompatActivity() {

    // Add the private property here:
    private lateinit var documentScreenLauncher: ActivityResultLauncher<DocumentScanningFlow>

    override fun onCreate(savedInstanceState: Bundle?) {
    ...

Next, in the onCreate() method of your Activity, we need to initialize the documentScreenLauncher and define the callback that will be called when the Document Scanner UI is closed:

        // ... paste after the existing code in onCreate():
        documentScreenLauncher =
            registerForActivityResultOk(DocumentScannerActivity.ResultContract(this)) {
                    resultEntity: DocumentScannerActivity.Result ->
                resultEntity.result?.let {
                    processDocumentResult(it)
                }
            }

We also need to create the processDocumentResult() method, where we’ll handle the result in step 5 of this tutorial:

    // Outside of onCreate():
    private fun processDocumentResult(it: Document) {
        // TODO: We will handle the result in step 5.                
    }

Also in the onCreate() method, we set up an OnClickListener for our Scan document button. When the button is clicked, it should launch documentScreenLauncher using a configuration object:

        // ... paste after the existing code in onCreate():
        findViewById<Button>(R.id.btn_scan_document).setOnClickListener {
            val configuration = DocumentScanningFlow().apply {
                // Customize text resources, behavior and UI:
                // ...
            }
            documentScreenLauncher.launch(configuration)
        }

In this tutorial, we use a default configuration object. It will start the Document Scanner UI with the default settings: in multi-page scanning mode with an acknowledge screen (at which point the SDK’s Document Quality Analyzer checks the scans quality) after scanning each page. You can customize the UI and behavior of the Document Scanner by modifying the configuration object. For more information on how to customize the Document Scanner UI, please refer to the RTU UI documentation.

If you want, you can now run the app to try out the scanner without the PDF export feature.

Step 5: Implement the PDF export feature

As it stands, nothing will happen when you submit the document on the review screen, since we didn’t implement the callback yet. Let’s change that by adding a method to handle the result of the Document Scanner U. It will export the scanned document as a PDF that the user can then share.

You’ll need the following imports:

import android.content.Intent
import androidx.core.content.FileProvider
import androidx.core.net.toFile
import io.scanbot.sdk.ScanbotSDK

First, lets return to our processDocumentResult(...) method and use the Scanbot SDK PDF renderer to create a PDF from the scanned images:

 private fun processDocumentResult(it: Document) {
        val pdfRenderer = ScanbotSDK(this).createPdfRenderer()
        pdfRenderer.render(it)

        val pdfUri = it.pdfUri
 }

If you want to work with the PDF in your app, you can use the pdfUri directly.

But if you want to share the file, you can add the following code to the processDocumentResult(...) method:

// Paste inside processDocumentResult() after the pdfUri variable is created:
val contentUri = FileProvider.getUriForFile(this, "${packageName}.fileprovider", pdfUri.toFile())
val shareIntent = Intent(Intent.ACTION_SEND).apply {
    type = "application/pdf"
    putExtra(Intent.EXTRA_STREAM, contentUri)
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(Intent.createChooser(shareIntent, "Share PDF"))

You’ll notice that we use a FileProvider to get a content:// URI for the PDF file. This is necessary because the PDF file is stored in the app’s private storage and can’t be shared directly. To use a FileProvider, we also need to add a provider in AndroidManifest.xml, inside the <application> tag:

<application>
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

Finally, we need to create a file_paths.xml file in app/res/xml and add the following content:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="pdfs" path="." />
</paths>

Now users can share a scanned document as a PDF file and use it as they see fit. For example, they can send it via email or save it to a cloud storage.

And that’s it! You’ve successfully integrated a fully functional document scanner into your app 🎉

You can even crop and rotate your scans and change their order in a multi-page document.

Happy scanning! 🤳

Conclusion

If this tutorial has piqued your interest in integrating document scanning functionalities into your Android app, make sure to take a look at the other neat features in the Android Document Scanner SDK’s 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.