Skip to content

Commit 84d9e98

Browse files
committed
Implement DataStore
1 parent a87a6c0 commit 84d9e98

7 files changed

Lines changed: 209 additions & 11 deletions

File tree

app/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
### This general module contains and covers the following topics:
22

33
1. [Biometric Dialog](https://github.com/AsemLab/Samples/blob/main/app/src/main/java/com/asemlab/samples/ui/BiometricActivity.kt): show biometric dialog using the Biometric library. [Official](https://developer.android.com/identity/sign-in/biometric-auth)
4-
2. [DownloadManager](https://github.com/AsemLab/Samples/blob/main/app/src/main/java/com/asemlab/samples/download/FileDownloaderImp.kt): is a system service that handles long-running HTTP downloads. Clients may request that a URI be downloaded to a particular destination file. [Official](https://developer.android.com/reference/android/app/DownloadManager)
4+
2. [DataStore](https://github.com/AsemLab/Samples/blob/main/app/src/main/java/com/asemlab/samples/ui/DataStoreActivity.kt): is a data storage solution that allows you to store key-value pairs or typed objects with protocol buffers. [Official](https://developer.android.com/topic/libraries/architecture/datastore)
5+
3. [DownloadManager](https://github.com/AsemLab/Samples/blob/main/app/src/main/java/com/asemlab/samples/download/FileDownloaderImp.kt): is a system service that handles long-running HTTP downloads. Clients may request that a URI be downloaded to a particular destination file. [Official](https://developer.android.com/reference/android/app/DownloadManager)
56
3. [Epoxy](https://github.com/AsemLab/Samples/blob/main/app/src/main/java/com/asemlab/samples/epoxy/EpoxyActivity.kt): is an Android library for building complex screens in a RecyclerView. [Official](https://github.com/airbnb/epoxy)
67
4. [Pass data between components](https://github.com/AsemLab/Samples/tree/main/app/src/main/java/com/asemlab/samples/passdata): demonstrate how to pass data from Activity to Activity/Fragment and from Fragment to Activity/Fragment.
78
5. [Per-app language preferences](https://github.com/AsemLab/Samples/blob/main/app/src/main/java/com/asemlab/samples/utils/LanguageHelper.kt): allow users to set their preferred language for each app. The app specific preferred language will override the system language for that particular application. [Official](https://developer.android.com/guide/topics/resources/app-languages)

app/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,7 @@ dependencies {
9191
implementation(libs.epoxy.databinding)
9292
kapt(libs.epoxy.processor)
9393
implementation(libs.androidx.biometric)
94+
95+
// TODO Add DataStore dependency
96+
implementation(libs.datastore)
9497
}

app/src/main/AndroidManifest.xml

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
<uses-permission android:name="android.permission.READ_CONTACTS" />
88
<uses-permission android:name="android.permission.INTERNET" />
99

10-
<!-- TODO Add locales_config.xml -->
1110
<application
1211
android:allowBackup="true"
1312
android:icon="@mipmap/ic_launcher"
@@ -16,17 +15,28 @@
1615
android:roundIcon="@mipmap/ic_launcher_round"
1716
android:supportsRtl="true"
1817
android:theme="@style/Theme.ContactsContent">
18+
<activity
19+
android:name=".ui.DataStoreActivity"
20+
android:exported="true" >
21+
22+
<!-- <intent-filter> -->
23+
<!-- <action android:name="android.intent.action.MAIN" /> -->
24+
25+
26+
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
27+
<!-- </intent-filter> -->
28+
</activity>
1929
<activity
2030
android:name=".ui.BiometricActivity"
2131
android:exported="true" />
2232
<activity
2333
android:name=".passdata.f2f.ThirdActivity"
2434
android:exported="true">
2535
<!-- <intent-filter> -->
26-
<!-- <action android:name="android.intent.action.MAIN" /> -->
36+
<!-- <action android:name="android.intent.action.MAIN" /> -->
2737

2838

29-
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
39+
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
3040
<!-- </intent-filter> -->
3141
</activity>
3242
<activity
@@ -37,10 +47,10 @@
3747
android:exported="true">
3848

3949
<!-- <intent-filter> -->
40-
<!-- <action android:name="android.intent.action.MAIN" /> -->
50+
<!-- <action android:name="android.intent.action.MAIN" /> -->
4151

4252

43-
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
53+
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
4454
<!-- </intent-filter> -->
4555
</activity>
4656
<activity
@@ -69,11 +79,13 @@
6979
<activity
7080
android:name=".ui.NotificationProgressActivity"
7181
android:exported="true">
72-
<!-- <intent-filter>-->
73-
<!-- <action android:name="android.intent.action.MAIN" />-->
7482

75-
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
76-
<!-- </intent-filter>-->
83+
<!-- <intent-filter> -->
84+
<!-- <action android:name="android.intent.action.MAIN" /> -->
85+
86+
87+
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
88+
<!-- </intent-filter> -->
7789
</activity>
7890

7991
<receiver
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.asemlab.samples.ui
2+
3+
import android.os.Bundle
4+
import androidx.activity.enableEdgeToEdge
5+
import androidx.appcompat.app.AppCompatActivity
6+
import androidx.core.view.ViewCompat
7+
import androidx.core.view.WindowInsetsCompat
8+
import androidx.databinding.DataBindingUtil
9+
import androidx.lifecycle.lifecycleScope
10+
import com.asemlab.samples.R
11+
import com.asemlab.samples.databinding.ActivityDatastoreBinding
12+
import com.asemlab.samples.utils.DataStoreUtils
13+
import kotlinx.coroutines.launch
14+
15+
class DataStoreActivity : AppCompatActivity() {
16+
17+
private lateinit var binding: ActivityDatastoreBinding
18+
19+
20+
override fun onCreate(savedInstanceState: Bundle?) {
21+
super.onCreate(savedInstanceState)
22+
enableEdgeToEdge()
23+
binding = DataBindingUtil.setContentView(this, R.layout.activity_datastore)
24+
25+
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
26+
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
27+
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
28+
insets
29+
}
30+
31+
with(binding) {
32+
33+
lifecycleScope.launch {
34+
usernameTV.text = DataStoreUtils.getUsername(this@DataStoreActivity)
35+
genderTV.text = DataStoreUtils.getGender(this@DataStoreActivity).toString()
36+
ageTV.text = DataStoreUtils.getAge(this@DataStoreActivity).toString()
37+
}
38+
39+
40+
addButton.setOnClickListener {
41+
lifecycleScope.launch {
42+
DataStoreUtils.setUsername(this@DataStoreActivity, "Asem97")
43+
DataStoreUtils.setAge(this@DataStoreActivity, 28)
44+
DataStoreUtils.setGender(this@DataStoreActivity, true)
45+
46+
recreate()
47+
}
48+
}
49+
}
50+
51+
}
52+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.asemlab.samples.utils
2+
3+
import android.content.Context
4+
import androidx.datastore.core.DataStore
5+
import androidx.datastore.preferences.core.Preferences
6+
import androidx.datastore.preferences.core.booleanPreferencesKey
7+
import androidx.datastore.preferences.core.edit
8+
import androidx.datastore.preferences.core.intPreferencesKey
9+
import androidx.datastore.preferences.core.stringPreferencesKey
10+
import androidx.datastore.preferences.preferencesDataStore
11+
import kotlinx.coroutines.flow.first
12+
import kotlinx.coroutines.flow.map
13+
14+
15+
object DataStoreUtils {
16+
17+
// TODO Init DataStore object
18+
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_details")
19+
20+
// TODO Init keys
21+
val USERNAME_KEY = stringPreferencesKey("username")
22+
val AGE_KEY = intPreferencesKey("age")
23+
val GENDER_KEY = booleanPreferencesKey("gender")
24+
25+
// TODO Write to DataStore
26+
suspend fun setUsername(context: Context, username: String) {
27+
context.dataStore.edit { data ->
28+
data[USERNAME_KEY] = username
29+
}
30+
}
31+
32+
suspend fun setAge(context: Context, age: Int) {
33+
context.dataStore.edit { data ->
34+
data[AGE_KEY] = age
35+
}
36+
}
37+
38+
suspend fun setGender(context: Context, gender: Boolean) {
39+
context.dataStore.edit { data ->
40+
data[GENDER_KEY] = gender
41+
}
42+
}
43+
44+
// TODO Read from DataStore
45+
suspend fun getUsername(context: Context): String {
46+
return context.dataStore.data.map {
47+
it[USERNAME_KEY] ?: ""
48+
}.first()
49+
}
50+
51+
suspend fun getAge(context: Context): Int {
52+
return context.dataStore.data.map {
53+
it[AGE_KEY] ?: 0
54+
}.first()
55+
}
56+
57+
suspend fun getGender(context: Context): Boolean {
58+
return context.dataStore.data.map {
59+
it[GENDER_KEY] ?: false
60+
}.first()
61+
}
62+
63+
64+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<layout>
3+
4+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
5+
xmlns:app="http://schemas.android.com/apk/res-auto"
6+
xmlns:tools="http://schemas.android.com/tools"
7+
android:id="@+id/main"
8+
android:layout_width="match_parent"
9+
android:layout_height="match_parent"
10+
tools:context=".ui.DataStoreActivity">
11+
12+
<TextView
13+
android:id="@+id/usernameTV"
14+
android:layout_width="wrap_content"
15+
android:layout_height="wrap_content"
16+
android:layout_marginVertical="16dp"
17+
android:textSize="18sp"
18+
app:layout_constraintBottom_toTopOf="@+id/ageTV"
19+
app:layout_constraintEnd_toEndOf="parent"
20+
app:layout_constraintHorizontal_bias="0.5"
21+
app:layout_constraintStart_toStartOf="parent"
22+
app:layout_constraintTop_toTopOf="parent"
23+
app:layout_constraintVertical_chainStyle="packed"
24+
tools:text="asem97" />
25+
26+
<TextView
27+
android:id="@+id/ageTV"
28+
android:layout_width="wrap_content"
29+
android:layout_height="wrap_content"
30+
android:layout_marginVertical="16dp"
31+
android:textSize="18sp"
32+
app:layout_constraintBottom_toTopOf="@+id/genderTV"
33+
app:layout_constraintEnd_toEndOf="parent"
34+
app:layout_constraintHorizontal_bias="0.5"
35+
app:layout_constraintStart_toStartOf="parent"
36+
app:layout_constraintTop_toBottomOf="@+id/usernameTV"
37+
tools:text="28" />
38+
39+
<TextView
40+
android:id="@+id/genderTV"
41+
android:layout_width="wrap_content"
42+
android:layout_height="wrap_content"
43+
android:layout_marginVertical="16dp"
44+
android:textSize="18sp"
45+
app:layout_constraintBottom_toTopOf="@id/addButton"
46+
app:layout_constraintEnd_toEndOf="parent"
47+
app:layout_constraintHorizontal_bias="0.5"
48+
app:layout_constraintStart_toStartOf="parent"
49+
app:layout_constraintTop_toBottomOf="@+id/ageTV"
50+
tools:text="Male" />
51+
52+
<Button
53+
android:id="@+id/addButton"
54+
android:layout_width="wrap_content"
55+
android:layout_height="wrap_content"
56+
android:layout_marginVertical="16dp"
57+
android:text="Add default data"
58+
app:layout_constraintBottom_toBottomOf="parent"
59+
app:layout_constraintEnd_toEndOf="parent"
60+
app:layout_constraintStart_toStartOf="parent"
61+
app:layout_constraintTop_toBottomOf="@+id/genderTV" />
62+
63+
64+
</androidx.constraintlayout.widget.ConstraintLayout>
65+
</layout>

gradle/libs.versions.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ benchmarkMacroJunit4 = "1.2.0-beta01"
5656
apollo = "4.0.0"
5757
firebase-distribution = "16.0.0-beta13"
5858
play-services-location = "21.3.0"
59-
59+
datastore = "1.1.7"
6060

6161
[libraries]
6262
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
@@ -130,6 +130,7 @@ apollo-runtime = { module = "com.apollographql.apollo:apollo-runtime", version.r
130130
firebase-appdistribution = { module = "com.google.firebase:firebase-appdistribution", version.ref="firebase-distribution" }
131131
firebase-appdistribution-api-ktx = { module = "com.google.firebase:firebase-appdistribution-api-ktx" , version.ref="firebase-distribution"}
132132
play-services-location = { module = "com.google.android.gms:play-services-location", version.ref = "play-services-location" }
133+
datastore = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" }
133134

134135
[plugins]
135136
android-application = { id = "com.android.application", version.ref = "android-application" }

0 commit comments

Comments
 (0)