diff --git a/app/src/main/java/hu/bme/kszk/szobatarsch/data/networkConnection.kt b/app/src/main/java/hu/bme/kszk/szobatarsch/data/networkConnection.kt new file mode 100644 index 0000000000000000000000000000000000000000..5df6aed9044cf94d3277c79e5036de9725c0c706 --- /dev/null +++ b/app/src/main/java/hu/bme/kszk/szobatarsch/data/networkConnection.kt @@ -0,0 +1,87 @@ +package hu.bme.kszk.szobatarsch.data + +import android.content.Context +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.produceState +import androidx.compose.ui.platform.LocalContext +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.callbackFlow + +//Source: https://medium.com/scalereal/observing-live-connectivity-status-in-jetpack-compose-way-f849ce8431c7 and https://github.com/PatilShreyas/NotyKT + +sealed class ConnectionState { + object Available : ConnectionState() + object Unavailable : ConnectionState() +} + +val Context.currentConnectivityState: ConnectionState + get() { + val connectivityManager = + getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + return getCurrentConnectivityState(connectivityManager) + } + +private fun getCurrentConnectivityState( + connectivityManager: ConnectivityManager +): ConnectionState { + val connected = connectivityManager.allNetworks.any { network -> + connectivityManager.getNetworkCapabilities(network) + ?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + ?: false + } + + return if (connected) ConnectionState.Available else ConnectionState.Unavailable +} + +@ExperimentalCoroutinesApi +fun Context.observeConnectivityAsFlow() = callbackFlow { + val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + + val callback = NetworkCallback { connectionState -> trySend(connectionState) } + + val networkRequest = NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .build() + + connectivityManager.registerNetworkCallback(networkRequest, callback) + + // Set current state + val currentState = getCurrentConnectivityState(connectivityManager) + trySend(currentState) + + // Remove callback when not used + awaitClose { + // Remove listeners + connectivityManager.unregisterNetworkCallback(callback) + } +} + +fun NetworkCallback(callback: (ConnectionState) -> Unit): ConnectivityManager.NetworkCallback { + return object : ConnectivityManager.NetworkCallback() { + override fun onAvailable(network: Network) { + callback(ConnectionState.Available) + } + + override fun onLost(network: Network) { + callback(ConnectionState.Unavailable) + } + } +} + +@ExperimentalCoroutinesApi +@Composable +fun connectivityState(): State<ConnectionState> { + val context = LocalContext.current + + // Creates a State<ConnectionState> with current connectivity state as initial value + return produceState(initialValue = context.currentConnectivityState) { + // In a coroutine, can make suspend calls + context.observeConnectivityAsFlow().collect { value = it } + } +} \ No newline at end of file