kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
Use Ktor/Ktorfit for API calls (#3122)
rodzic
d600d182b5
commit
bec5dac9d4
|
@ -25,7 +25,6 @@ import com.geeksville.mesh.model.DeviceHardware
|
|||
import com.geeksville.mesh.network.DeviceHardwareRemoteDataSource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
@ -69,8 +68,7 @@ constructor(
|
|||
// 2. Fetch from remote API
|
||||
runCatching {
|
||||
debug("Fetching device hardware from remote API.")
|
||||
val remoteHardware =
|
||||
remoteDataSource.getAllDeviceHardware() ?: throw IOException("Empty response from server")
|
||||
val remoteHardware = remoteDataSource.getAllDeviceHardware()
|
||||
|
||||
localDataSource.insertAllDeviceHardware(remoteHardware)
|
||||
localDataSource.getByHwModel(hwModel)?.asExternalModel()
|
||||
|
|
|
@ -26,7 +26,6 @@ import com.geeksville.mesh.database.entity.asExternalModel
|
|||
import com.geeksville.mesh.network.FirmwareReleaseRemoteDataSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
@ -99,8 +98,7 @@ constructor(
|
|||
val remoteFetchSuccess =
|
||||
runCatching {
|
||||
debug("Fetching fresh firmware releases from remote API.")
|
||||
val networkReleases =
|
||||
remoteDataSource.getFirmwareReleases() ?: throw IOException("Empty response from server")
|
||||
val networkReleases = remoteDataSource.getFirmwareReleases()
|
||||
|
||||
// The API fetches all release types, so we cache them all at once.
|
||||
localDataSource.insertFirmwareReleases(networkReleases.releases.stable, FirmwareReleaseType.STABLE)
|
||||
|
|
|
@ -32,6 +32,7 @@ plugins {
|
|||
alias(libs.plugins.kotlin.jvm) apply false
|
||||
alias(libs.plugins.kotlin.parcelize) apply false
|
||||
alias(libs.plugins.kotlin.serialization) apply false
|
||||
alias(libs.plugins.ktorfit) apply false
|
||||
alias(libs.plugins.protobuf) apply false
|
||||
alias(libs.plugins.secrets) apply false
|
||||
alias(libs.plugins.dependency.analysis)
|
||||
|
|
|
@ -22,8 +22,8 @@ hilt = "2.57.1"
|
|||
maps-compose = "6.10.0"
|
||||
|
||||
# Networking
|
||||
okhttp = "5.1.0"
|
||||
retrofit = "3.0.0"
|
||||
ktor = "3.3.0"
|
||||
ktorfit = "2.6.4"
|
||||
|
||||
# Other
|
||||
coil = "3.3.0"
|
||||
|
@ -115,10 +115,11 @@ kotlinx-coroutines-guava = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-
|
|||
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.9.0" }
|
||||
|
||||
# Networking
|
||||
okhttp3 = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
|
||||
okhttp3-logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
|
||||
retrofit2 = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
||||
retrofit2-kotlin-serialization = { module = "com.squareup.retrofit2:converter-kotlinx-serialization", version.ref = "retrofit" }
|
||||
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
|
||||
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
|
||||
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
|
||||
ktorfit = { module = "de.jensklingenberg.ktorfit:ktorfit-lib", version.ref = "ktorfit" }
|
||||
okhttp3-logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version = "5.1.0" }
|
||||
|
||||
# Testing
|
||||
espresso-core = { module = "androidx.test.espresso:espresso-core", version = "3.7.0" }
|
||||
|
@ -189,7 +190,7 @@ firebase = ["firebase-analytics", "firebase-crashlytics", "firebase-performance"
|
|||
maps-compose = ["location-services", "maps-compose", "maps-compose-utils", "maps-compose-widgets"]
|
||||
|
||||
# Networking
|
||||
retrofit = ["retrofit2", "retrofit2-kotlin-serialization", "okhttp3", "okhttp3-logging-interceptor"]
|
||||
ktor = ["ktor-client-content-negotiation", "ktor-client-okhttp", "ktor-serialization-kotlinx-json", "ktorfit", "okhttp3-logging-interceptor"]
|
||||
|
||||
# Other
|
||||
coil = ["coil", "coil-network-core", "coil-network-okhttp", "coil-svg"]
|
||||
|
@ -224,6 +225,7 @@ kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
|||
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
|
||||
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||
kover = { id = "org.jetbrains.kotlinx.kover", version = "0.9.1" }
|
||||
ktorfit = { id = "de.jensklingenberg.ktorfit", version.ref = "ktorfit" }
|
||||
|
||||
# Google
|
||||
devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "devtools-ksp" }
|
||||
|
|
|
@ -22,6 +22,7 @@ plugins {
|
|||
alias(libs.plugins.dokka)
|
||||
alias(libs.plugins.kover)
|
||||
alias(libs.plugins.protobuf)
|
||||
alias(libs.plugins.ktorfit)
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -30,7 +31,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.bundles.retrofit)
|
||||
implementation(libs.bundles.ktor)
|
||||
implementation(libs.bundles.coil)
|
||||
"googleImplementation"(libs.bundles.datadog)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network.di
|
||||
|
||||
import com.geeksville.mesh.network.BuildConfig
|
||||
import com.geeksville.mesh.network.model.NetworkDeviceHardware
|
||||
import com.geeksville.mesh.network.model.NetworkFirmwareReleases
|
||||
import com.geeksville.mesh.network.service.ApiService
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import javax.inject.Singleton
|
||||
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Module
|
||||
class FDroidNetworkModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOkHttpClient(): OkHttpClient = OkHttpClient.Builder()
|
||||
.addInterceptor(
|
||||
interceptor =
|
||||
HttpLoggingInterceptor().apply {
|
||||
if (BuildConfig.DEBUG) {
|
||||
setLevel(HttpLoggingInterceptor.Level.BODY)
|
||||
}
|
||||
},
|
||||
)
|
||||
.build()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideApiService(): ApiService = object : ApiService {
|
||||
override suspend fun getDeviceHardware(): List<NetworkDeviceHardware> =
|
||||
throw NotImplementedError("API calls to getDeviceHardware are not supported on Fdroid builds.")
|
||||
|
||||
override suspend fun getFirmwareReleases(): NetworkFirmwareReleases =
|
||||
throw NotImplementedError("API calls to getFirmwareReleases are not supported on Fdroid builds.")
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network.retrofit
|
||||
|
||||
import com.geeksville.mesh.network.model.NetworkDeviceHardware
|
||||
import com.geeksville.mesh.network.model.NetworkFirmwareReleases
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
private const val ERROR_NO_OP = 420
|
||||
@Singleton
|
||||
class NoOpApiService@Inject constructor() : ApiService {
|
||||
override suspend fun getDeviceHardware(): Response<List<NetworkDeviceHardware>> {
|
||||
return Response.error(ERROR_NO_OP, "Not Found".toResponseBody(null))
|
||||
}
|
||||
|
||||
override suspend fun getFirmwareReleases(): Response<NetworkFirmwareReleases> {
|
||||
return Response.error(ERROR_NO_OP, "Not Found".toResponseBody(null))
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network.di
|
||||
|
||||
import android.content.Context
|
||||
import coil3.ImageLoader
|
||||
import coil3.disk.DiskCache
|
||||
import coil3.memory.MemoryCache
|
||||
import coil3.network.okhttp.OkHttpNetworkFetcherFactory
|
||||
import coil3.request.crossfade
|
||||
import coil3.svg.SvgDecoder
|
||||
import coil3.util.DebugLogger
|
||||
import coil3.util.Logger
|
||||
import com.datadog.android.okhttp.DatadogEventListener
|
||||
import com.datadog.android.okhttp.DatadogInterceptor
|
||||
import com.geeksville.mesh.network.BuildConfig
|
||||
import com.geeksville.mesh.network.retrofit.ApiService
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||
import javax.inject.Singleton
|
||||
|
||||
private const val DISK_CACHE_PERCENT = 0.02
|
||||
private const val MEMORY_CACHE_PERCENT = 0.25
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Module
|
||||
class ApiModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOkHttpClient(): OkHttpClient {
|
||||
|
||||
val loggingInterceptor = HttpLoggingInterceptor().apply {
|
||||
if (BuildConfig.DEBUG) {
|
||||
setLevel(HttpLoggingInterceptor.Level.BODY)
|
||||
}
|
||||
}
|
||||
val tracedHosts = listOf("meshtastic.org")
|
||||
return OkHttpClient.Builder()
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.addInterceptor(DatadogInterceptor.Builder(tracedHosts).build())
|
||||
.eventListenerFactory(DatadogEventListener.Factory())
|
||||
.build()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRetrofit(
|
||||
okHttpClient: OkHttpClient
|
||||
): Retrofit {
|
||||
return Retrofit.Builder()
|
||||
.baseUrl("https://api.meshtastic.org/") // Replace with your base URL
|
||||
.addConverterFactory(
|
||||
Json.asConverterFactory(
|
||||
"application/json; charset=UTF8".toMediaType()
|
||||
)
|
||||
)
|
||||
.client(okHttpClient)
|
||||
.build()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideApiService(retrofit: Retrofit): ApiService {
|
||||
return retrofit.create(ApiService::class.java)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun imageLoader(
|
||||
httpClient: OkHttpClient,
|
||||
@ApplicationContext application: Context,
|
||||
): ImageLoader {
|
||||
val sharedOkHttp = httpClient.newBuilder().build()
|
||||
return ImageLoader.Builder(application)
|
||||
.components {
|
||||
add(
|
||||
OkHttpNetworkFetcherFactory({ sharedOkHttp })
|
||||
)
|
||||
add(SvgDecoder.Factory())
|
||||
}
|
||||
.memoryCache {
|
||||
MemoryCache.Builder()
|
||||
.maxSizePercent(application, MEMORY_CACHE_PERCENT)
|
||||
.build()
|
||||
}
|
||||
.diskCache {
|
||||
DiskCache.Builder()
|
||||
.maxSizePercent(DISK_CACHE_PERCENT)
|
||||
.build()
|
||||
}
|
||||
.logger(if (BuildConfig.DEBUG) DebugLogger(Logger.Level.Verbose) else null)
|
||||
.crossfade(true)
|
||||
.build()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network.di
|
||||
|
||||
import com.datadog.android.okhttp.DatadogEventListener
|
||||
import com.datadog.android.okhttp.DatadogInterceptor
|
||||
import com.geeksville.mesh.network.BuildConfig
|
||||
import com.geeksville.mesh.network.service.ApiService
|
||||
import com.geeksville.mesh.network.service.createApiService
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import de.jensklingenberg.ktorfit.Ktorfit
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.okhttp.OkHttp
|
||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import javax.inject.Singleton
|
||||
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Module
|
||||
class GoogleNetworkModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOkHttpClient(): OkHttpClient = OkHttpClient.Builder()
|
||||
.addInterceptor(
|
||||
interceptor =
|
||||
HttpLoggingInterceptor().apply {
|
||||
if (BuildConfig.DEBUG) {
|
||||
setLevel(HttpLoggingInterceptor.Level.BODY)
|
||||
}
|
||||
},
|
||||
)
|
||||
.addInterceptor(interceptor = DatadogInterceptor.Builder(tracedHosts = listOf("meshtastic.org")).build())
|
||||
.eventListenerFactory(eventListenerFactory = DatadogEventListener.Factory())
|
||||
.build()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideHttpClient(okHttpClient: OkHttpClient): HttpClient = HttpClient(engineFactory = OkHttp) {
|
||||
engine { preconfigured = okHttpClient }
|
||||
|
||||
install(plugin = ContentNegotiation) {
|
||||
json(
|
||||
Json {
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideApiService(httpClient: HttpClient): ApiService {
|
||||
val ktorfit = Ktorfit.Builder().baseUrl(url = "https://api.meshtastic.org/").httpClient(httpClient).build()
|
||||
return ktorfit.createApiService()
|
||||
}
|
||||
}
|
|
@ -18,15 +18,12 @@
|
|||
package com.geeksville.mesh.network
|
||||
|
||||
import com.geeksville.mesh.network.model.NetworkDeviceHardware
|
||||
import com.geeksville.mesh.network.retrofit.ApiService
|
||||
import com.geeksville.mesh.network.service.ApiService
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeviceHardwareRemoteDataSource @Inject constructor(
|
||||
private val apiService: ApiService,
|
||||
) {
|
||||
suspend fun getAllDeviceHardware(): List<NetworkDeviceHardware>? = withContext(Dispatchers.IO) {
|
||||
apiService.getDeviceHardware().body()
|
||||
}
|
||||
class DeviceHardwareRemoteDataSource @Inject constructor(private val apiService: ApiService) {
|
||||
suspend fun getAllDeviceHardware(): List<NetworkDeviceHardware> =
|
||||
withContext(Dispatchers.IO) { apiService.getDeviceHardware() }
|
||||
}
|
||||
|
|
|
@ -18,15 +18,12 @@
|
|||
package com.geeksville.mesh.network
|
||||
|
||||
import com.geeksville.mesh.network.model.NetworkFirmwareReleases
|
||||
import com.geeksville.mesh.network.retrofit.ApiService
|
||||
import com.geeksville.mesh.network.service.ApiService
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class FirmwareReleaseRemoteDataSource @Inject constructor(
|
||||
private val apiService: ApiService,
|
||||
) {
|
||||
suspend fun getFirmwareReleases(): NetworkFirmwareReleases? = withContext(Dispatchers.IO) {
|
||||
apiService.getFirmwareReleases().body()
|
||||
}
|
||||
class FirmwareReleaseRemoteDataSource @Inject constructor(private val apiService: ApiService) {
|
||||
suspend fun getFirmwareReleases(): NetworkFirmwareReleases =
|
||||
withContext(Dispatchers.IO) { apiService.getFirmwareReleases() }
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@ import coil3.svg.SvgDecoder
|
|||
import coil3.util.DebugLogger
|
||||
import coil3.util.Logger
|
||||
import com.geeksville.mesh.network.BuildConfig
|
||||
import com.geeksville.mesh.network.retrofit.ApiService
|
||||
import com.geeksville.mesh.network.retrofit.NoOpApiService
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
@ -42,40 +40,23 @@ private const val MEMORY_CACHE_PERCENT = 0.25
|
|||
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Module
|
||||
class ApiModule {
|
||||
class NetworkModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideApiService(): ApiService {
|
||||
return NoOpApiService()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun imageLoader(
|
||||
httpClient: OkHttpClient,
|
||||
@ApplicationContext application: Context,
|
||||
): ImageLoader {
|
||||
val sharedOkHttp = httpClient.newBuilder().build()
|
||||
return ImageLoader.Builder(application)
|
||||
fun provideImageLoader(okHttpClient: OkHttpClient, @ApplicationContext application: Context): ImageLoader {
|
||||
val sharedOkHttp = okHttpClient.newBuilder().build()
|
||||
return ImageLoader.Builder(context = application)
|
||||
.components {
|
||||
add(
|
||||
OkHttpNetworkFetcherFactory({ sharedOkHttp })
|
||||
)
|
||||
add(OkHttpNetworkFetcherFactory(callFactory = { sharedOkHttp }))
|
||||
add(SvgDecoder.Factory())
|
||||
}
|
||||
.memoryCache {
|
||||
MemoryCache.Builder()
|
||||
.maxSizePercent(application, MEMORY_CACHE_PERCENT)
|
||||
.build()
|
||||
MemoryCache.Builder().maxSizePercent(context = application, percent = MEMORY_CACHE_PERCENT).build()
|
||||
}
|
||||
.diskCache {
|
||||
DiskCache.Builder()
|
||||
.maxSizePercent(DISK_CACHE_PERCENT)
|
||||
.build()
|
||||
}
|
||||
.logger(if (BuildConfig.DEBUG) DebugLogger(Logger.Level.Verbose) else null)
|
||||
.crossfade(true)
|
||||
.diskCache { DiskCache.Builder().maxSizePercent(percent = DISK_CACHE_PERCENT).build() }
|
||||
.logger(logger = if (BuildConfig.DEBUG) DebugLogger(minLevel = Logger.Level.Verbose) else null)
|
||||
.crossfade(enable = true)
|
||||
.build()
|
||||
}
|
||||
}
|
|
@ -15,17 +15,16 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network.retrofit
|
||||
package com.geeksville.mesh.network.service
|
||||
|
||||
import com.geeksville.mesh.network.model.NetworkDeviceHardware
|
||||
import com.geeksville.mesh.network.model.NetworkFirmwareReleases
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.GET
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
|
||||
interface ApiService {
|
||||
@GET("resource/deviceHardware")
|
||||
suspend fun getDeviceHardware(): Response<List<NetworkDeviceHardware>>
|
||||
suspend fun getDeviceHardware(): List<NetworkDeviceHardware>
|
||||
|
||||
@GET("/github/firmware/list")
|
||||
suspend fun getFirmwareReleases(): Response<NetworkFirmwareReleases>
|
||||
@GET("github/firmware/list")
|
||||
suspend fun getFirmwareReleases(): NetworkFirmwareReleases
|
||||
}
|
Ładowanie…
Reference in New Issue