diff --git a/datastore/.gitignore b/datastore/.gitignore
new file mode 100644
index 000000000..42afabfd2
--- /dev/null
+++ b/datastore/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/datastore/build.gradle.kts b/datastore/build.gradle.kts
new file mode 100644
index 000000000..9d5484f9f
--- /dev/null
+++ b/datastore/build.gradle.kts
@@ -0,0 +1,120 @@
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin.android)
+ alias(libs.plugins.compose.compiler)
+
+ // [START android_datastore_proto_plugin]
+ alias(libs.plugins.google.protobuf)
+ // [END android_datastore_proto_plugin]
+
+ // [START android_datastore_serialization_plugin]
+ alias(libs.plugins.kotlin.serialization)
+ // [END android_datastore_serialization_plugin]
+}
+
+android {
+ namespace = "com.example.datastore.snippets"
+ compileSdk = 36
+
+ defaultConfig {
+ applicationId = "com.example.datastore.snippets"
+ minSdk = 23
+ targetSdk = 36
+ versionCode = 1
+ versionName = "1.0"
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ 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"
+ }
+ buildFeatures {
+ compose = true
+ }
+}
+
+dependencies {
+ implementation(libs.androidx.core.ktx)
+ implementation(libs.androidx.lifecycle.runtime)
+ implementation(libs.androidx.activity.compose)
+ implementation(platform(libs.androidx.compose.bom))
+ implementation(libs.androidx.compose.ui)
+ implementation(libs.androidx.compose.ui.graphics)
+ implementation(libs.androidx.compose.ui.tooling.preview)
+ implementation(libs.androidx.compose.material3)
+
+ // [START android_datastore_dependency]
+ // Typed DataStore (Typed API surface, such as Proto)
+ implementation(libs.androidx.datastore)
+
+ // Alternatively - without an Android dependency.
+ implementation(libs.androidx.datastore.core)
+ // [END android_datastore_dependency]
+
+ // [START android_datastore_preferences_dependency]
+ // Preferences DataStore (SharedPreferences like APIs)
+ implementation(libs.androidx.datastore.preferences)
+
+ // Alternatively - without an Android dependency.
+ implementation(libs.androidx.datastore.preferences.core)
+ // [END android_datastore_preferences_dependency]
+
+ // [START android_datastore_preferences_dependency_rxjava]
+ // optional - RxJava2 support
+ implementation(libs.androidx.datastore.preferences.rxjava2)
+
+ // optional - RxJava3 support
+ implementation(libs.androidx.datastore.preferences.rxjava3)
+ // [END android_datastore_preferences_dependency_rxjava]
+
+ implementation(libs.androidx.navigation3.ui)
+ implementation(libs.androidx.navigation3.runtime)
+
+ // [START android_datastore_proto_dependency]
+ implementation(libs.google.protobuf.kotlin.lite)
+ // [END android_datastore_proto_dependency]
+
+ // [START android_datastore_json_dependency]
+ implementation(libs.kotlinx.serialization.json)
+ // [END android_datastore_json_dependency]
+
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.androidx.test.ext.junit)
+ androidTestImplementation(libs.androidx.test.espresso.core)
+ androidTestImplementation(platform(libs.androidx.compose.bom))
+ androidTestImplementation(libs.androidx.compose.ui.test.junit4)
+ debugImplementation(libs.androidx.compose.ui.tooling)
+ debugImplementation(libs.androidx.compose.ui.test.manifest)
+}
+
+// [START android_datastore_proto_task]
+protobuf {
+ protoc {
+ artifact = "com.google.protobuf:protoc:4.32.1"
+ }
+ generateProtoTasks {
+ all().forEach { task ->
+ task.builtins {
+ create("java") {
+ option("lite")
+ }
+ create("kotlin")
+ }
+ }
+ }
+}
+// [END android_datastore_proto_task]
\ No newline at end of file
diff --git a/datastore/proguard-rules.pro b/datastore/proguard-rules.pro
new file mode 100644
index 000000000..481bb4348
--- /dev/null
+++ b/datastore/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/datastore/src/androidTest/java/com/example/datastore/snippets/DataStoreSnippetsTest.kt b/datastore/src/androidTest/java/com/example/datastore/snippets/DataStoreSnippetsTest.kt
new file mode 100644
index 000000000..6163fe03e
--- /dev/null
+++ b/datastore/src/androidTest/java/com/example/datastore/snippets/DataStoreSnippetsTest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.datastore.snippets
+
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.example.datastore.snippets.json.JsonDataStoreScreen
+import com.example.datastore.snippets.multiprocess.MultiProcessDataStoreScreen
+import com.example.datastore.snippets.preferences.PreferencesDataStoreScreen
+import com.example.datastore.snippets.proto.ProtoDataStoreScreen
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class DataStoreSnippetsTest {
+ @get:Rule
+ val rule = createComposeRule()
+
+ @Test
+ fun launchPreferencesDataStore() {
+ rule.setContent { PreferencesDataStoreScreen() }
+ rule.onNodeWithText("Preferences DataStore").assertExists()
+ }
+
+ @Test
+ fun launchProtoDataStore() {
+ rule.setContent { ProtoDataStoreScreen() }
+ rule.onNodeWithText("Proto DataStore").assertExists()
+ }
+
+ @Test
+ fun launchJsonDataStore() {
+ rule.setContent { JsonDataStoreScreen() }
+ rule.onNodeWithText("Json DataStore").assertExists()
+ }
+
+ @Test
+ fun launchMultiProcessDataStore() {
+ rule.setContent { MultiProcessDataStoreScreen() }
+ rule.onNodeWithText("Multi-process DataStore").assertExists()
+ }
+}
diff --git a/datastore/src/main/AndroidManifest.xml b/datastore/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..7ca446743
--- /dev/null
+++ b/datastore/src/main/AndroidManifest.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/datastore/src/main/java/com/example/datastore/snippets/Home.kt b/datastore/src/main/java/com/example/datastore/snippets/Home.kt
new file mode 100644
index 000000000..a014c65ac
--- /dev/null
+++ b/datastore/src/main/java/com/example/datastore/snippets/Home.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.datastore.snippets
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+
+@Composable
+internal fun Home(backStack: MutableList) {
+ Column {
+ Item("Preferences Data Store") {
+ backStack.add(MainActivity.Snippets.PreferencesDataStore)
+ }
+ Item("Proto Data Store") {
+ backStack.add(MainActivity.Snippets.ProtoDataStore)
+ }
+ Item("Json Data Store") {
+ backStack.add(MainActivity.Snippets.JsonDataStore)
+ }
+ Item("Multi process Data Store") {
+ backStack.add(MainActivity.Snippets.MultiProcessDataStore)
+ }
+ }
+}
+
+@Composable
+private fun Item(text: String, onClick: () -> Unit) {
+ Box(
+ Modifier
+ .fillMaxWidth()
+ .clickable(onClick = onClick)
+ .padding(10.dp)
+ ) {
+ Text(fontSize = 30.sp, text = text)
+ }
+}
\ No newline at end of file
diff --git a/datastore/src/main/java/com/example/datastore/snippets/MainActivity.kt b/datastore/src/main/java/com/example/datastore/snippets/MainActivity.kt
new file mode 100644
index 000000000..3ac44d81b
--- /dev/null
+++ b/datastore/src/main/java/com/example/datastore/snippets/MainActivity.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.datastore.snippets
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.navigation3.runtime.NavEntry
+import androidx.navigation3.ui.NavDisplay
+import com.example.datastore.snippets.MainActivity.Snippets.JsonDataStore
+import com.example.datastore.snippets.MainActivity.Snippets.LandingPage
+import com.example.datastore.snippets.MainActivity.Snippets.MultiProcessDataStore
+import com.example.datastore.snippets.MainActivity.Snippets.PreferencesDataStore
+import com.example.datastore.snippets.MainActivity.Snippets.ProtoDataStore
+import com.example.datastore.snippets.json.JsonDataStoreScreen
+import com.example.datastore.snippets.multiprocess.MultiProcessDataStoreScreen
+import com.example.datastore.snippets.preferences.PreferencesDataStoreScreen
+import com.example.datastore.snippets.proto.ProtoDataStoreScreen
+import com.example.datastore.snippets.ui.theme.SnippetsTheme
+
+class MainActivity : ComponentActivity() {
+
+ internal enum class Snippets { LandingPage, PreferencesDataStore, ProtoDataStore, JsonDataStore, MultiProcessDataStore }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ setContent {
+ SnippetsTheme {
+ Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
+ val backStack = remember { mutableStateListOf(LandingPage) }
+ NavDisplay(
+ modifier = Modifier.padding(innerPadding),
+ backStack = backStack
+ ) {
+ when (it) {
+ LandingPage -> NavEntry(LandingPage) {
+ Home(backStack)
+ }
+
+ PreferencesDataStore -> NavEntry(PreferencesDataStore) {
+ PreferencesDataStoreScreen()
+ }
+
+ ProtoDataStore -> NavEntry(ProtoDataStore) {
+ ProtoDataStoreScreen()
+ }
+
+ JsonDataStore -> NavEntry(JsonDataStore) {
+ JsonDataStoreScreen()
+ }
+
+ MultiProcessDataStore -> NavEntry(MultiProcessDataStore) {
+ MultiProcessDataStoreScreen()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun Greeting(name: String, modifier: Modifier = Modifier) {
+ Text(
+ text = "Hello $name!",
+ modifier = modifier
+ )
+}
+
+@Preview(showBackground = true)
+@Composable
+fun GreetingPreview() {
+ SnippetsTheme {
+ Greeting("Android")
+ }
+}
\ No newline at end of file
diff --git a/datastore/src/main/java/com/example/datastore/snippets/TimestampUpdateService.kt b/datastore/src/main/java/com/example/datastore/snippets/TimestampUpdateService.kt
new file mode 100644
index 000000000..9b10afc5c
--- /dev/null
+++ b/datastore/src/main/java/com/example/datastore/snippets/TimestampUpdateService.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.datastore.snippets
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import com.example.datastore.snippets.multiprocess.MultiProcessDataStore
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+// [START android_datastore_multiprocess_service]
+class TimestampUpdateService : Service() {
+ val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
+ val multiProcessDataStore by lazy { MultiProcessDataStore(applicationContext) }
+
+ // [START_EXCLUDE silent]
+ override fun onBind(intent: Intent): IBinder? = null
+ // [END_EXCLUDE silent]
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ serviceScope.launch {
+ while (true) {
+ multiProcessDataStore.updateLastUpdateTime()
+ delay(1000)
+ }
+ }
+ return START_NOT_STICKY
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ serviceScope.cancel()
+ }
+}
+// [END android_datastore_multiprocess_service]
diff --git a/datastore/src/main/java/com/example/datastore/snippets/json/JsonDataStore.kt b/datastore/src/main/java/com/example/datastore/snippets/json/JsonDataStore.kt
new file mode 100644
index 000000000..a73d0a431
--- /dev/null
+++ b/datastore/src/main/java/com/example/datastore/snippets/json/JsonDataStore.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.datastore.snippets.json
+
+import android.content.Context
+import androidx.datastore.core.CorruptionException
+import androidx.datastore.core.DataStore
+import androidx.datastore.core.Serializer
+import androidx.datastore.dataStore
+import java.io.InputStream
+import java.io.OutputStream
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.SerializationException
+import kotlinx.serialization.json.Json
+
+// [START android_datastore_json_create]
+val Context.dataStore: DataStore by dataStore(
+ fileName = "settings.json",
+ serializer = SettingsSerializer,
+)
+// [END android_datastore_json_create]
+
+class JsonDataStore(private val context: Context) {
+
+ // [START android_datastore_json_read]
+ fun counterFlow(): Flow = context.dataStore.data.map { settings ->
+ settings.exampleCounter
+ }
+ // [END android_datastore_json_read]
+
+ // [START android_datastore_json_write]
+ suspend fun incrementCounter() {
+ context.dataStore.updateData { settings ->
+ settings.copy(exampleCounter = settings.exampleCounter + 1)
+ }
+ }
+ // [END android_datastore_json_write]
+}
+
+// [START android_datastore_json_definition]
+@Serializable
+data class Settings(
+ val exampleCounter: Int
+)
+// [END android_datastore_json_definition]
+
+// [START android_datastore_json_serializer]
+object SettingsSerializer : Serializer {
+
+ override val defaultValue: Settings = Settings(exampleCounter = 0)
+
+ override suspend fun readFrom(input: InputStream): Settings =
+ try {
+ Json.decodeFromString(
+ input.readBytes().decodeToString()
+ )
+ } catch (serialization: SerializationException) {
+ throw CorruptionException("Unable to read Settings", serialization)
+ }
+
+ override suspend fun writeTo(t: Settings, output: OutputStream) {
+ output.write(
+ Json.encodeToString(t)
+ .encodeToByteArray()
+ )
+ }
+}
+// [END android_datastore_json_serializer]
diff --git a/datastore/src/main/java/com/example/datastore/snippets/json/JsonDataStoreScreen.kt b/datastore/src/main/java/com/example/datastore/snippets/json/JsonDataStoreScreen.kt
new file mode 100644
index 000000000..916b60a67
--- /dev/null
+++ b/datastore/src/main/java/com/example/datastore/snippets/json/JsonDataStoreScreen.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.datastore.snippets.json
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.Button
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.sp
+import kotlinx.coroutines.launch
+
+@Preview(showBackground = true)
+@Composable
+internal fun JsonDataStoreScreen() {
+ Column(Modifier.fillMaxSize()) {
+ Text(
+ text = "Json DataStore",
+ fontSize = 30.sp
+ )
+ // [START android_datastore_json_compose_sample]
+ val context = LocalContext.current
+ val coroutineScope = rememberCoroutineScope()
+ val jsonDataStore = remember(context) { JsonDataStore(context) }
+
+ // Display counter value.
+ val exampleCounter by jsonDataStore.counterFlow()
+ .collectAsState(initial = 0, coroutineScope.coroutineContext)
+ Text(
+ text = "Counter $exampleCounter",
+ fontSize = 25.sp
+ )
+
+ // Update the counter.
+ Button(onClick = { coroutineScope.launch { jsonDataStore.incrementCounter() } }) {
+ Text("increment")
+ }
+ // [END android_datastore_json_compose_sample]
+ }
+}
\ No newline at end of file
diff --git a/datastore/src/main/java/com/example/datastore/snippets/multiprocess/MultiProcessDataStore.kt b/datastore/src/main/java/com/example/datastore/snippets/multiprocess/MultiProcessDataStore.kt
new file mode 100644
index 000000000..b677c872e
--- /dev/null
+++ b/datastore/src/main/java/com/example/datastore/snippets/multiprocess/MultiProcessDataStore.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.datastore.snippets.multiprocess
+
+import android.content.Context
+import androidx.datastore.core.CorruptionException
+import androidx.datastore.core.DataStore
+import androidx.datastore.core.MultiProcessDataStoreFactory
+import androidx.datastore.core.Serializer
+import java.io.File
+import java.io.InputStream
+import java.io.OutputStream
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.SerializationException
+import kotlinx.serialization.json.Json
+
+fun createMultiProcessDataStore(context: Context): DataStore