Flying the Kotlin Spaceship at Twilio

October 31, 2017
Written by

kotlin

At Google I/O 2017 Google announced official support for the Kotlin programming language. Mostly because Kotlin is a friendly modern language with immense expressive power, functional programming capabilities, lambda functions support, powerful type-inference and analysis capabilities with quite ergonomic syntactic sugar.

Why Kotlin?

The language has been in development for a few years now and has interoperability with existing Java code so you can call Java code from Kotlin and vice-versa. It has excellent tooling support with Android Studio and Gradle plugins as well as debugger integration.

How Twilio Uses Kotlin

The Twilio Chat Android SDK was written in Java with some JNI bridging to C libraries provided by Twilio to give a handy package with native look and feel.

The Chat Demo application was also written in Java which made it a hard to follow with all the Chat SDK usage details behind a lot of Java boilerplate.

So we set a goal to fix this and make the demo application more transparent so users could focus on SDK usage examples rather than trying to untangle Java code.

A longer-term goal is to convert the SDK code to Kotlin to reduce the boilerplate amount and improve maintainability.

How we did it?

First we installed the new Android Studio 3.0 – it looks much cleaner than the old 2.0 series and also has fully functional support for Kotlin.

Then, open a Java project with it and go to Tools > Kotlin > Configure Kotlin in project command. This will add directives to enable Kotlin support in the project and synchronize it with these changes. Now we’re able to write and compile Kotlin.

Now for the the most exciting part. Open any Java file in the project and go to Code > Convert Java File to Kotlin File. This will automatically convert the Java code to Kotlin.

The conversion process tries to stay as close to original Java structure as possible while also using several idiomatic Kotlin constructs to make the code cleaner.

The result output of the plugin can be immediately compiled, so you can test conversion file-by-file.

Interesting parts

Refactoring Java code to Kotlin conventions

While direct automatic translation is easy, Kotlin has a few idiomatic approaches to coding that may help produce cleaner code.

Autogenerated UI element accessors

Let’s look at this code as an example. Synthetic properties generated by Kotlin let you access your XML-defined elements by their ID as if they were normal constants in your code. See usage examples here and here.

apply() is great!

apply() is an extension method available for all classes. It simply captures the object and lets you execute a block of code within this object’s context so the following Java code:

JSONObject item = new JSONObject();
item.put("turn", intToSymbol(newVal));
JSONArray loc = new JSONArray();
loc.put(position / 3);
loc.put(position % 3);
item.put("location", loc);
item.put("when", new Date().getTime() / 1000);

Becomes this block of code:

val item = JSONObject().apply {
    put("turn", intToSymbol(current))
    put("location", JSONArray().apply {
        put(position / 3)
        put(position % 3)
    })
    put("when", Date().time / 1000)
}

It’s much better when you have to call multiple methods on a temporary object like above.

Anko is awesome

You can read about anko here and here but what anko does is provide a bunch of helpers that make Kotlin developer’s life overall enjoyable more than you could’ve imagined.

Anko is quite helpful for defining clean no-XML-included views for your application programmatically. It especially shines with Alert dialog creation:

alert("Update friendly name") {
    customView {
        val friendly_name = editText { text.append(channel.friendlyName) }
        positiveButton("Update") {
            val friendly_str = friendly_name.text.toString()
            channel.setFriendlyName(friendly_str, ToastStatusListener(
                    "Successfully changed name", "Error changing name"))
        }
        negativeButton("Cancel") {}
    }
}.show()

You can have a look at our old Java code and the associated XML file. Anko needed none of the XML and the code is super-clean!

Activity transitions? Just use Anko to simplify them along with service intent invocation:

startActivity<MessageActivity>(
    Constants.EXTRA_CHANNEL to it,
    Constants.EXTRA_CHANNEL_SID to it.sid)

This creates an intent and sets some intent extras needed to start this activity.

Or to start a service:

startService<MediaService>(
    MediaService.EXTRA_ACTION to MediaService.EXTRA_ACTION_UPLOAD,
    MediaService.EXTRA_CHANNEL to channel as Parcelable,
    MediaService.EXTRA_MEDIA_URI to data?.data.toString())

Listener callbacks

Listener callbacks are best when passed as lambdas in the last method parameter. You can rewire the API a bit using extension methods or wrapper objects if you use them.

Here are a few helpers that make setting listeners on SDK methods a much more pleasant experience.

JavaScript support

Wait, what? Yes, you can do web programming in Kotlin too. Material for a possible future post, but check out what JetBrains did with it – Kotlin backend and React frontend all built with one language, sweet!

Kotlin All the Things!

Overall, Kotlin code is a lot easier to write and much more pleasant to read afterwards, so give it a go and share your experience in the comments!

Let me know what you’re using Kotlin for, contact me via:
Email: berkus@twilio.com
GitHub: berkus