Publishing an SDK with SKIE and KMMBridge

Author: Kevin Galligan
SKIE does an amazing job of improving the Swift-side of a Kotlin API, but it does change your types. How do you safely integrate SKIE into existing code? How do you avoid impacting other developers on your team?

One of the most important factors in a successful shared-code implementation is the quality of the API presented. Specifically, what is the experience of a developer calling Kotlin from Swift? Swift interop with Kotlin is amazing, but only relative to other options. The loss of expressive features is a main complaint of iOS developers who are presented with KMP, and this is not simply an aesthetic complaint.

SKIE bridges some important Kotlin features to Swift, in a form that is natural and functional to Swift. That makes writing the API easier for Kotlin devs, and using the API a better experience for Swift devs.

Last year we released KMMBridge to make publishing an iOS Framework easier for KMP teams. We have a Kick Start template repo that is a very basic example of how to publish an SDK. In this post, we’re going to add some new features to that template project, using SKIE to produce a better end result.

For more detailed background on KMMBridge and the kick start sample, see Quick Start with KMMBridge.

Getting Started

Clone the GitHub repo with the updated KMMBridge Kick Start. We will eventually merge this with the main Kick Start sample, but for now grab the following example:

kpgalligan/KMMBridgeKickStartSKIE

Open that repo in Intellij or Android Studio.

Original SDK

The sample publishes 2 modules. One for analytics, and one for dog breed data. This code is basically a trimmed down version of KaMPKit. We grab and cache dog breed info the Dog CEO API. The user can mark dog breeds as favorites.

Both of these modules are published independently for Android consumers, and an umbrella module is created for iOS consumers. That umbrella module is published as an Xcode Framework.

The original SDK is very basic. The BreedRepository provided a Flow with a List<Breed> objects as it’s subject. This flow is updated as the local database is updated. The repo also has some functions to let you refresh data and update favorite values.

For an Android consumer, the exposed API includes Corotines-aware structures. That is natural for a Kotlin consumer. On the iOS side, we need to adapt those endpoints because, while they will “compile”, trying to call them directly can be problematic.

In the original version, we did this by creating a delegate repositry