Getting started
Requirements:
- Latest Android Studio version with Android SDK installed
- Android device running Android 5.0 or later
Android Studio is the most commonly used IDE for developing Android applications. Alternatively, you could use IntelliJ IDEA. In this tutorial, we will only use standard Android SDK features – and the Scanbot SDK.
Create a “Hello World” Android app
In Android Studio, create a blank project. To do that, go to File ➜ New ➜ New Project. Then, select the Empty Activity project template – we won’t need any complex UI or special features.
On the next screen, choose io.example.myapplication
as the package name, then press Finish.
Android Studio will now generate a simple Android project for you.
Note: Make sure that the option Use legacy android.support.libraries is unchecked and that Android Studio generates the Android project using the new AndroidX libraries.
Currently, the lowest version of the Android SDK supported by our Scanbot SDK is 5.0 (API Level 21). Select a larger value if you want to restrict users with outdated OS versions from installing your app.
Test run
First, connect a mobile device via USB (ADB debugging needs to be enabled). Alternatively, you can use Android Studio’s built-in Android emulator. However, a physical device is recommended to make use of its camera hardware.
Select your device or emulator in the navigation bar and press the Run button.
You should now see an empty app with a simple “Hello World!” message running on your device.
Add the Scanbot SDK dependencies
Next, we will add the Scanbot Scanner SDK for Android dependency, which comes as a set of Gradle modules. Gradle dependencies let you quickly integrate and update third-party libraries that simplify access to native system APIs like camera, network, or battery status, as well as third-party platform SDKs like Firebase.
For more details about Gradle dependencies, refer to the Android documentation’s “Build dependencies.”
Now, let’s add the Scanbot SDK modules to our project.
Gradle allows you to pull external dependencies from different repositories. The Scanbot SDK modules are stored on our Nexus repository, and so we need to add it to the list of repositories in the project’s settings.gradle
file.
Add the Scanbot repository under the mavenCentral
and google
repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url 'https://nexus.scanbot.io/nexus/content/repositories/releases/' }
}
We also need to add the Scanbot SDK dependency to the app
module of the application. Depending on the feature set we want, different Gradle dependencies are required.
In this tutorial, we will only use the Document Scanning feature, which means adding the dependency module io.scanbot:sdk-package-1
.
For this, open the build.gradle
file of the app
module.
Add the following line to the file:
implementation "io.scanbot:sdk-package-1:2.2.0"
1.87.1 is the version of the Scanbot SDK for Android we use in this tutorial. You can find the latest version in our changelog.
The Scanbot SDK also provides Ready-to-Use UI (RTU UI) components – Activities that make integrating the scanning features very easy. To use those RTU UI components, also add the following Gradle dependency:
implementation "io.scanbot:sdk-package-ui:2.2.0"
Don’t forget to sync your project every time you add dependencies!
To learn more about other features of the SDK and how to set up each component, please refer to our documentation.
Camera permission and further adjustments
In the app/src/main/AndroidManifest.xml
file, add the CAMERA
permission and declare that the app uses this feature by adding the following:
<manifest ...>
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera"/>
...
</manifest>
Since our application will work with high-resolution images, we strongly recommend adding the property android:largeHeap=”true”
to the <application>
element of the AndroidManifest.xml
file, especially for Android versions lower than 7.x:
<application
android:largeHeap="true"
...>
Processing high-resolution images is a memory-intensive task, and this property will ensure your app is allocated enough heap to avoid OutOfMemoryError
exceptions.
Scanbot SDK:
Unlimited scanning at a fixed price
Your reliable data capture solution for mobile and web app integration.
Supports all common platforms and frameworks.
It’s coding time
Now, let’s write some Kotlin code to put the SDK features to use.
Initialize the Scanbot SDK
Scanbot SDK needs to be initialized to work properly. For that, we will use the class ScanbotSDKInitializer
. The simplest way of doing that is to add it to our Application
class, which is the main entry point of an Android application.
Let’s add a new class ExampleApplication
(New ➜ Kotlin class) and implement it as follows:
package io.example.myapplication
import android.app.Application
import io.scanbot.sdk.ScanbotSDKInitializer
class ExampleApplication : Application() {
override fun onCreate() {
super.onCreate()
ScanbotSDKInitializer()
.license(this, LICENSE_KEY) // Please add a valid trial license key here. See the notes below!
.initialize(this)
}
}
Now we declare this class in our AndroidManifest.xml
:
<application
android:largeHeap="true"
android:name=".ExampleApplication"
..>
Done! Now, the Scanbot SDK will be initialized immediately after the user opens the app.
Next up: Adding a UI that lets us actually scan something with our new app.
Integrate the Document Scanner UI
As mentioned above, the Scanbot Scanner SDK for Android provides ready-to-use UI components for document scanning. We can easily integrate the screen components with just a few lines of code. We will use the class DocumentScannerActivity
and define our desired configuration with the DocumentScannerConfiguration
class.
First, let’s wrap the SDK Activity
call into a simple function named scanDocument()
– we will bind it to a button later – and add it to our MainActivity
class:
class MainActivity : AppCompatActivity() {
...
private fun startDocument() {
val configuration = DocumentScannerConfiguration()
configuration.setTopBarBackgroundColor(Color.RED)
// It is possible to customize the behavior and appearance of the SDK screen
val docIntent = DocumentScannerActivity.newIntent(this, configuration)
startActivityForResult(docIntent, DOCUMENT_SCANNER_ACTIVITY_REQUEST_CODE)
}
companion object {
const val DOCUMENT_SCANNER_ACTIVITY_REQUEST_CODE = 100
}
}
With DocumentScannerConfiguration
, you can pass config parameters to customize colors, text resources, and the behavior of some Document Scanner features. See our API docs on GitHub for more details.
Now let’s add a button to the layout of our MainActivity
. For simplicity’s sake, we will also replace the ConstraintLayout
with LinearLayout
.
Change src/main/res/layout/activity_main.xml
to look like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/start_scanner_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Start Scanner"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
Next, we will bind our scanDocument()
method as an onClickListener
event to the button we just created in the onCreate
method of our MainActivity
class:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.start_scanner_button).setOnClickListener {
startDocument()
}
}
Let’s run the app and see how the scanning UI looks when scanning a document.
During the first run, the application will ask for permission to access the device’s camera, as it needs it to perform a scan. Our RTU UI components handle camera permissions automatically, so you don’t need to worry about it.
The Document Scanner screen now appears and the software detects the contours of the document. We can also see that the toolbar color is now red, which we set in the configuration.
Note: To keep things simple, we didn’t enable the multipage feature of the Document Scanner (see the config parameter setMultiPageEnabled
, which is false
by default). This means that the scanner UI will automatically close after a single scan.
Next, we will pull the first Page
element from the result array to display the cropped document image.
Let’s proceed!
Process and display the scanned image
After the scan, the Document Scanner Activity
returns an array of Page
objects. These contain all the information about the scanned document.
As usual in Android development, we need to override the onActivityResult
method in the calling Activity
to access its results.
First, we make sure that the call is made from our DocumentScannerActivity
by checking requestCode and resultCode. Then, to access the pages themselves, we need to use the SNAPPED_PAGE_EXTRA
key. In this example, like we said earlier, we are only interested in the first element of the array. We will process the page in the processPagePreview
method later.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == DOCUMENT_SCANNER_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
val snappedPagesExtra = data?.getParcelableArrayExtra(DocumentScannerActivity.SNAPPED_PAGE_EXTRA)
snappedPagesExtra?.get(0)?.let { page ->
processPagePreview(page as Page)
}
}
}
private fun processPagePreview(page: Page) {
// We will implement it later
}
To access the image contained in the Page
object, we need to use the PageFileStorage
class. An instance of it can be created by calling the createPageFileStorage()
in the ScanbotSDK class. The most convenient place to do this is our onCreate
method and saving it as a private property pageFileStorage
.
class MainActivity : AppCompatActivity() {
private lateinit var pageFileStorage: PageFileStorage
override fun onCreate(savedInstanceState: Bundle?) {
...
pageFileStorage = ScanbotSDK(this).createPageFileStorage()
}
To show a preview, we will add an ImageView
widget to our layout. The complete layout of our MainActivity
now looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/start_scanner_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Start Scanner"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/page_preview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
To actually show the image, let’s implement a processPagePreview
method. We can take the image from the pageFileStorage
by a pageId
. Alternatively, we could access the file by URI using the getImageURI
method.
In real applications, there would be more efficient ways of loading images from storage (Glide or Picasso libraries, for example).
private fun processPagePreview(page: Page) {
val imageType = PageFileStorage.PageFileType.DOCUMENT
val filteredPreviewImage = pageFileStorage.getImage(page.pageId, imageType)
val previewWidget = findViewById<ImageView>(R.id.page_preview)
previewWidget.setImageBitmap(filteredPreviewImage)
}
A DOCUMENT
image type is the cropped and perspective-corrected image (hi-resolution), while the ORIGINAL
image is the unprocessed image (hi-resolution). All images are stored as JPG files by default. It’s also possible to access preview images (low-resolution), which should be used as thumbnails and can be displayed by calling getPreviewImage
. See the API docs for more details.
Finally, let’s run our app once more. The cropped image preview now appears in the ImageView
after a successful scan. Congratulations!
Complete example projects
To get off to a flying start, check out the following example project on GitHub:
This project demonstrates the integration of all API methods of the Scanbot SDK for Android, such as Cropping UI, Image Filtering, PDF and TIFF Rendering, Optical Character Recognition, Barcode Scanning, MRZ Scanner and EHIC Scanning. If you want more control over how the scanning screen looks, or more flexibility in the implementation, you can use our Classical Components. You can find an example project for these components here.
Finally, you can find the app we made in this tutorial here.
Scanbot SDK (trial) license key
Please note: Without a license key, the Scanbot SDK will run for one minute per session! After the trial period is up, all Scanbot Scanner SDK functions as well as the UI components will stop working or may be terminated.
You can get an unrestricted, no-strings-attached 7-day trial license for free.
As the Scanbot SDK license key is bound to the Application ID, you will have to use the default generated App Identifier (io.example.myapplication) of this tutorial app. Alternatively, you can use the ID of your app when requesting your trial license. Please note that app IDs are case-sensitive!
Where to find the App Identifier
The application ID is defined in the app/build.gradle
file as applicationId
property:
android {
defaultConfig {
applicationId "io.example.myapplication"
...
}
...
}
Happy coding! 👩💻👨💻
If you need any kind of assistance, feel free to contact one of our experts. Let’s talk.
💡 You can also follow along our tutorial on YouTube!
💡 Did you have trouble with this tutorial?
We offer free integration support for the implementation and testing of the Scanbot SDK. If you encounter technical issues or need advice on choosing the appropriate framework or features, join our Slack or MS Teams or send us an email to receive your free support.