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?
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.