Hernâni Pereira
Hernâni Pereira

Reputation: 324

Android Pass Context in object

I need to pass the Application Context to an object. This is to call a function to intercept in the okhttpClient, my connection service. I'am using an object class to build the connection to the server with retrofit and an external interface with my services.

object DfreeApiService  {

   private lateinit var interceptor: HttpLoggingInterceptor
   private lateinit var okHttpClient: OkHttpClient
   private lateinit var networkConnectivityInterceptor: NetworkConnectivityInterceptor

   val client: Retrofit
   get() {
       networkConnectivityInterceptor= NetworkConnectivityInterceptor() //cannot pass the context here
       interceptor = HttpLoggingInterceptor()
       interceptor.level = HttpLoggingInterceptor.Level.BODY
       okHttpClient= OkHttpClient.Builder()
          // .addInterceptor(networkConnectivityInterceptor)
           .addInterceptor(interceptor)
           .connectionSpecs(
               Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT)
           )
           .followRedirects(true)
           .followSslRedirects(true)
           .retryOnConnectionFailure(true)
           .connectTimeout(20, TimeUnit.SECONDS)
           .readTimeout(20, TimeUnit.SECONDS)
           .writeTimeout(20, TimeUnit.SECONDS)
           .cache(null)
           .build()

           val retrofit: Retrofit =Retrofit.Builder()
               .client(okHttpClient)
               .baseUrl("http://example:2000/")
               .addConverterFactory(GsonConverterFactory.create())
               .build()

       return retrofit

   }

}

And in the following code is my interface:

interface AuthenticationApi {

    @POST("ws/login")
    suspend fun login(@Body userInfo: UserInfo): Response<UserReponse>

    @POST("ws/register")
    suspend fun register(@Body userInfo: UserRegister): Response<UserReponse>

    @POST("ws/pw_recover")
    suspend fun pw_recover(@Body email: String): Response<BaseResponse>

    @POST("ws/login")
    suspend fun loginGoogle(@Body user: GoogleUser) : Response<UserReponse>


    companion object{
        operator fun invoke():AuthenticationApi{
            return DfreeApiService.client.create(AuthenticationApi::class.java)
        }
    }
  }

I'am using mvvm and kodein. Without the internet interceptor the app crashes when there is no internet. My interceptor:

    class NetworkConnectivityInterceptor(
    context: Context
    ) : Interceptor {

    private val applicationContext = context

    @RequiresApi(Build.VERSION_CODES.M)
    override fun intercept(chain: Interceptor.Chain): Response {
        if (!isInternetAvailable())
            throw NoInternetException("Make sure you have an active data connection")
        return chain.proceed(chain.request())
    }

    @RequiresApi(Build.VERSION_CODES.M)
    private fun isInternetAvailable(): Boolean {
        var result = false
        val connectivityManager =
            applicationContext.getSystemService(Application.CONNECTIVITY_SERVICE) as ConnectivityManager?
        connectivityManager?.let {
            it.getNetworkCapabilities(connectivityManager.activeNetwork)?.apply {
                result = when {
                    hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                    hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                    else -> false
                }

            }
        }
        return result
    }
}

Thanks for your attention

Upvotes: 2

Views: 4603

Answers (1)

Hern&#226;ni Pereira
Hern&#226;ni Pereira

Reputation: 324

In the mainActivity:

class ExampleApplication : Application(), KodeinAware {
lateinit var context: Context
override val kodein = Kodein.lazy {
    import(androidXModule(this@ExampleApplication))
    bind() from singleton { ExampleApiService }
    bind() from singleton { AuthenticationApi() }
    bind() from singleton { NetworkConnectivityInterceptor(instance()) }
    bind() from singleton { ExampleDataBase(instance()) }
    bind<UserRepository>() with singleton { UserRepository(instance(), instance()) }
    bind() from provider { AuthenticationLoginViewModelFactory(instance(),instance()) }
    bind() from provider { CreateAccountViewModelFactory(instance(),instance()) }
    bind() from provider { PasswordViewModelFactory(instance(),instance()) }
}

override fun onCreate() {
    super.onCreate()
    DfreeApiService.init(this)
}

}

And in the object DfreeApiSercive:

object DfreeApiService  {

private lateinit var application: Application

fun init(application: Application){
    this.application=application
}

 private lateinit var interceptor: HttpLoggingInterceptor
private lateinit var okHttpClient: OkHttpClient
private lateinit var networkConnectivityInterceptor: NetworkConnectivityInterceptor


val client: Retrofit
get() {
    networkConnectivityInterceptor= NetworkConnectivityInterceptor(application.applicationContext)
    interceptor = HttpLoggingInterceptor()
    interceptor.level = HttpLoggingInterceptor.Level.BODY
    okHttpClient= OkHttpClient.Builder()
        .addInterceptor(networkConnectivityInterceptor)
        .addInterceptor(interceptor)
...
}
}

And with this way you can import the context to an object.

Upvotes: 3

Related Questions