Search code examples
androidmoduledagger-2

How to check internet connection in dagger 2 module for okhttp3


I am creating module for okhttp3 using dagger 2. Now i want to check internet connection inside network module. What is the best way to achieve that?


Solution

  • For those who are Following MVVM or Kotlin Coroutines(not necessary) and above api 22 here it is:

    With the new implementation of Dagger Android and MVVM.
    Before deep dive into it your dagger class graph or object graph is already set, then you have to do something like:

    ConnectivityInterceptor Interface

    interface ConnectivityInterceptor : Interceptor
    


    ConnectivityInterceptorImpl

    You can use Custom Exception class or simply use IOException
    To Check the internet connection state of mobile device you've to use connectivity manager and of course enable network state from manifest as well
    In the isOnline() there are some of things which were daprecated forapi 28 or api 29 and some method can't be usable if api level is below 22 so i used current state which not going to bother you either if you are above api 22

    class ConnectivityInterceptorImpl (
        private var application: Application
    ) : ConnectivityInterceptor {
    
        override fun intercept(chain: Interceptor.Chain): Response {
            if (!isOnline())
                throw NoConnectivityException() //custom Exception class
            return chain.proceed(chain.request())
        }
    
        private fun isOnline(): Boolean {
            val connectivityManager = application.getSystemService(
                Context.CONNECTIVITY_SERVICE
            ) as ConnectivityManager
            var res = false
            connectivityManager.let {
                it.getNetworkCapabilities(connectivityManager.activeNetwork)?.apply {
                    res = when {
                        hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                        hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                        else -> false
                    }
                }
            }
            return res
        }
    }
    



    Dagger AppModule

    Here comes the Dagger Thing:
    As we are using Interceptor for network state which is of course going to act as interceptor in the okHttpClient and Okkhttp is used here to make the network calls following by the retrofitBuilder() which means we are doing something called Singleton, so in that case we have to manage the object graph of Dagger

    @Module
    abstract class AppModule {
    
        @Module
        companion object {
            @JvmStatic
            @Singleton
            @Provides
            fun providesConnectivityInterceptorImpl(application: Application):
                    ConnectivityInterceptorImpl {
                return ConnectivityInterceptorImpl(application)
            }
    
            @JvmStatic
            @Singleton
            @Provides
            fun getClient(connectivityInterceptorImpl: ConnectivityInterceptorImpl): ApiService {
                val requestInterceptor = Interceptor { chain ->
                    val url = chain.request()
                        .url()
                        .newBuilder()
                        .addQueryParameter("api", KEY)
                        .build()
    
                    val request =
                        chain
                            .request()
                            .newBuilder()
                            .url(url)
                            .build()
                    return@Interceptor chain.proceed(request)
                }
    
                val okHttpClient = OkHttpClient
                    .Builder()
                    .addInterceptor(connectivityInterceptorImpl) // here it is
                    .addInterceptor(requestInterceptor)
                    .connectTimeout(60, TimeUnit.SECONDS)
                    .build()
    
                return Retrofit.Builder()
                    .client(okHttpClient)
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
                    .create(ApiService::class.java)
            }
        }
    }
    



    Enum Class

    To handle network State

    enum class Status  {
        RUNNING,
        SUCCESS,
        FAILED
    }
    
    class NetworkState(val status: Status, val msg: String) {
        companion object {
            val LOADED: NetworkState = NetworkState(Status.SUCCESS,"Success")
            val LOADING: NetworkState = NetworkState(Status.RUNNING,"Running")
            val ERROR: NetworkState = NetworkState(Status.FAILED,"Failed")
        }
    }
    



    Repository

    Do this in the Repository:
    if you are using DataSource layer, you can do that in dataSource class

    private val _networkState = MutableLiveData<NetworkState>()
        val returnNetworkState: LiveData<NetworkState>
            get() = _networkState
    fun networkData(){
    CoroutineScope(IO).launch {
                _networkState.postValue(NetworkState.LOADING)
                try {
                   //Asynchronous Operation
                   _networkState.postValue(NetworkState.LOADED)
    
                } catch (e: NoConnectivityException) { // custom exception class
                    Log.d(TAG, "No Internet Is Available")
                   _networkState.postValue(NetworkState.ERROR)
    
                }
            }   
         }
    



    Inside your Activity/Fragment update your UI observing through LiveData accordingly.

    myViewModel.returnNetworkState.observe(this, Observer {
              //textView or anything
            })
    


    All Done.