diff --git a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt index dc075f299..67c829f0d 100644 --- a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt +++ b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt @@ -22,7 +22,6 @@ import android.net.ConnectivityManager.NetworkCallback import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest -import android.net.NetworkRequest.Builder import androidx.core.content.getSystemService import androidx.tracing.trace import com.google.samples.apps.nowinandroid.core.common.network.Dispatcher @@ -33,12 +32,13 @@ import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn import javax.inject.Inject internal class ConnectivityManagerNetworkMonitor @Inject constructor( - @ApplicationContext private val context: Context, - @Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher, + @param:ApplicationContext private val context: Context, + @param:Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher, ) : NetworkMonitor { override val isOnline: Flow = callbackFlow { trace("NetworkMonitor.callbackFlow") { @@ -69,8 +69,12 @@ internal class ConnectivityManagerNetworkMonitor @Inject constructor( } trace("NetworkMonitor.registerNetworkCallback") { - val request = Builder() + val request = NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .build() connectivityManager.registerNetworkCallback(request, callback) } @@ -87,9 +91,31 @@ internal class ConnectivityManagerNetworkMonitor @Inject constructor( } .flowOn(ioDispatcher) .conflate() + .distinctUntilChanged() private fun ConnectivityManager.isCurrentlyConnected(): Boolean { - val networkCapabilities = getNetworkCapabilities(activeNetwork) ?: return false - return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + val network = activeNetwork ?: return false + val capabilities = getNetworkCapabilities(network) ?: return false + + return hasInternetCapability(capabilities) && + isValidated(capabilities) && + hasSupportedTransport(capabilities) + } + + private fun hasInternetCapability(capabilities: NetworkCapabilities): Boolean { + return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + } + + private fun isValidated(capabilities: NetworkCapabilities): Boolean { + return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + } + + private fun hasSupportedTransport(capabilities: NetworkCapabilities): Boolean { + val supportedTransports = setOf( + NetworkCapabilities.TRANSPORT_WIFI, + NetworkCapabilities.TRANSPORT_CELLULAR, + NetworkCapabilities.TRANSPORT_ETHERNET, + ) + return supportedTransports.any(capabilities::hasTransport) } }