diff --git a/src/main/java/com/infomaniak/lib/core/utils/NetworkExtensions.kt b/src/main/java/com/infomaniak/lib/core/networking/NetworkAvailability.kt similarity index 57% rename from src/main/java/com/infomaniak/lib/core/utils/NetworkExtensions.kt rename to src/main/java/com/infomaniak/lib/core/networking/NetworkAvailability.kt index 14200ef9..98b41a4e 100644 --- a/src/main/java/com/infomaniak/lib/core/utils/NetworkExtensions.kt +++ b/src/main/java/com/infomaniak/lib/core/networking/NetworkAvailability.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.infomaniak.lib.core.utils +package com.infomaniak.lib.core.networking import android.content.Context import android.net.ConnectivityManager @@ -23,16 +23,59 @@ import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest import android.os.Build +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.channels.ProducerScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.launch -fun Context.networkStatusFlow(): Flow { - val networks = mutableSetOf() - val rootServerUrl = "a.root-servers.net" +class NetworkAvailability(private val context: Context) { - fun networkRequestBuilder(): NetworkRequest { + val isNetworkAvailable: Flow = callbackFlow { + val networks = mutableSetOf() + val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + + val callback = object : ConnectivityManager.NetworkCallback() { + + override fun onAvailable(network: Network) { + networks.add(network) + sendNetworkAvailability(networks) + } + + override fun onLost(network: Network) { + networks.remove(network) + sendNetworkAvailability(networks) + } + } + + launch(Dispatchers.IO) { + send(getInitialNetworkAvailability(connectivityManager)) + } + + connectivityManager.registerNetworkCallback(networkRequestBuilder(), callback) + + awaitClose { connectivityManager.unregisterNetworkCallback(callback) } + } + + @Suppress("DEPRECATION") + private fun getInitialNetworkAvailability(connectivityManager: ConnectivityManager): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + connectivityManager.activeNetwork?.let { + hasInternetConnectivity(it) + } ?: false + } else { + connectivityManager.activeNetworkInfo?.isConnected ?: false + } + } + + private fun ProducerScope.sendNetworkAvailability(networks: MutableSet) { + launch(Dispatchers.IO) { + send(hasAvailableNetwork(networks)) + } + } + + private fun networkRequestBuilder(): NetworkRequest { return NetworkRequest.Builder().apply { addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH) addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) @@ -45,31 +88,13 @@ fun Context.networkStatusFlow(): Flow { }.build() } - fun hasInternetConnectivity(network: Network): Boolean = runCatching { - network.getByName(rootServerUrl) != null + private fun hasInternetConnectivity(network: Network) = runCatching { + network.getByName(ROOT_SERVER_URL) != null }.getOrDefault(false) - fun hasAvailableNetwork() = networks.any(::hasInternetConnectivity) + private fun hasAvailableNetwork(networks: MutableSet) = networks.any { hasInternetConnectivity(it) } - return callbackFlow { - val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - - val callback = object : ConnectivityManager.NetworkCallback() { - override fun onAvailable(network: Network) { - networks.add(network) - launch { send(hasAvailableNetwork()) } - } - - override fun onLost(network: Network) { - networks.remove(network) - launch { send(hasAvailableNetwork()) } - } - } - - connectivityManager.registerNetworkCallback(networkRequestBuilder(), callback) - - awaitClose { - connectivityManager.unregisterNetworkCallback(callback) - } + companion object { + private const val ROOT_SERVER_URL = "a.root-servers.net" } }