Skip to content

Commit

Permalink
Create a class instead of an extension
Browse files Browse the repository at this point in the history
  • Loading branch information
tevincent committed Aug 6, 2024
1 parent 881d04b commit 22b898e
Showing 1 changed file with 53 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,67 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.infomaniak.lib.core.utils
package com.infomaniak.lib.core.networking

import android.content.Context
import android.net.ConnectivityManager
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<Boolean> {
val networks = mutableSetOf<Network>()
val rootServerUrl = "a.root-servers.net"
class NetworkAvailability(private val context: Context) {

fun networkRequestBuilder(): NetworkRequest {
val isNetworkAvailable: Flow<Boolean> = callbackFlow {
val networks = mutableSetOf<Network>()
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<Boolean>.sendNetworkAvailability(networks: MutableSet<Network>) {
launch(Dispatchers.IO) {
send(hasAvailableNetwork(networks))
}
}

private fun networkRequestBuilder(): NetworkRequest {
return NetworkRequest.Builder().apply {
addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH)
addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
Expand All @@ -45,31 +88,13 @@ fun Context.networkStatusFlow(): Flow<Boolean> {
}.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<Network>) = 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"
}
}

0 comments on commit 22b898e

Please sign in to comment.