From bf4ddeda0a0b9b61a35c07ac53b6e5563dc0d29c Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Sun, 3 Jul 2022 21:41:44 +0530 Subject: [PATCH] android: rework injection setup --- android/build.gradle.kts | 1 + .../claw/android/injection/ApiModule.kt | 33 ++------------- .../android/injection/InterceptorModule.kt | 20 +++++++++ .../claw/android/injection/OkHttpModule.kt | 41 +++++++++++++++++++ .../interceptors/NapierLoggingInterceptor.kt | 13 ------ .../claw/android/network/NapierLogger.kt | 12 ++++++ .../UserAgentInterceptor.kt | 6 ++- gradle/libs.versions.toml | 1 + 8 files changed, 83 insertions(+), 44 deletions(-) create mode 100644 android/src/main/kotlin/dev/msfjarvis/claw/android/injection/InterceptorModule.kt create mode 100644 android/src/main/kotlin/dev/msfjarvis/claw/android/injection/OkHttpModule.kt delete mode 100644 android/src/main/kotlin/dev/msfjarvis/claw/android/interceptors/NapierLoggingInterceptor.kt create mode 100644 android/src/main/kotlin/dev/msfjarvis/claw/android/network/NapierLogger.kt rename android/src/main/kotlin/dev/msfjarvis/claw/android/{interceptors => network}/UserAgentInterceptor.kt (60%) diff --git a/android/build.gradle.kts b/android/build.gradle.kts index 39cb3a00..d9e6b694 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -50,6 +50,7 @@ dependencies { implementation(libs.kotlinx.serialization.json) implementation(libs.material.motion.core) implementation(libs.material.motion.navigation) + implementation(libs.okhttp.loggingInterceptor) implementation(libs.retrofit.kotlinxSerializationConverter) implementation(libs.sqldelight.extensions.coroutines) } diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/ApiModule.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/ApiModule.kt index f63a2cf3..dc459fc4 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/ApiModule.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/ApiModule.kt @@ -1,19 +1,13 @@ package dev.msfjarvis.claw.android.injection -import android.content.Context import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory -import dagger.Lazy import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import dev.msfjarvis.claw.android.interceptors.NapierLoggingInterceptor -import dev.msfjarvis.claw.android.interceptors.UserAgentInterceptor import dev.msfjarvis.claw.api.LobstersApi import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json -import okhttp3.Cache import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import retrofit2.Retrofit @@ -23,35 +17,16 @@ import retrofit2.create @Module @InstallIn(SingletonComponent::class) object ApiModule { - - @Provides - fun provideCache(@ApplicationContext context: Context): Cache { - return Cache(context.cacheDir, 10 * 1024 * 1024) - } - - @Provides - fun provideClient(cache: Lazy): OkHttpClient { - return OkHttpClient.Builder() - .cache(cache.get()) - .addNetworkInterceptor(UserAgentInterceptor()) - .addNetworkInterceptor(NapierLoggingInterceptor()) - .build() - } - - /** - * Using [Lazy] here is a trick I picked up from Zac Sweers, which he explained in more detail - * here: https://www.zacsweers.dev/dagger-party-tricks-deferred-okhttp-init/ - */ @Provides fun provideRetrofit( - client: Lazy, - json: Lazy, + client: OkHttpClient, + json: Json, ): Retrofit { val contentType = "application/json".toMediaType() return Retrofit.Builder() - .client(client.get()) + .client(client) .baseUrl(LobstersApi.BASE_URL) - .addConverterFactory(json.get().asConverterFactory(contentType)) + .addConverterFactory(json.asConverterFactory(contentType)) .build() } diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/InterceptorModule.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/InterceptorModule.kt new file mode 100644 index 00000000..87596589 --- /dev/null +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/InterceptorModule.kt @@ -0,0 +1,20 @@ +package dev.msfjarvis.claw.android.injection + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet +import dev.msfjarvis.claw.android.network.NapierLogger +import dev.msfjarvis.claw.android.network.UserAgentInterceptor +import okhttp3.Interceptor +import okhttp3.logging.HttpLoggingInterceptor + +@Module +@InstallIn(SingletonComponent::class) +interface InterceptorModule { + + @Binds fun NapierLogger.bindLogger(): HttpLoggingInterceptor.Logger + + @Binds @IntoSet fun UserAgentInterceptor.bindUAInterceptor(): Interceptor +} diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/OkHttpModule.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/OkHttpModule.kt new file mode 100644 index 00000000..e3b6ea9c --- /dev/null +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/OkHttpModule.kt @@ -0,0 +1,41 @@ +package dev.msfjarvis.claw.android.injection + +import android.content.Context +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet +import okhttp3.Cache +import okhttp3.Interceptor +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor + +@Module +@InstallIn(SingletonComponent::class) +object OkHttpModule { + @Provides + fun provideCache(@ApplicationContext context: Context): Cache { + return Cache(context.cacheDir, 10 * 1024 * 1024) + } + + @Provides + fun provideClient( + cache: Cache, + interceptors: Set<@JvmSuppressWildcards Interceptor>, + ): OkHttpClient { + return OkHttpClient.Builder() + .apply { + cache(cache) + interceptors.forEach(::addNetworkInterceptor) + } + .build() + } + + @Provides + @IntoSet + fun provideHttpLoggingInterceptor(logger: HttpLoggingInterceptor.Logger): Interceptor { + return HttpLoggingInterceptor(logger).setLevel(HttpLoggingInterceptor.Level.HEADERS) + } +} diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/interceptors/NapierLoggingInterceptor.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/interceptors/NapierLoggingInterceptor.kt deleted file mode 100644 index 4a69ca1d..00000000 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/interceptors/NapierLoggingInterceptor.kt +++ /dev/null @@ -1,13 +0,0 @@ -package dev.msfjarvis.claw.android.interceptors - -import io.github.aakira.napier.Napier -import okhttp3.Interceptor -import okhttp3.Response - -class NapierLoggingInterceptor : Interceptor { - override fun intercept(chain: Interceptor.Chain): Response { - val request = chain.request() - Napier.d(tag = "LobstersApi") { "${request.method}: ${request.url}" } - return chain.proceed(request) - } -} diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/network/NapierLogger.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/network/NapierLogger.kt new file mode 100644 index 00000000..e3e1df46 --- /dev/null +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/network/NapierLogger.kt @@ -0,0 +1,12 @@ +package dev.msfjarvis.claw.android.network + +import io.github.aakira.napier.Napier +import javax.inject.Inject +import okhttp3.logging.HttpLoggingInterceptor + +/** Implementation of [HttpLoggingInterceptor.Logger] backed by [Napier]. */ +class NapierLogger @Inject constructor() : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Napier.d(tag = "LobstersApi") { message } + } +} diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/interceptors/UserAgentInterceptor.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/network/UserAgentInterceptor.kt similarity index 60% rename from android/src/main/kotlin/dev/msfjarvis/claw/android/interceptors/UserAgentInterceptor.kt rename to android/src/main/kotlin/dev/msfjarvis/claw/android/network/UserAgentInterceptor.kt index 44c6c04e..ca2e57c7 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/interceptors/UserAgentInterceptor.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/network/UserAgentInterceptor.kt @@ -1,10 +1,12 @@ -package dev.msfjarvis.claw.android.interceptors +package dev.msfjarvis.claw.android.network import dev.msfjarvis.claw.android.BuildConfig +import javax.inject.Inject import okhttp3.Interceptor import okhttp3.Response -class UserAgentInterceptor : Interceptor { +/** An OkHttp [Interceptor] that adds a recognizable User-Agent header to all network requests. */ +class UserAgentInterceptor @Inject constructor() : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { return chain.proceed( chain diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e3e6626b..869e5046 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -63,6 +63,7 @@ material_motion-core = { module = "io.github.fornewid:material-motion-compose-co material_motion-navigation = { module = "io.github.fornewid:material-motion-compose-navigation", version.ref = "material_motion" } multiplatform-paging = "io.github.kuuuurt:multiplatform-paging:0.4.7" napier = "io.github.aakira:napier:2.6.1" +okhttp-loggingInterceptor = "com.squareup.okhttp3:logging-interceptor:3.14.9" retrofit-kotlinxSerializationConverter = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0" retrofit-lib = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } retrofit-mock = { module = "com.squareup.retrofit2:retrofit-mock", version.ref = "retrofit" }