1717package com.google.samples.apps.nowinandroid.core.network.demo
1818
1919import JvmUnitTestDemoAssetManager
20+ import android.os.Build.VERSION.SDK_INT
21+ import android.os.Build.VERSION_CODES.M
2022import com.google.samples.apps.nowinandroid.core.network.Dispatcher
2123import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
2224import com.google.samples.apps.nowinandroid.core.network.NiaNetworkDataSource
@@ -28,6 +30,7 @@ import kotlinx.coroutines.withContext
2830import kotlinx.serialization.ExperimentalSerializationApi
2931import kotlinx.serialization.json.Json
3032import kotlinx.serialization.json.decodeFromStream
33+ import java.io.BufferedReader
3134import javax.inject.Inject
3235
3336/* *
@@ -39,24 +42,39 @@ class DemoNiaNetworkDataSource @Inject constructor(
3942 private val assets : DemoAssetManager = JvmUnitTestDemoAssetManager ,
4043) : NiaNetworkDataSource {
4144
42- @OptIn(ExperimentalSerializationApi ::class )
4345 override suspend fun getTopics (ids : List <String >? ): List <NetworkTopic > =
44- withContext(ioDispatcher) {
45- assets.open(TOPICS_ASSET ).use(networkJson::decodeFromStream)
46- }
46+ getDataFromJsonFile(TOPICS_ASSET )
4747
48- @OptIn(ExperimentalSerializationApi ::class )
4948 override suspend fun getNewsResources (ids : List <String >? ): List <NetworkNewsResource > =
50- withContext(ioDispatcher) {
51- assets.open(NEWS_ASSET ).use(networkJson::decodeFromStream)
52- }
49+ getDataFromJsonFile(NEWS_ASSET )
5350
5451 override suspend fun getTopicChangeList (after : Int? ): List <NetworkChangeList > =
5552 getTopics().mapToChangeList(NetworkTopic ::id)
5653
5754 override suspend fun getNewsResourceChangeList (after : Int? ): List <NetworkChangeList > =
5855 getNewsResources().mapToChangeList(NetworkNewsResource ::id)
5956
57+ /* *
58+ * Get data from the given JSON [fileName].
59+ */
60+ @OptIn(ExperimentalSerializationApi ::class )
61+ private suspend inline fun <reified T > getDataFromJsonFile (fileName : String ): List <T > =
62+ withContext(ioDispatcher) {
63+ assets.open(fileName).use { inputStream ->
64+ if (SDK_INT <= M ) {
65+ /* *
66+ * On API 23 (M) and below we must use a workaround to avoid an exception being
67+ * thrown during deserialization. See:
68+ * https://github.com/Kotlin/kotlinx.serialization/issues/2457#issuecomment-1786923342
69+ */
70+ inputStream.bufferedReader().use(BufferedReader ::readText)
71+ .let (networkJson::decodeFromString)
72+ } else {
73+ networkJson.decodeFromStream(inputStream)
74+ }
75+ }
76+ }
77+
6078 companion object {
6179 private const val NEWS_ASSET = " news.json"
6280 private const val TOPICS_ASSET = " topics.json"
0 commit comments