Search code examples
android

How to check internet connection in Android


In my application I want check internet connection and for this I write below codes.
But when before run application and disconnect internet, not call checked internet code!
Just when internet connection is connected and run application with connected internet then disconnect internet show internet is connect or disconnect!

Internet connection class:

class NetworkConnectivity @Inject constructor(private val manager: ConnectivityManager, private val request: NetworkRequest) : ConnectivityStatus {
    override fun observe(): Flow<Boolean> {
        return callbackFlow {
            val callback = object : ConnectivityManager.NetworkCallback() {
                override fun onAvailable(network: Network) {
                    super.onAvailable(network)
                    launch { send(true) }
                }

                override fun onLost(network: Network) {
                    super.onLost(network)
                    launch { send(false) }
                }
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                manager.registerDefaultNetworkCallback(callback)
            } else {
                manager.registerNetworkCallback(request, callback)
            }
            awaitClose {
                manager.unregisterNetworkCallback(callback)
            }
        }
    }
}

ViewModel class:

@HiltViewModel
class DetailViewModel @Inject constructor(private val repository: MainRepository) : ViewModel() {
    @Inject
    lateinit var networkConnectivity: NetworkConnectivity    

    val detailData = MutableLiveData<NetworkRequest<ResponseDetailPage>>()
    fun callDetailApi(id: Int, apiKey: String) = viewModelScope.launch {
        Log.e("DetailLog","ViewModel 1")
        networkConnectivity.observe().collect {
            if (it) {
                Log.e("DetailLog","ViewModel 2")
                detailData.value = NetworkRequest.Loading()
                //Response
                val response = repository.remote.recipeInformation(id, apiKey)
                detailData.value = NetworkResponse(response).generalNetworkResponse()
            } else {
                Log.e("DetailLog","ViewModel 3")
                detailData.value = NetworkRequest.Error("No internet connection")
            }
        }
    }
}

After run application (when internet is disconnected) just show ViewModel 1 log in logcat!

Why not checked internet when start application with disconnected mode?


Solution

  • I'm using this function to check for internet connectivity:

    fun isInternetAvailable(context: Context): Boolean {
            var result = false
            val connectivityManager =
                    context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val networkCapabilities = connectivityManager.activeNetwork ?: return false
                val actNw =
                        connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
                result = when {
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                    else -> false
                }
            } else {
                connectivityManager.run {
                    connectivityManager.activeNetworkInfo?.run {
                        result = when (type) {
                            ConnectivityManager.TYPE_WIFI -> true
                            ConnectivityManager.TYPE_MOBILE -> true
                            ConnectivityManager.TYPE_ETHERNET -> true
                            else -> false
                        }
    
                    }
                }
            }
            return result
        }
    

    If you target SDK23+, you can remove build version check.

    Here's how I call this function in my viewmodel:

    private val _internetIsAvailable = MutableLiveData<Boolean?>()
        val extInternetAvailable: LiveData<Boolean?> get() = _internetIsAvailable
        private val _loadStatus = MutableLiveData<LoadStatus>()
        val extLoadStatus: LiveData<LoadStatus> get() = _loadStatus
    
        init {
            // runs every time VM is created (not view created)
            viewModelScope.launch {
                _loadStatus.value = LoadStatus.LOADING
                _internetIsAvailable.value = NetworkChecker(app).isInternetAvailable()
                _loadStatus.value = LoadStatus.DONE
            }
        }
    

    In fragments:

    private fun observeInternetAvailability() {
            mainVM.extInternetAvailable.observe(this) { intAvailable ->
                Logger.d("Internet is $intAvailable")
                if (intAvailable == false) {
                    ToastUtils.updateWarning(this, getString(R.string.no_internet))
                    showLoading(true)
                }
            }
        }