Mobile Development 22 min read

MMKV‑Kotlin: A Kotlin Multiplatform Key‑Value Storage Library – Design, Usage, Testing and Maven Publishing

This article introduces MMKV‑Kotlin, a Kotlin Multiplatform wrapper for Tencent's high‑performance MMKV key‑value storage, covering its background, simple integration steps, architectural decisions, platform‑specific implementations, comprehensive unit and instrumented testing, and the process of publishing the library to Maven Central.

Ctrip Technology
Ctrip Technology
Ctrip Technology
MMKV‑Kotlin: A Kotlin Multiplatform Key‑Value Storage Library – Design, Usage, Testing and Maven Publishing

The Ctrip flight mobile team has been using Kotlin Multiplatform (KMM) since 2021 and needed a cross‑platform KV storage solution; they chose Tencent's open‑source MMKV for its performance, multi‑process support, and cross‑platform consistency.

Simple usage

Add the appropriate dependency in the common source set:

dependencies {
    implementation("com.ctrip.flight.mmkv:mmkv-kotlin:1.0.0")
}

For pure Android projects:

dependencies {
    implementation("com.ctrip.flight.mmkv:mmkv-kotlin-android:1.0.0")
}

Initialize MMKV on each platform. Android requires a Context :

import com.ctrip.flight.mmkv.initialize

fun initializeMMKV(context: Context) {
    val rootDir = initialize(context)
    Log.d("MMKV Path", rootDir)
}

iOS initialization uses a root directory string:

import com.ctrip.flight.mmkv.initialize

fun initializeMMKV(rootDir: String) {
    initialize(rootDir)
    Log.d("MMKV Path", rootDir)
}

Basic read/write operations mirror MMKV’s Java/Objective‑C APIs:

import com.ctrip.flight.mmkv.defaultMMKV

fun demo() {
    val kv = defaultMMKV()
    kv.set("Boolean", true)
    kv.set("Int", Int.MIN_VALUE)
    kv.set("String", "Hello from mmkv")
    println("Boolean: ${kv.takeBoolean("Boolean")}")
    println("Int: ${kv.takeInt("Int")}")
    println("String: ${kv.takeString("String")}")
}

Architecture design

MMKV core is written in C++ and provides memory‑mapped file storage, protobuf serialization, and multi‑process capabilities. Platform‑specific wrappers expose the core to Java (Android), Objective‑C (iOS), Dart, and JavaScript. MMKV‑Kotlin adds a thin layer that forwards calls to the native MMKV instances while keeping a unified API.

The common MMKV_KMP interface is defined as:

interface MMKV_KMP {
    operator fun set(key: String, value: String): Boolean
    operator fun set(key: String, value: Boolean): Boolean
    fun takeString(key: String, default: String = ""): String
    fun takeBoolean(key: String, default: Boolean = false): Boolean
    fun close()
    // ... other functions and properties
}

Android implementation delegates to the Java MMKV API:

class MMKVImpl internal constructor(val platformMMKV: MMKV) : MMKV_KMP {
    override fun set(key: String, value: String) = platformMMKV.encode(key, value)
    override fun set(key: String, value: Boolean) = platformMMKV.encode(key, value)
    override fun takeString(key: String, default: String) = platformMMKV.decodeString(key, default) ?: default
    override fun takeBoolean(key: String, default: Boolean) = platformMMKV.decodeBool(key, default)
    override fun close() = platformMMKV.close()
    // ... other functions
}

iOS implementation uses the Objective‑C MMKV API:

class MMKVImpl internal constructor(val platformMMKV: MMKV) : MMKV_KMP {
    override fun set(key: String, value: Int) = platformMMKV.setInt32(value, key)
    override fun set(key: String, value: Boolean) = platformMMKV.setBool(value, key)
    override fun takeString(key: String, default: String) = platformMMKV.getStringForKey(key, default) ?: default
    override fun takeBoolean(key: String, default: Boolean) = platformMMKV.getBoolForKey(key, default)
    override fun close() = platformMMKV.close()
    // ... other functions
}

Factory functions created via expect/actual return a MMKV_KMP instance after constructing the platform‑specific MMKV object.

Unit testing

Common tests are written with kotlin-test and cover CRUD operations, default values, and type‑specific behavior. Example test class:

class MMKVKotlinTest {
    companion object { const val KEY_NOT_EXIST = "Key_Not_Exist" }
    lateinit var mmkv: MMKV_KMP
    fun setUp() { mmkv = mmkvWithID("unitTest", cryptKey = "UnitTestCryptKey") }
    fun tearDown() { mmkv.clearAll() }
    fun testBoolean() {
        assertEquals(true, mmkv.set("Boolean", true))
        assertEquals(true, mmkv.takeBoolean("Boolean"))
        assertEquals(false, mmkv.takeBoolean(KEY_NOT_EXIST))
        assertEquals(true, mmkv.takeBoolean(KEY_NOT_EXIST, true))
    }
    // ... other type tests
}

iOS uses @BeforeTest / @AfterTest annotations, while Android requires instrumented tests because the native .so cannot run on the host JVM. Android instrumented test example:

@RunWith(AndroidJUnit4ClassRunner::class)
@SmallTest
class MMKVKotlinTestAndroid {
    private lateinit var mmkvTest: MMKVKotlinTest
    @Before
    fun setUp() {
        val context = ApplicationProvider.getApplicationContext
()
        initialize(context)
        mmkvTest = MMKVKotlinTest().apply { setUp() }
    }
    @After
    fun tearDown() { mmkvTest.tearDown() }
    @Test
    fun testCommon() = with(mmkvTest) { testBoolean() /* ... */ }
    // ... IPC and Parcelable tests
}

Maven Central publishing

The library is released to Maven Central using the maven-publish and signing plugins. The publishing block configures Javadoc, POM metadata, repository credentials, and GPG signing:

publishing {
    publications.withType
{
        artifact(javadocJar)
        pom { /* pom settings */ }
    }
    repositories {
        maven {
            credentials { username = NEXUS_USERNAME; password = NEXUS_PASSWORD }
            url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2")
        }
    }
    signing { sign(publishing.publications) }
}

Only the release variant is published for Android, while iOS produces three klib artifacts (iosArm64, iosSimulatorArm64, iosX64). The article also notes a pitfall where overriding artifactId does not affect the Android artifact.

Future plans

MMKV‑Kotlin now supports macOS (Intel and Apple‑silicon) via additional Maven coordinates. Support for other Apple platforms (watchOS, tvOS) is under investigation, while Windows and Linux are not planned due to limited Kotlin/Native C++ interop. The Ctrip team will continue to evolve the library alongside MMKV and Kotlin updates.

iOSAndroidunit testingKotlin MultiplatformKey-Value StorageMaven PublishingMMKV
Ctrip Technology
Written by

Ctrip Technology

Official Ctrip Technology account, sharing and discussing growth.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.