2

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?

taman neupane
  • 938
  • 9
  • 18

2 Answers2

3

Take a look at any of the answers to this canonical question and simply encapsulate them.

For example, you could have an interface like this:

public interface OnlineChecker {
    boolean isOnline();
}

And then most upvoted implementation:

public class DefaultOnlineChecker implements OnlineChecker {

    private final ConnectivityManager connectivityManager;

    public DefaultOnlineChecker(ConnectivityManager connectivityManager) {
        this.connectivityManager = connectivityManager;
    }

    @Override
    public boolean isOnline() {
         NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
         return netInfo != null && netInfo.isConnectedOrConnecting();
    }
}

The second-most upvoted implementation:

public class ExperimentalOnlineChecker implements OnlineChecker {

    private final Runtime runtime;

    public ExperimentalOnlineChecker(Runtime runtime) {
        this.runtime = runtime;
    }

    @Override
    public boolean isOnline() {
        try {
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int     exitValue = ipProcess.waitFor();
            return (exitValue == 0);
        }
        catch (IOException e)          { e.printStackTrace(); }
        catch (InterruptedException e) { e.printStackTrace(); }

        return false;
    }
}

Then in its own module or elsewhere just bind the implementation you want:

@Module
public class OnlineCheckerModule {

    @Provides
    public OnlineChecker onlineChecker() {
        Runtime runtime = Runtime.getRuntime();
        return new ExperimentalOnlineChecker(runtime);
    }
}

Now inside your Activity or Fragment you can simply inject using property injection:

@Inject OnlineChecker onlineChecker;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super(savedInstanceState);
    //perform injection with Dagger 2 and then you can use your
    //OnlineChecker
}
David Rawson
  • 20,912
  • 7
  • 88
  • 124
3

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.

USMAN osman
  • 952
  • 7
  • 13