Files
archived-matedroid/app/src/main/java/com/matedroid/di/NetworkModule.kt
T
Davide Ferrari d0fe97884a chore: remove unnecessary moshi-kotlin reflection dependency (#30)
Remove moshi-kotlin (reflection-based adapter) since the project uses
KSP code generation with @JsonClass(generateAdapter = true).

Benefits:
- Smaller APK size (no reflection library)
- Faster JSON parsing (generated code vs reflection)
- Cleaner dependency tree

Note: The Moshi kapt deprecation warning during hiltJavaCompileDebug
is a known Hilt bug and will persist until Hilt fixes it or Moshi 2.0
removes kapt support entirely.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 14:18:57 +01:00

146 lines
4.8 KiB
Kotlin

package com.matedroid.di
import android.annotation.SuppressLint
import com.matedroid.data.api.NominatimApi
import com.matedroid.data.api.TeslamateApi
import com.matedroid.data.local.SettingsDataStore
import com.squareup.moshi.Moshi
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideMoshi(): Moshi {
return Moshi.Builder()
.build()
}
@Provides
@Singleton
fun provideTeslamateApiFactory(
settingsDataStore: SettingsDataStore,
moshi: Moshi
): TeslamateApiFactory {
return TeslamateApiFactory(settingsDataStore, moshi)
}
@Provides
@Singleton
fun provideNominatimApi(moshi: Moshi): NominatimApi {
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.build()
return Retrofit.Builder()
.baseUrl("https://nominatim.openstreetmap.org/")
.client(okHttpClient)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(NominatimApi::class.java)
}
}
class TeslamateApiFactory(
private val settingsDataStore: SettingsDataStore,
private val moshi: Moshi
) {
private var currentBaseUrl: String? = null
private var currentAcceptInvalidCerts: Boolean? = null
private var currentApi: TeslamateApi? = null
fun create(baseUrl: String, acceptInvalidCerts: Boolean? = null): TeslamateApi {
val normalizedUrl = baseUrl.trimEnd('/') + "/"
val settings = runBlocking { settingsDataStore.settings.first() }
val useInsecure = acceptInvalidCerts ?: settings.acceptInvalidCerts
// Return cached API if settings haven't changed
if (currentBaseUrl == normalizedUrl &&
currentAcceptInvalidCerts == useInsecure &&
currentApi != null) {
return currentApi!!
}
val okHttpClient = createOkHttpClient(settings.apiToken, useInsecure)
currentBaseUrl = normalizedUrl
currentAcceptInvalidCerts = useInsecure
currentApi = Retrofit.Builder()
.baseUrl(normalizedUrl)
.client(okHttpClient)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(TeslamateApi::class.java)
return currentApi!!
}
fun invalidateCache() {
currentBaseUrl = null
currentAcceptInvalidCerts = null
currentApi = null
}
private fun createOkHttpClient(apiToken: String, acceptInvalidCerts: Boolean): OkHttpClient {
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
val builder = OkHttpClient.Builder()
.addInterceptor { chain ->
val request = if (apiToken.isNotBlank()) {
chain.request().newBuilder()
.addHeader("Authorization", "Bearer $apiToken")
.build()
} else {
chain.request()
}
chain.proceed(request)
}
.addInterceptor(loggingInterceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
if (acceptInvalidCerts) {
configureInsecureTls(builder)
}
return builder.build()
}
@SuppressLint("TrustAllX509TrustManager", "CustomX509TrustManager")
private fun configureInsecureTls(builder: OkHttpClient.Builder) {
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
})
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustAllCerts, SecureRandom())
builder.sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
builder.hostnameVerifier { _, _ -> true }
}
}