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
- Android Studio 3.0: it is a preview version that features support for the Kolin language.
- Dynamsoft Barcode SDK for Android: the SDK package contains a DynamsoftBarcodeReader.aar file.
A Simple Android Barcode Reader
Create a new Android project includes Kotlin support
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:
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()
}
}
}