Three Tips for Publishing a Modern Android SDK

Tore
Thu Apr 22 2021
ANDROID-APP-DEVELOPMENT SDK KOTLIN

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

Explore Statsig’s smart feature gates with built-in A/B tests, or create an account instantly and start optimizing your web and mobile applications. You can also schedule a live demo or chat with us to design a custom package for your business.

MORE POSTS

Recently published

My Summer as a Statsig Intern

RIA RAJAN

This summer I had the pleasure of joining Statsig as their first ever product design intern. This was my first college internship, and I was so excited to get some design experience. I had just finished my freshman year in college and was still working on...

Read more

Long-live the 95% Confidence Interval

TIMOTHY CHAN

The 95% confidence interval currently dominates online and scientific experimentation; it always has. Yet it’s validity and usefulness is often questioned. It’s called too conservative by some [1], and too permissive by others. It’s deemed arbitrary...

Read more

Realtime Product Observability with Apache Druid

JASON WANG

Statsig’s Journey with Druid This is the text version of the story that we shared at Druid Summit Seattle 2022. Every feature we build at Statsig serves a common goal — to help you better know about your product, and empower you to make good decisions for...

Read more

Quant vs. Qual

MARGARET-ANN SEGER

💡 How to decide between leaning on data vs. research when diagnosing and solving product problems Four heuristics I’ve found helpful when deciding between data vs. research to diagnose + solve a problem. Earth image credit of Moncast Drawing. As a PM, data...

Read more

The Importance of Default Values

TORE

Have you ever sent an email to the wrong person? Well I have. At work. From a generic support email address. To a group of our top customers. Facepalm. In March of 2018, I was working on the games team at Facebook. You may remember that month as a tumultuous...

Read more
ANNOUNCEMENT

CUPED on Statsig

CRAIG

Run experiments with more speed and accuracy We’re pleased to announce the rollout of CUPED for all our customers. Statsig will now automatically use CUPED to reduce variance and bias on experiments’ key metrics. This gives you access to a powerful experiment...

Read more

We use cookies to ensure you get the best experience on our website.

Privacy Policy