Anyone doing Android development in 2021 and beyond should strongly consider using Kotlin. Here are a few of the key features and reasons we chose to use Kotlin:
Safety: primarily null safety, which Kotlin’s type system is designed around
Async Programming: Kotlin Coroutines and support for async/await make asynchronous programming simpler, removing scattered callbacks and boilerplate AsyncTasks
Style: Kotlin is nicer to read and write. Data classes, singleton objects, etc. are much less verbose
Java Interop: Java programs can call into Kotlin libraries, and vice versa. Without this, building a Kotlin SDK would be a nonstarter
Still not sure about using Kotlin in your Android app? Check out the Android Kotlin documentation.
We’ve tested our SDK in Android apps written in both Kotlin and Java. One of the main requirements for our SDK was to cover both. Kotlin makes this easy — you can still use core java libraries in Kotlin, and in Java you can call into Kotlin libraries as well. So even though we chose to write our SDK in Kotlin, any developer can use our SDK in their app. Exposing Java static methods via @JvmStatic and generating overloads for Java using @JvmOverloads was trivial, but there was one tricky feature to get working seamlessly in both Java and Kotlin: callbacks.
Since our SDK was written in Kotlin, I first defined the initialization function signature like this, with a callback as the final parameter:
@JvmOverloads
@JvmStatic fun initialize(
application: Application,
sdkKey: String,
callback: () -> Unit) {
Notice that Kotlin doesn’t have a void return type — void functions return type “Unit”. When I tested this with an app written in Kotlin, it was simple:
Statsig.initialize(
this.application,
"<CLIENT_SDK_KEY>",
::onStatsigInitialized,
)
In Java, it didn’t work out of the box. It didn’t like the missing Unit type. When I first tried to integrate the SDK, I got an error:
Function0 is not a functional interface
After some investigating, I found a good way to avoid this (without requiring people to import the Kotlin standard library in their Android app), and landed on this Functional Interface:
@FunctionalInterface
interface StatsigCallback {
fun onStatsigReady()
}
Now, our Java client could use the SDK:
Statsig.initialize(
app,
"<CLIENT_SDK_KEY>",
this::onStatsigReady,
);...private void onStatsigReady() {
// check gates/configs and log events
}
And in Kotlin, it looks like this:
val callback = object : StatsigCallback {
override fun onStatsigReady() {
// check gates/configs and log events
}
}Statsig.initialize(
this.application,
"<CLIENT_SDK_KEY>",
callback,
)
Coming from Android java development, I immediately gravitated towards the mockito-kotlin library, which was created to provide a bridge between Kotlin and Mockito. I quickly found its limitations when I was unable to mock companion objects and their methods (think “static” methods in java).
For that reason, I recommend the mockk library instead. It’s a Kotlin-first solution to testing a Kotlin codebase, and provides support for Kotlin-language specific implementations which you might not be able to easily test using mockito (like companion objects, or coroutines). The syntax is a bit different than mockito, but you’ll pick it up quickly enough.
I used mockk to mock out the network request helper I built (which was a Kotlin object, and difficult to mock otherwise). Mockk simplified it to a few lines:
mockkObject(StatsigNetwork)
every {
// accept any parameters to mock all calls
StatsigNetwork.apiPost(any(), any(), any(), any(), any())
} answers {
val callback = lastArg<(InitializeResponse?) -> Unit>()
callback(InitializeResponse(
... // hard code the network response
))
}
Once the SDK was complete, tested, and working in Kotlin and Java, I wanted to find the right place to publish it. So of course, I looked to JCenter and Maven Central first. JCenter is being sunset, and would only serve our SDK for less than a year! MavenCentral was the next logical choice, but I also found JitPack. It seemed to fit more with our model for distributing javascript SDKs, where versions in github were tracked by version tags. JitPack allows us to manage our Android SDK the same way. Actually, it’s even easier than our javascript SDKs because we don’t have to separately publish the package to NPM! JitPack serves our SDK versions based purely on git tags, and git tags mark the state of the repo at a particular version.
So there you have it — a few tips and tricks for writing a modern Android library. Feel free to check out our SDK on github if you want to dig into the code even more.
Happy coding!
The Statsig <> Azure AI Integration is a powerful solution for configuring, measuring, and optimizing AI applications. Read More ⇾
Take an inside look at how we built Statsig, and why we handle assignment the way we do. Read More ⇾
Learn the takeaways from Ron Kohavi's presentation at Significance Summit wherein he discussed the challenges of experimentation and how to overcome them. Read More ⇾
Learn how the iconic t-test adapts to real-world A/B testing challenges and discover when alternatives might deliver better results for your experiments. Read More ⇾
See how we’re making support faster, smarter, and more personal for every user by automating what we can, and leveraging real, human help from our engineers. Read More ⇾
Marketing platforms offer basic A/B testing, but their analysis tools fall short. Here's how Statsig helps you bridge the gap and unlock deeper insights. Read More ⇾