diff --git a/FloconAndroid/datastores-no-op/.gitignore b/FloconAndroid/datastores-no-op/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/FloconAndroid/datastores-no-op/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/FloconAndroid/datastores-no-op/build.gradle.kts b/FloconAndroid/datastores-no-op/build.gradle.kts
new file mode 100644
index 00000000..31aafa27
--- /dev/null
+++ b/FloconAndroid/datastores-no-op/build.gradle.kts
@@ -0,0 +1,88 @@
+plugins {
+ alias(libs.plugins.android.library)
+ alias(libs.plugins.kotlin.android)
+ id("com.vanniktech.maven.publish") version "0.34.0"
+}
+
+android {
+ namespace = "io.github.openflocon.flocon.datastores"
+ compileSdk = 36
+
+ defaultConfig {
+ minSdk = 23
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles("consumer-rules.pro")
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
+ kotlinOptions {
+ jvmTarget = "11"
+ }
+}
+
+dependencies {
+
+ implementation(project(":flocon-base"))
+
+ implementation(platform(libs.kotlinx.coroutines.bom))
+ implementation(libs.jetbrains.kotlinx.coroutines.core)
+
+ implementation(libs.androidx.datastore.preferences)
+}
+
+
+mavenPublishing {
+ publishToMavenCentral(automaticRelease = true)
+
+ if (project.hasProperty("signing.required") && project.property("signing.required") == "false") {
+ // Skip signing
+ } else {
+ signAllPublications()
+ }
+
+ coordinates(
+ groupId = project.property("floconGroupId") as String,
+ artifactId = "flocon-datastores-no-op",
+ version = System.getenv("PROJECT_VERSION_NAME") ?: project.property("floconVersion") as String
+ )
+
+ pom {
+ name = "Flocon Datastores Integration No Op"
+ description = project.property("floconDescription") as String
+ inceptionYear = "2025"
+ url = "https://github.com/openflocon/Flocon"
+ licenses {
+ license {
+ name = "The Apache License, Version 2.0"
+ url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ distribution = "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ }
+ }
+ developers {
+ developer {
+ id = "openflocon"
+ name = "Open Flocon"
+ url = "https://github.com/openflocon"
+ }
+ }
+ scm {
+ url = "https://github.com/openflocon/Flocon"
+ connection = "scm:git:git://github.com/openflocon/Flocon.git"
+ developerConnection = "scm:git:ssh://git@github.com/openflocon/Flocon.git"
+ }
+ }
+}
\ No newline at end of file
diff --git a/FloconAndroid/datastores-no-op/consumer-rules.pro b/FloconAndroid/datastores-no-op/consumer-rules.pro
new file mode 100644
index 00000000..e69de29b
diff --git a/FloconAndroid/datastores-no-op/proguard-rules.pro b/FloconAndroid/datastores-no-op/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/FloconAndroid/datastores-no-op/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/FloconAndroid/datastores-no-op/src/main/AndroidManifest.xml b/FloconAndroid/datastores-no-op/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..74b7379f
--- /dev/null
+++ b/FloconAndroid/datastores-no-op/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/FloconAndroid/datastores-no-op/src/main/kotlin/io/github/openflocon/flocon/preferences/datastores/model/FloconDatastorePreference.kt b/FloconAndroid/datastores-no-op/src/main/kotlin/io/github/openflocon/flocon/preferences/datastores/model/FloconDatastorePreference.kt
new file mode 100644
index 00000000..855d25c2
--- /dev/null
+++ b/FloconAndroid/datastores-no-op/src/main/kotlin/io/github/openflocon/flocon/preferences/datastores/model/FloconDatastorePreference.kt
@@ -0,0 +1,37 @@
+package io.github.openflocon.flocon.preferences.datastores.model
+
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.booleanPreferencesKey
+import androidx.datastore.preferences.core.doublePreferencesKey
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.floatPreferencesKey
+import androidx.datastore.preferences.core.intPreferencesKey
+import androidx.datastore.preferences.core.longPreferencesKey
+import androidx.datastore.preferences.core.stringPreferencesKey
+import io.github.openflocon.flocon.FloconLogger
+import io.github.openflocon.flocon.plugins.sharedprefs.model.FloconPreference
+import io.github.openflocon.flocon.plugins.sharedprefs.model.FloconPreferenceValue
+import kotlinx.coroutines.flow.first
+
+class FloconDatastorePreference(
+ override val name: String,
+ val dataStore: DataStore,
+) : FloconPreference {
+
+ override suspend fun set(
+ columnName: String,
+ value: FloconPreferenceValue
+ ) {
+ // no op
+ }
+
+ override suspend fun columns(): List {
+ return emptyList() // no op
+ }
+
+ override suspend fun get(columnName: String): FloconPreferenceValue? {
+ return null // no op
+ }
+
+}
\ No newline at end of file
diff --git a/FloconAndroid/datastores/.gitignore b/FloconAndroid/datastores/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/FloconAndroid/datastores/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/FloconAndroid/datastores/build.gradle.kts b/FloconAndroid/datastores/build.gradle.kts
new file mode 100644
index 00000000..47a353b6
--- /dev/null
+++ b/FloconAndroid/datastores/build.gradle.kts
@@ -0,0 +1,89 @@
+plugins {
+ alias(libs.plugins.android.library)
+ alias(libs.plugins.kotlin.android)
+ id("com.vanniktech.maven.publish") version "0.34.0"
+}
+
+android {
+ namespace = "io.github.openflocon.flocon.datastores"
+ compileSdk = 36
+
+ defaultConfig {
+ minSdk = 23
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles("consumer-rules.pro")
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
+ kotlinOptions {
+ jvmTarget = "11"
+ }
+}
+
+dependencies {
+
+ implementation(project(":flocon-base"))
+
+ implementation(platform(libs.kotlinx.coroutines.bom))
+ implementation(libs.jetbrains.kotlinx.coroutines.core)
+ implementation(libs.jetbrains.kotlinx.coroutines.android)
+
+ implementation(libs.androidx.datastore.preferences)
+}
+
+
+mavenPublishing {
+ publishToMavenCentral(automaticRelease = true)
+
+ if (project.hasProperty("signing.required") && project.property("signing.required") == "false") {
+ // Skip signing
+ } else {
+ signAllPublications()
+ }
+
+ coordinates(
+ groupId = project.property("floconGroupId") as String,
+ artifactId = "flocon-datastores",
+ version = System.getenv("PROJECT_VERSION_NAME") ?: project.property("floconVersion") as String
+ )
+
+ pom {
+ name = "Flocon Datastores Integration"
+ description = project.property("floconDescription") as String
+ inceptionYear = "2025"
+ url = "https://github.com/openflocon/Flocon"
+ licenses {
+ license {
+ name = "The Apache License, Version 2.0"
+ url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ distribution = "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ }
+ }
+ developers {
+ developer {
+ id = "openflocon"
+ name = "Open Flocon"
+ url = "https://github.com/openflocon"
+ }
+ }
+ scm {
+ url = "https://github.com/openflocon/Flocon"
+ connection = "scm:git:git://github.com/openflocon/Flocon.git"
+ developerConnection = "scm:git:ssh://git@github.com/openflocon/Flocon.git"
+ }
+ }
+}
\ No newline at end of file
diff --git a/FloconAndroid/datastores/consumer-rules.pro b/FloconAndroid/datastores/consumer-rules.pro
new file mode 100644
index 00000000..e69de29b
diff --git a/FloconAndroid/datastores/proguard-rules.pro b/FloconAndroid/datastores/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/FloconAndroid/datastores/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/FloconAndroid/datastores/src/main/AndroidManifest.xml b/FloconAndroid/datastores/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..74b7379f
--- /dev/null
+++ b/FloconAndroid/datastores/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/FloconAndroid/datastores/src/main/kotlin/io/github/openflocon/flocon/preferences/datastores/model/FloconDatastorePreference.kt b/FloconAndroid/datastores/src/main/kotlin/io/github/openflocon/flocon/preferences/datastores/model/FloconDatastorePreference.kt
new file mode 100644
index 00000000..3332e668
--- /dev/null
+++ b/FloconAndroid/datastores/src/main/kotlin/io/github/openflocon/flocon/preferences/datastores/model/FloconDatastorePreference.kt
@@ -0,0 +1,80 @@
+package io.github.openflocon.flocon.preferences.datastores.model
+
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.booleanPreferencesKey
+import androidx.datastore.preferences.core.doublePreferencesKey
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.floatPreferencesKey
+import androidx.datastore.preferences.core.intPreferencesKey
+import androidx.datastore.preferences.core.longPreferencesKey
+import androidx.datastore.preferences.core.stringPreferencesKey
+import io.github.openflocon.flocon.FloconLogger
+import io.github.openflocon.flocon.plugins.sharedprefs.model.FloconPreference
+import io.github.openflocon.flocon.plugins.sharedprefs.model.FloconPreferenceValue
+import kotlinx.coroutines.flow.first
+
+class FloconDatastorePreference(
+ override val name: String,
+ private val dataStore: DataStore,
+) : FloconPreference {
+
+ override suspend fun set(
+ columnName: String,
+ value: FloconPreferenceValue
+ ) {
+ try {
+ val data = dataStore.data.first().asMap()
+ val key = data.keys.find { it.name == columnName } ?: return
+
+ dataStore.edit {
+ try {
+ when (it[key]) {
+ is String -> it[stringPreferencesKey(columnName)] = value.stringValue!!
+ is Int -> it[intPreferencesKey(columnName)] = value.intValue!!
+ is Boolean -> it[booleanPreferencesKey(columnName)] = value.booleanValue!!
+ is Float -> it[floatPreferencesKey(columnName)] = value.floatValue!!
+ is Long -> it[longPreferencesKey(columnName)] = value.longValue!!
+ is Double -> it[doublePreferencesKey(columnName)] =
+ value.floatValue!!.toDouble()
+ }
+ } catch (t: Throwable) {
+ FloconLogger.logError("cannot update datastore preference", t)
+ }
+ }
+ } catch (t: Throwable) {
+ FloconLogger.logError(t.message ?: "cannot edit datastore preference columns", t)
+ }
+ }
+
+ override suspend fun columns(): List {
+ return try {
+ dataStore.data.first().asMap().map { it.key.name }
+ } catch (t: Throwable) {
+ FloconLogger.logError(t.message ?: "cannot get datastore preference columns", t)
+ emptyList()
+ }
+ }
+
+ override suspend fun get(columnName: String): FloconPreferenceValue? {
+ return try {
+ val data = dataStore.data.first().asMap()
+ val key = data.keys.find { it.name == columnName } ?: return null
+ val value = data[key] ?: return null
+
+ return when (value) {
+ is String -> FloconPreferenceValue(stringValue = value)
+ is Int -> FloconPreferenceValue(intValue = value)
+ is Float -> FloconPreferenceValue(floatValue = value)
+ is Double -> FloconPreferenceValue(floatValue = value.toFloat())
+ is Boolean -> FloconPreferenceValue(booleanValue = value)
+ is Long -> FloconPreferenceValue(longValue = value)
+ else -> null
+ }
+ } catch (t: Throwable) {
+ FloconLogger.logError(t.message ?: "cannot get datastore preference value", t)
+ null
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/FloconAndroid/flocon-base/src/commonMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/model/FloconPreference.kt b/FloconAndroid/flocon-base/src/commonMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/model/FloconPreference.kt
index 3e15ebe3..5a3810f9 100644
--- a/FloconAndroid/flocon-base/src/commonMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/model/FloconPreference.kt
+++ b/FloconAndroid/flocon-base/src/commonMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/model/FloconPreference.kt
@@ -4,7 +4,7 @@ interface FloconPreference {
val name: String
suspend fun set(
- rowName: String,
+ columnName: String,
value: FloconPreferenceValue,
)
diff --git a/FloconAndroid/flocon-no-op/build.gradle.kts b/FloconAndroid/flocon-no-op/build.gradle.kts
index ee80a3e2..dedd7d82 100644
--- a/FloconAndroid/flocon-no-op/build.gradle.kts
+++ b/FloconAndroid/flocon-no-op/build.gradle.kts
@@ -91,7 +91,7 @@ mavenPublishing {
)
pom {
- name = "Flocon"
+ name = "Flocon No Op"
description = project.property("floconDescription") as String
inceptionYear = "2025"
url = "https://github.com/openflocon/Flocon"
diff --git a/FloconAndroid/flocon-no-op/src/androidMain/kotlin/io/github/openflocon/flocon/sharedprefs/FloconSharedPreference.kt b/FloconAndroid/flocon-no-op/src/androidMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPreference.kt
similarity index 88%
rename from FloconAndroid/flocon-no-op/src/androidMain/kotlin/io/github/openflocon/flocon/sharedprefs/FloconSharedPreference.kt
rename to FloconAndroid/flocon-no-op/src/androidMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPreference.kt
index a6bfc75f..d5be3322 100644
--- a/FloconAndroid/flocon-no-op/src/androidMain/kotlin/io/github/openflocon/flocon/sharedprefs/FloconSharedPreference.kt
+++ b/FloconAndroid/flocon-no-op/src/androidMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPreference.kt
@@ -1,4 +1,4 @@
-package io.github.openflocon.flocon.sharedprefs
+package io.github.openflocon.flocon.plugins.sharedprefs
import android.content.SharedPreferences
import io.github.openflocon.flocon.plugins.sharedprefs.model.FloconPreference
@@ -10,7 +10,7 @@ data class FloconSharedPreference(
) : FloconPreference {
override suspend fun set(
- rowName: String,
+ columnName: String,
value: FloconPreferenceValue
) {
// no op
diff --git a/FloconAndroid/flocon/src/androidMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPreference.kt b/FloconAndroid/flocon/src/androidMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPreference.kt
index 84daf290..1bbe8d4a 100644
--- a/FloconAndroid/flocon/src/androidMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPreference.kt
+++ b/FloconAndroid/flocon/src/androidMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPreference.kt
@@ -10,22 +10,22 @@ data class FloconSharedPreference(
) : FloconPreference {
override suspend fun set(
- rowName: String,
+ columnName: String,
value: FloconPreferenceValue
) {
- val originalValue: Any? = sharedPreferences.all[rowName]
+ val originalValue: Any? = sharedPreferences.all[columnName]
val editor = sharedPreferences.edit()
if (originalValue is Boolean && value.booleanValue != null) {
- editor.putBoolean(rowName, value.booleanValue!!)
+ editor.putBoolean(columnName, value.booleanValue!!)
} else if (originalValue is Long && value.longValue != null) {
- editor.putLong(rowName, value.longValue!!)
+ editor.putLong(columnName, value.longValue!!)
} else if (originalValue is Int && value.intValue != null) {
- editor.putInt(rowName, value.intValue!!)
+ editor.putInt(columnName, value.intValue!!)
} else if (originalValue is Float && value.floatValue != null) {
- editor.putFloat(rowName, value.floatValue!!)
+ editor.putFloat(columnName, value.floatValue!!)
} else if (originalValue is String && value.stringValue != null) {
- editor.putString(rowName, value.stringValue!!)
+ editor.putString(columnName, value.stringValue!!)
} else {
// do nothin
}
diff --git a/FloconAndroid/flocon/src/commonMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPrefsPlugin.kt b/FloconAndroid/flocon/src/commonMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPrefsPlugin.kt
index aa615747..e1818d43 100644
--- a/FloconAndroid/flocon/src/commonMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPrefsPlugin.kt
+++ b/FloconAndroid/flocon/src/commonMain/kotlin/io/github/openflocon/flocon/plugins/sharedprefs/FloconSharedPrefsPlugin.kt
@@ -67,7 +67,7 @@ internal class FloconPreferencesPluginImpl(
scope.launch {
try {
preference.set(
- rowName = toDeviceMessage.key,
+ columnName = toDeviceMessage.key,
value = FloconPreferenceValue(
stringValue = toDeviceMessage.stringValue,
booleanValue = toDeviceMessage.booleanValue,
diff --git a/FloconAndroid/gradle/libs.versions.toml b/FloconAndroid/gradle/libs.versions.toml
index 84ea62e6..1e4a3182 100644
--- a/FloconAndroid/gradle/libs.versions.toml
+++ b/FloconAndroid/gradle/libs.versions.toml
@@ -3,6 +3,7 @@ agp = "8.11.0-rc02"
apollo = "4.0.0"
coilCompose = "3.2.0"
compose = "1.9.0"
+datastorePreferences = "1.1.7"
kotlin = "2.1.0"
mavenPublish = "0.34.0"
coreKtx = "1.16.0"
@@ -33,6 +34,7 @@ buildconfig = "5.6.8"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
androidx-sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "sqlite" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
diff --git a/FloconAndroid/publishLocal.sh b/FloconAndroid/publishLocal.sh
index 4021b891..5e62f35c 100755
--- a/FloconAndroid/publishLocal.sh
+++ b/FloconAndroid/publishLocal.sh
@@ -8,7 +8,9 @@
:okhttp-interceptor:assembleRelease \
:okhttp-interceptor-no-op:assembleRelease \
:ktor-interceptor:assembleRelease \
- :ktor-interceptor-no-op:assembleRelease
+ :ktor-interceptor-no-op:assembleRelease \
+ :datastores:assembleRelease \
+ :datastores-no-op:assembleRelease
./gradlew \
:flocon-base:publishToMavenLocal \
@@ -21,4 +23,6 @@
:okhttp-interceptor-no-op:publishToMavenLocal \
:ktor-interceptor:publishToMavenLocal \
:ktor-interceptor-no-op:publishToMavenLocal \
+ :datastores:publishToMavenLocal \
+ :datastores-no-op:publishToMavenLocal \
-Psigning.required=false
\ No newline at end of file
diff --git a/FloconAndroid/sample-android-only/build.gradle.kts b/FloconAndroid/sample-android-only/build.gradle.kts
index b83ca7ed..1d056d1c 100644
--- a/FloconAndroid/sample-android-only/build.gradle.kts
+++ b/FloconAndroid/sample-android-only/build.gradle.kts
@@ -84,6 +84,8 @@ dependencies {
implementation(project(":grpc:grpc-interceptor-lite"))
debugImplementation(project(":ktor-interceptor"))
releaseImplementation(project(":ktor-interceptor-no-op"))
+ debugImplementation(project(":datastores"))
+ releaseImplementation(project(":datastores-no-op"))
}
@@ -135,6 +137,10 @@ dependencies {
implementation(libs.ktor.client.okhttp)
implementation(libs.ktor.client.core)
//endregion
+
+ // region datastore
+ implementation(libs.androidx.datastore.preferences)
+ // endregion
}
apollo {
diff --git a/FloconAndroid/sample-android-only/src/main/java/io/github/openflocon/flocon/myapplication/MainActivity.kt b/FloconAndroid/sample-android-only/src/main/java/io/github/openflocon/flocon/myapplication/MainActivity.kt
index 2974317d..b35249fb 100644
--- a/FloconAndroid/sample-android-only/src/main/java/io/github/openflocon/flocon/myapplication/MainActivity.kt
+++ b/FloconAndroid/sample-android-only/src/main/java/io/github/openflocon/flocon/myapplication/MainActivity.kt
@@ -26,6 +26,7 @@ import io.github.openflocon.flocon.myapplication.deeplinks.initializeDeeplinks
import io.github.openflocon.flocon.myapplication.graphql.GraphQlTester
import io.github.openflocon.flocon.myapplication.grpc.GrpcController
import io.github.openflocon.flocon.myapplication.images.initializeImages
+import io.github.openflocon.flocon.myapplication.sharedpreferences.initializeDatastores
import io.github.openflocon.flocon.myapplication.sharedpreferences.initializeSharedPreferences
import io.github.openflocon.flocon.myapplication.sharedpreferences.initializeSharedPreferencesAfterInit
import io.github.openflocon.flocon.myapplication.table.initializeTable
@@ -68,6 +69,7 @@ class MainActivity : ComponentActivity() {
initializeDeeplinks()
initializeSharedPreferencesAfterInit(applicationContext)
+ initializeDatastores(applicationContext)
val dummyHttpCaller = DummyHttpCaller(client = okHttpClient)
val dummyWebsocketCaller = DummyWebsocketCaller(client = okHttpClient)
diff --git a/FloconAndroid/sample-android-only/src/main/java/io/github/openflocon/flocon/myapplication/sharedpreferences/Datastores.kt b/FloconAndroid/sample-android-only/src/main/java/io/github/openflocon/flocon/myapplication/sharedpreferences/Datastores.kt
new file mode 100644
index 00000000..4b5fab96
--- /dev/null
+++ b/FloconAndroid/sample-android-only/src/main/java/io/github/openflocon/flocon/myapplication/sharedpreferences/Datastores.kt
@@ -0,0 +1,47 @@
+package io.github.openflocon.flocon.myapplication.sharedpreferences
+
+import android.content.Context
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.intPreferencesKey
+import androidx.datastore.preferences.core.stringPreferencesKey
+import androidx.datastore.preferences.preferencesDataStore
+import io.github.openflocon.flocon.plugins.sharedprefs.floconRegisterPreference
+import io.github.openflocon.flocon.preferences.datastores.model.FloconDatastorePreference
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
+
+private val Context.dataStore by preferencesDataStore(name = "datastore")
+
+private val USER_NAME = stringPreferencesKey("username")
+private val USER_AGE = intPreferencesKey("user.age")
+
+fun initializeDatastores(context: Context) {
+ Datastores(context)
+}
+
+class Datastores(private val context: Context) {
+ suspend fun saveUsername(username: String) {
+ val value = context.dataStore.data.first()[USER_NAME]
+ println("Datastore Local Value : $value")
+ if (value == null) {
+ context.dataStore.edit { prefs ->
+ prefs[USER_NAME] = username
+ }
+ }
+ }
+
+ suspend fun saveUserAge(age: Int) {
+ context.dataStore.edit { prefs ->
+ prefs[USER_AGE] = age
+ }
+ }
+
+ init {
+ floconRegisterPreference(FloconDatastorePreference("datastore", context.dataStore))
+ GlobalScope.launch {
+ saveUsername("John Doe")
+ saveUserAge(30)
+ }
+ }
+}
diff --git a/FloconAndroid/settings.gradle.kts b/FloconAndroid/settings.gradle.kts
index 30721c32..511b0712 100644
--- a/FloconAndroid/settings.gradle.kts
+++ b/FloconAndroid/settings.gradle.kts
@@ -27,3 +27,5 @@ include(":grpc:grpc-interceptor-base")
include(":grpc:grpc-interceptor-lite")
include(":ktor-interceptor")
include(":ktor-interceptor-no-op")
+include(":datastores")
+include(":datastores-no-op")