Merge pull request #1368 from android/mlykotom/offload-connectivity-monitor

Offload connectivity monitor to a background thread
pull/1424/head
Tomáš Mlynarič 8 months ago committed by GitHub
commit 7f2ce57c67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -26,57 +26,68 @@ import android.net.NetworkRequest.Builder
import android.os.Build.VERSION import android.os.Build.VERSION
import android.os.Build.VERSION_CODES import android.os.Build.VERSION_CODES
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.tracing.trace
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flowOn
import javax.inject.Inject import javax.inject.Inject
internal class ConnectivityManagerNetworkMonitor @Inject constructor( internal class ConnectivityManagerNetworkMonitor @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context,
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher,
) : NetworkMonitor { ) : NetworkMonitor {
override val isOnline: Flow<Boolean> = callbackFlow { override val isOnline: Flow<Boolean> = callbackFlow {
val connectivityManager = context.getSystemService<ConnectivityManager>() trace("NetworkMonitor.callbackFlow") {
if (connectivityManager == null) { val connectivityManager = context.getSystemService<ConnectivityManager>()
channel.trySend(false) if (connectivityManager == null) {
channel.close() channel.trySend(false)
return@callbackFlow channel.close()
} return@callbackFlow
}
/** /**
* The callback's methods are invoked on changes to *any* network matching the [NetworkRequest], * The callback's methods are invoked on changes to *any* network matching the [NetworkRequest],
* not just the active network. So we can simply track the presence (or absence) of such [Network]. * not just the active network. So we can simply track the presence (or absence) of such [Network].
*/ */
val callback = object : NetworkCallback() { val callback = object : NetworkCallback() {
private val networks = mutableSetOf<Network>() private val networks = mutableSetOf<Network>()
override fun onAvailable(network: Network) { override fun onAvailable(network: Network) {
networks += network networks += network
channel.trySend(true) channel.trySend(true)
} }
override fun onLost(network: Network) { override fun onLost(network: Network) {
networks -= network networks -= network
channel.trySend(networks.isNotEmpty()) channel.trySend(networks.isNotEmpty())
}
} }
}
val request = Builder() trace("NetworkMonitor.registerNetworkCallback") {
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) val request = Builder()
.build() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
connectivityManager.registerNetworkCallback(request, callback) .build()
connectivityManager.registerNetworkCallback(request, callback)
}
/** /**
* Sends the latest connectivity status to the underlying channel. * Sends the latest connectivity status to the underlying channel.
*/ */
channel.trySend(connectivityManager.isCurrentlyConnected()) channel.trySend(connectivityManager.isCurrentlyConnected())
awaitClose { awaitClose {
connectivityManager.unregisterNetworkCallback(callback) connectivityManager.unregisterNetworkCallback(callback)
}
} }
} }
.flowOn(ioDispatcher)
.conflate() .conflate()
@Suppress("DEPRECATION") @Suppress("DEPRECATION")

Loading…
Cancel
Save