Mixing Kotlin and Java to Build Android Barcode Reader

Last week I made a warm up for Kotlin, getting started to learn tutorials and reference. Now it is time to take the next step. Since Kotlin is hundred percent compatible with Java, we can use both programming languages without barriers in one project. In this article, I want to share how to build an Android barcode reader using Kotlin code and Java code.

Prerequisites

A Simple Android Barcode Reader

Create a new Android project includes Kotlin support

Kotlin new Android project

Add an AAR file to Android project

There are two ways to add the dependency DynamsoftBarcodeReader.aar to your project.

Import the AAR file as a module

Create a new module to import *.aar file:

Kotlin import Android AAR

Then open project structure (Ctrl + Alt + Shift +S) to add module dependency.

Manually edit the build.gradle file

Open app/build.gradle to add following code:

allprojects {
    repositories {
        flatDir {
            dirs 'libs'
        }
    }
}
dependencies {
    compile(name:'DynamsoftBarcodeReader', ext:'aar')
}

Create and initialize UI elements

Open default layout file res/activity_main.xml to add a Button and a TextView:

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/bt_read_barcode"/>
    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>

If you are familiar with Android, you should know that we can get the view references in function onCreate(). Here is the Java code:

private TextView mTextView;
private Button mButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mButton = (Button) findViewById(R.id.button);
    mTextView = (TextView)findViewById(R.id.text);
}

How to convert the Java code to Kotlin code? For beginners who have no idea how to write the code from scratch, just press ‘Ctrl + Alt + Shift +K’ to use the auto-conversion tool.

private var mTextView: TextView? = null
private var mButton: Button? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    mButton = findViewById(R.id.button) as Button
    mTextView = findViewById(R.id.text) as TextView
}

Not like Java, Kotlin uses ‘type ?’ to declare a nullable type. Now let’s add a click event. According to my experience, I wrote the Kotlin code as follows at the first time:

mButton.setOnClickListener // Error

I got the error message “smart cast to ‘Button’ is impossible, because ‘mButton’ is a mutable property that could have been changed by this time.”

To make the code work, I have to use the !! operator which returns a non-null value of mButton.

mButton!!.setOnClickListener // OK

Is it possible to make the syntax look like Java? We can declare late-initialized properties:

private lateinit var mTextView: TextView
private lateinit var mButton: Button

In this way, we can avoid null check when calling the method:

mButton.setOnClickListener // OK

Call barcode reading Activity

The barcode detection Activity, written in Java, is originally from the open source code of Dynamsoft Barcode Scanner. We just need to create an intent to start the barcode Activity and display the returned results:

mButton.setOnClickListener {
    val license: String = "AA721B9FAB21454427702FE780B56C50"
    val cameraIntent = Intent(baseContext, DBR::class.java)
    cameraIntent.action = DBR.ACTION_BARCODE
    cameraIntent.putExtra("license", license)

    // avoid calling other phonegap apps
    cameraIntent.`package` = baseContext.getPackageName()

    startActivityForResult(cameraIntent, REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (requestCode === REQUEST_CODE) {
        if (resultCode === Activity.RESULT_OK) {
            // https://kotlinlang.org/docs/reference/null-safety.html
            val result = data?.getStringExtra("SCAN_RESULT")
            val format = data?.getStringExtra("SCAN_RESULT_FORMAT")
            // https://stackoverflow.com/questions/33164886/android-textview-do-not-concatenate-text-displayed-with-settext
            mTextView.text = getString(R.string.barcode_result, result, format)
        } else if (resultCode === Activity.RESULT_CANCELED) {
            Toast.makeText(baseContext, "Cancelled", Toast.LENGTH_LONG).show()
        } else {
            Toast.makeText(baseContext, "Unexpected error", Toast.LENGTH_LONG).show()
        }
    }
}

Run the app

Kotlin Android barcode scan

Kotlin Android Barcode reader

Source Code

https://github.com/dynamsoft-dbr/kotlin-android