Uploading images in Kotlin Multiplatform

I’ve been working on sharing logic between Android and iOS and I’d like to share my experience with working with images in a platform agnostic way.

Introduction

Kotlin Multiplatform lets you share non platform specific logic ( “non UI code”) between different platforms (Android, jvm, js, iOS, macOS, etc…) and gives you the possibility of creating abstractions over platform specific logic.
I won’t dive into more detail about the technology, you can read more about it here.

Context

The feature was about uploading an application, with an icon and screenshots. Check out the final versions:

Additionally my goal was to test out Kotlin Multiplatform with the following technical decisions:

  • A shared ViewModel layer
  • Unidirectional data flow

Practically this means, that all the icons, screenshots you see above will be part of the state stored in a shared ViewModel, with the following events:

  1. All platforms submit their platform specific representation of the selected image
  2. The ViewModel works with these images in a platform agnostic way
  3. All platforms receive back the platform specific representation of the image and show it on the UI

Implementation

Kotlin Multiplatform is really clever and it lets us create the platform agnostic abstractions with an expected declaration that needs to have an actual implementation (read more about expect/actual).

Since the image will travel frequently from platform specific to platform agnostic code, I had a strong feeling, that because of the unidirectional pattern of the code, I’ll face two unpleasant issues:

  1. Platform specific information will be lost
  2. I’ll need to use some primitives (like bytes) and do some ugly conversions

It turned out KMP is neater than I’ve expected and I didn’t have to do either of those.

The Code

As I’ve mentioned earlier we need to make a platform agnostic abstraction for the images and we’ll need a way to convert these images into bytes before uploading it to the backend:

We could move the toByteArray() inside our ImageFile class, but instead we’d like to leverage typealiases , when defining the actual implementations for the platforms:

iOS
macOS
Android

The neat part is, that since we are using typealiases for the actual implementations, all the platforms have the freedom to submit their native implementation of the ImageFile and the updated state from the ViewModel will contain it without any information loss:

Yes, cross-platform frameworks may be okay(ish), but show me a technology that can achieve this level of interoperability between platforms 🚀

For sending out the request, I’ve used Ktor as it provides a seamless way for sharing the network layer between different platforms:

If you’d like to check out the full project: https://github.com/halcyonmobile/MultiplatformPlayground

Senior Android Developer — Contractor — Freelancer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store