Three Tips for Publishing a Modern Android SDK

Thu Apr 22 2021

Tore Hanssen

Software Engineer, Statsig

Develop in Kotlin, Test using mockk, and Publish with JitPack

1. Develop in Kotlin

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.

Challenges — Java Interop

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, )

2. Test using mockk

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 )) }

3. Publish with JitPack

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!

Try Statsig Today

Get started for free. Add your whole team!
We use cookies to ensure you get the best experience on our website.
Privacy Policy