
Cross-end MMKV wrapper enabling shared-layer key-value persistence with native SO/C-interop support, special adaptation for an alternate OS, unified buildchain and simple initialization/publishing.
mmkvKotlin是基于 Kotlin MultiPlatform 技术,对 腾讯开源组件 MMKV 的跨端封装,适用于基于 KMP 平台的跨端工程。
支持平台:
本项目以携程开源的 mmkv-kotlin 为基础,新增了对鸿蒙平台的适配,支持在跨端层使用Kotlin语言进行多平台kv存储读写。
指定仓库
mavenCentral()
添加mmkvKotlin依赖
参考shared模块: 在shared/build.gradle.kts中增加Android/iOS构建目标的commonMain对mmkvKotlin依赖
...
val commonMain by getting {
dependencies {
implementation("com.tencent.kuikly-open:core:${Version.getKuiklyVersion()}")
implementation("com.tencent.kuikly-open:core-annotations:${Version.getKuiklyVersion()}")
implementation("io.github.walkman707:mmkvKotlin:1.0.2")
}
}
...在shared/build.ohos.gradle.kts中增加Ohos构建目标的commonMain对mmkvKotlin依赖
...
val commonMain by getting {
dependencies {
implementation("com.tencent.kuikly-open:core:${Version.getKuiklyOhosVersion()}")
implementation("com.tencent.kuikly-open:core-annotations:${Version.getKuiklyOhosVersion()}")
implementation("io.github.walkman707:mmkvKotlin:1.0.2")
}
}
...:::tip 注意
鸿蒙额外配置:
...
ohosArm64 {
val main by compilations.getting
compilations.forEach {
it.kotlinOptions.freeCompilerArgs += when {
HostManager.hostIsMac -> listOf("-linker-options", "-lmmkv_c_wrapper -L${projectDir}/src/libs/arm64-v8a/")
else -> throw RuntimeException("暂不支持")
}
}
}
...
:::
指定仓库:
mavenCentral()
添加依赖
dependencies {
implementation(libs.mmkv)
} override fun onCreate() {
super.onCreate()
MMKV.initialize(this)
MMKV.defaultMMKV().run {
encode("test", "abcdef")
}
} pod 'MMKV', '1.2.14'
init() {
// 初始化MMKV
initializeMMKV()
}
private func initializeMMKV() {
// 设置MMKV根目录
let rootDir = MMKV.initialize(rootDir: nil)
print("MMKV root directory: \(rootDir)")
// 获取默认MMKV实例
guard let mmkv = MMKV.default() else {
print("Failed to initialize MMKV")
return
}
mmkv.set("abcdef", forKey: "test")
print("MMKV initialized successfully")
// 可选:设置加密密钥(用于敏感数据)
// mmkv.setEncryptKey("your_encryption_key".data(using: .utf8))
}添加依赖
在需要entry模块,添加
"@tencent/mmkv": "~2.2.1"
export default class AbilityState extends AbilityStage {
onCreate(): void {
super.onCreate()
// Napi.initKuikly();
//直接调用鸿蒙版 MMKV 初始化,和 kmp 共用同一个
MMKV.initialize(this.context.getApplicationContext())
MMKV.defaultMMKV().encodeString("test", "abcdef")
hilog.info(0x0000, 'mmkv', MMKV.defaultMMKV().decodeString("test"))
}
}AGP版本
mmkv:2.1.0版本开始,升级了对androidx.annotation的依赖版本到1.9.0。这会触发androidx 高版本的兼容 bug,引发编译错误,需要升级AGP到8.3.0+ 如果业务AGP版本要求低于8.3.0,则可以修改本组件,依赖低版本mmkv组件。
JDK版本 升级AGP到8.3.0+后,则JDK也需要升级到17。
参考本工程,可在gradle.properties中指定gradle java home版本:
org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk-17.0.15.jdk/Contents/Home
.
├── README.md
├── androidApp # mmkvKotlin 使用示例
├── build.gradle.kts # Android/iOS根构建脚本
├── build.ohos.gradle.kts # Ohos根构建脚本
├── buildSrc
├── gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── h5App
├── iosApp # mmkvKotlin 使用示例
├── kotlin-js-store
├── local.properties
├── miniApp
├── mmkvKotlin # mmkvKotlin KMP工程
├── ohosApp # mmkvKotlin 使用示例
├── package.json
├── settings.gradle.kts
├── settings.ohos.gradle.kts
└── shared # Kuikly跨端侧使用mmkvKotlin Demo示例
mmkvKotlin 模块鸿蒙基于cinterop,使用Kotlin语法与MMKV native so(libmmkv.so)进行交互。
MMKV C接口封装
在ohosAPP/mmkv-c-wrapper模块,提供了对libmmkv.so的C接口封装源码。
鸿蒙构建脚本配置
在mmkvKotlin/build.gradle.kts(统一Kotlin编译工具链)或mmkvKotlin/build.ohos.gradle.kts(鸿蒙独立Kotlin编译工具链)中,进行cinterop配置,指定C头文件和SO路径:
ohosArm64 {
val main by compilations.getting
// val devopsFlag = providers.environmentVariable("PIPELINE_ID").orNull != null
val devopsFlag = true
val includeDir = "${rootProject.rootDir}/ohosApp/mmkv_c_wrapper/src/main/cpp/include/"
val soLibDir = if(devopsFlag) {
"${rootProject.rootDir}/shared/src/libs/arm64-v8a"
} else {
"${rootProject.rootDir}/ohosApp/mmkv_c_wrapper/build/default/intermediates/libs/default/arm64-v8a"
}
// 需要在mmkvKotlin里调来自外部C的时候加这个
val interop by main.cinterops.creating {
definitionFile = file("src/nativeInterop/cinterop/interop.def")
includeDirs(includeDir)
extraOpts("-libraryPath", soLibDir)
}
compilations.forEach {
it.kotlinOptions.freeCompilerArgs += when {
HostManager.hostIsMac -> listOf("-linker-options", "-lmmkv_c_wrapper -L${soLibDir}")
else -> throw RuntimeException("暂不支持")
}
// 抑制 NativeApi 提示
it.compilerOptions.options.optIn.addAll(
"kotlinx.cinterop.ExperimentalForeignApi",
"kotlin.experimental.ExperimentalNativeApi",
)
}
}
本组件已发布到各平台标准仓库。如果开发者需要发布到自己私仓,可参考本节指引发布。
配置发布仓库:
修改build.gradle.kts发布仓库配置
publishing {
...
mavenLocal()
// 发布到build/repo目录
// maven {
// url = uri(layout.buildDirectory.dir("repo"))
// }
}
...
}
配置 maven 发布所需参数环境变量
参考KotlinbuildVar.kt
fun MavenPublication.signPublicationIfKeyPresent(project: Project) {
val keyId = getSensitiveProperty(project, "signing_keyId")
val secretKey = getSensitiveProperty(project, "signing_secretKey")
val password = getSensitiveProperty(project, "signing_password")
println("signPublicationIfKeyPresent keyId: $keyId , password: $password , secreckey: $secretKey")
if (!secretKey.isNullOrBlank()) {
project.extensions.configure<SigningExtension>("signing") {
useInMemoryPgpKeys(keyId, secretKey, password)
sign(this@signPublicationIfKeyPresent)
}
}
}配置发布版本:
MavenConfig.VERSION
运行mmkvKotlin模块的 publish任务
:::tip 注意
如果业务mmkvKotlin模块采用鸿蒙独立Kotlin编译工具链方式,则需要在build.gradle.kts中移除ohosArm64 target配置,只对Android/iOS目标进行发布。 Ohos目标发布则需要参考下述方式单独发布。
:::
如果业务mmkvKotlin模块采用独立Kotlin编译工具链方案,则要单独对鸿蒙产物进行发布。
配置发布仓库
修改build.ohos.gradle.kts发布仓库配置
配置 maven 发布所需参数环境变量(同上一步)
配置发布版本:MavenConfig.VERSION_OHOS
注意,Ohos跨端产物必须独立版本号,如本工程是在版本号后增加-ohos标识。如果不独立版本号,在运行上一步安卓/iOS跨端产物发布后,再运行Ohos发布脚本,则分两次发布会引起maven元数据混乱。
运行发布脚本
./gradlew -c settings.ohos.gradle.kts :mmkvKotlin:publish
mmkvKotlin是基于 Kotlin MultiPlatform 技术,对 腾讯开源组件 MMKV 的跨端封装,适用于基于 KMP 平台的跨端工程。
支持平台:
本项目以携程开源的 mmkv-kotlin 为基础,新增了对鸿蒙平台的适配,支持在跨端层使用Kotlin语言进行多平台kv存储读写。
指定仓库
mavenCentral()
添加mmkvKotlin依赖
参考shared模块: 在shared/build.gradle.kts中增加Android/iOS构建目标的commonMain对mmkvKotlin依赖
...
val commonMain by getting {
dependencies {
implementation("com.tencent.kuikly-open:core:${Version.getKuiklyVersion()}")
implementation("com.tencent.kuikly-open:core-annotations:${Version.getKuiklyVersion()}")
implementation("io.github.walkman707:mmkvKotlin:1.0.2")
}
}
...在shared/build.ohos.gradle.kts中增加Ohos构建目标的commonMain对mmkvKotlin依赖
...
val commonMain by getting {
dependencies {
implementation("com.tencent.kuikly-open:core:${Version.getKuiklyOhosVersion()}")
implementation("com.tencent.kuikly-open:core-annotations:${Version.getKuiklyOhosVersion()}")
implementation("io.github.walkman707:mmkvKotlin:1.0.2")
}
}
...:::tip 注意
鸿蒙额外配置:
...
ohosArm64 {
val main by compilations.getting
compilations.forEach {
it.kotlinOptions.freeCompilerArgs += when {
HostManager.hostIsMac -> listOf("-linker-options", "-lmmkv_c_wrapper -L${projectDir}/src/libs/arm64-v8a/")
else -> throw RuntimeException("暂不支持")
}
}
}
...
:::
指定仓库:
mavenCentral()
添加依赖
dependencies {
implementation(libs.mmkv)
} override fun onCreate() {
super.onCreate()
MMKV.initialize(this)
MMKV.defaultMMKV().run {
encode("test", "abcdef")
}
} pod 'MMKV', '1.2.14'
init() {
// 初始化MMKV
initializeMMKV()
}
private func initializeMMKV() {
// 设置MMKV根目录
let rootDir = MMKV.initialize(rootDir: nil)
print("MMKV root directory: \(rootDir)")
// 获取默认MMKV实例
guard let mmkv = MMKV.default() else {
print("Failed to initialize MMKV")
return
}
mmkv.set("abcdef", forKey: "test")
print("MMKV initialized successfully")
// 可选:设置加密密钥(用于敏感数据)
// mmkv.setEncryptKey("your_encryption_key".data(using: .utf8))
}添加依赖
在需要entry模块,添加
"@tencent/mmkv": "~2.2.1"
export default class AbilityState extends AbilityStage {
onCreate(): void {
super.onCreate()
// Napi.initKuikly();
//直接调用鸿蒙版 MMKV 初始化,和 kmp 共用同一个
MMKV.initialize(this.context.getApplicationContext())
MMKV.defaultMMKV().encodeString("test", "abcdef")
hilog.info(0x0000, 'mmkv', MMKV.defaultMMKV().decodeString("test"))
}
}AGP版本
mmkv:2.1.0版本开始,升级了对androidx.annotation的依赖版本到1.9.0。这会触发androidx 高版本的兼容 bug,引发编译错误,需要升级AGP到8.3.0+ 如果业务AGP版本要求低于8.3.0,则可以修改本组件,依赖低版本mmkv组件。
JDK版本 升级AGP到8.3.0+后,则JDK也需要升级到17。
参考本工程,可在gradle.properties中指定gradle java home版本:
org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk-17.0.15.jdk/Contents/Home
.
├── README.md
├── androidApp # mmkvKotlin 使用示例
├── build.gradle.kts # Android/iOS根构建脚本
├── build.ohos.gradle.kts # Ohos根构建脚本
├── buildSrc
├── gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── h5App
├── iosApp # mmkvKotlin 使用示例
├── kotlin-js-store
├── local.properties
├── miniApp
├── mmkvKotlin # mmkvKotlin KMP工程
├── ohosApp # mmkvKotlin 使用示例
├── package.json
├── settings.gradle.kts
├── settings.ohos.gradle.kts
└── shared # Kuikly跨端侧使用mmkvKotlin Demo示例
mmkvKotlin 模块鸿蒙基于cinterop,使用Kotlin语法与MMKV native so(libmmkv.so)进行交互。
MMKV C接口封装
在ohosAPP/mmkv-c-wrapper模块,提供了对libmmkv.so的C接口封装源码。
鸿蒙构建脚本配置
在mmkvKotlin/build.gradle.kts(统一Kotlin编译工具链)或mmkvKotlin/build.ohos.gradle.kts(鸿蒙独立Kotlin编译工具链)中,进行cinterop配置,指定C头文件和SO路径:
ohosArm64 {
val main by compilations.getting
// val devopsFlag = providers.environmentVariable("PIPELINE_ID").orNull != null
val devopsFlag = true
val includeDir = "${rootProject.rootDir}/ohosApp/mmkv_c_wrapper/src/main/cpp/include/"
val soLibDir = if(devopsFlag) {
"${rootProject.rootDir}/shared/src/libs/arm64-v8a"
} else {
"${rootProject.rootDir}/ohosApp/mmkv_c_wrapper/build/default/intermediates/libs/default/arm64-v8a"
}
// 需要在mmkvKotlin里调来自外部C的时候加这个
val interop by main.cinterops.creating {
definitionFile = file("src/nativeInterop/cinterop/interop.def")
includeDirs(includeDir)
extraOpts("-libraryPath", soLibDir)
}
compilations.forEach {
it.kotlinOptions.freeCompilerArgs += when {
HostManager.hostIsMac -> listOf("-linker-options", "-lmmkv_c_wrapper -L${soLibDir}")
else -> throw RuntimeException("暂不支持")
}
// 抑制 NativeApi 提示
it.compilerOptions.options.optIn.addAll(
"kotlinx.cinterop.ExperimentalForeignApi",
"kotlin.experimental.ExperimentalNativeApi",
)
}
}
本组件已发布到各平台标准仓库。如果开发者需要发布到自己私仓,可参考本节指引发布。
配置发布仓库:
修改build.gradle.kts发布仓库配置
publishing {
...
mavenLocal()
// 发布到build/repo目录
// maven {
// url = uri(layout.buildDirectory.dir("repo"))
// }
}
...
}
配置 maven 发布所需参数环境变量
参考KotlinbuildVar.kt
fun MavenPublication.signPublicationIfKeyPresent(project: Project) {
val keyId = getSensitiveProperty(project, "signing_keyId")
val secretKey = getSensitiveProperty(project, "signing_secretKey")
val password = getSensitiveProperty(project, "signing_password")
println("signPublicationIfKeyPresent keyId: $keyId , password: $password , secreckey: $secretKey")
if (!secretKey.isNullOrBlank()) {
project.extensions.configure<SigningExtension>("signing") {
useInMemoryPgpKeys(keyId, secretKey, password)
sign(this@signPublicationIfKeyPresent)
}
}
}配置发布版本:
MavenConfig.VERSION
运行mmkvKotlin模块的 publish任务
:::tip 注意
如果业务mmkvKotlin模块采用鸿蒙独立Kotlin编译工具链方式,则需要在build.gradle.kts中移除ohosArm64 target配置,只对Android/iOS目标进行发布。 Ohos目标发布则需要参考下述方式单独发布。
:::
如果业务mmkvKotlin模块采用独立Kotlin编译工具链方案,则要单独对鸿蒙产物进行发布。
配置发布仓库
修改build.ohos.gradle.kts发布仓库配置
配置 maven 发布所需参数环境变量(同上一步)
配置发布版本:MavenConfig.VERSION_OHOS
注意,Ohos跨端产物必须独立版本号,如本工程是在版本号后增加-ohos标识。如果不独立版本号,在运行上一步安卓/iOS跨端产物发布后,再运行Ohos发布脚本,则分两次发布会引起maven元数据混乱。
运行发布脚本
./gradlew -c settings.ohos.gradle.kts :mmkvKotlin:publish