2
2
* Nextcloud Talk - Android Client
3
3
*
4
4
* SPDX-FileCopyrightText: 2024 Julius Linus <[email protected] >
5
+ * SPDX-FileCopyrightText: 2024 Marcel Hibbe <[email protected] >
5
6
* SPDX-License-Identifier: GPL-3.0-or-later
6
7
*/
7
8
@@ -11,67 +12,75 @@ import android.content.Context
11
12
import android.net.ConnectivityManager
12
13
import android.net.Network
13
14
import android.net.NetworkCapabilities
14
- import android.net.NetworkRequest.Builder
15
+ import android.util.Log
15
16
import androidx.core.content.getSystemService
16
17
import androidx.lifecycle.LiveData
17
18
import androidx.lifecycle.asLiveData
19
+ import kotlinx.coroutines.CoroutineScope
18
20
import kotlinx.coroutines.Dispatchers
19
21
import kotlinx.coroutines.channels.awaitClose
20
- import kotlinx.coroutines.flow.Flow
22
+ import kotlinx.coroutines.flow.SharingStarted
23
+ import kotlinx.coroutines.flow.StateFlow
21
24
import kotlinx.coroutines.flow.callbackFlow
22
- import kotlinx.coroutines.flow.conflate
23
- import kotlinx.coroutines.flow.distinctUntilChanged
24
- import kotlinx.coroutines.flow.flowOn
25
+ import kotlinx.coroutines.flow.stateIn
25
26
import javax.inject.Inject
26
27
import javax.inject.Singleton
27
28
28
29
@Singleton
29
30
class NetworkMonitorImpl @Inject constructor(
30
31
private val context : Context
31
32
) : NetworkMonitor {
33
+
34
+ private val connectivityManager = context.getSystemService<ConnectivityManager >()!!
35
+
32
36
override val isOnlineLiveData: LiveData <Boolean >
33
37
get() = isOnline.asLiveData()
34
38
35
- override val isOnline: Flow <Boolean > = callbackFlow {
36
- val connectivityManager = context.getSystemService<ConnectivityManager >()
37
- if (connectivityManager == null ) {
38
- channel.trySend(false )
39
- channel.close()
40
- return @callbackFlow
41
- }
42
-
43
- val networkRequest = Builder ()
44
- .addCapability(NetworkCapabilities .NET_CAPABILITY_INTERNET )
45
- .build()
39
+ override val isOnline: StateFlow <Boolean > get() = _isOnline
46
40
47
- val networkCallback = object : ConnectivityManager .NetworkCallback () {
48
- private val networks = mutableSetOf<Network >()
41
+ private val _isOnline : StateFlow <Boolean > = callbackFlow {
42
+ val callback = object : ConnectivityManager .NetworkCallback () {
43
+ override fun onCapabilitiesChanged (network : Network , networkCapabilities : NetworkCapabilities ) {
44
+ super .onCapabilitiesChanged(network, networkCapabilities)
45
+ val connected = networkCapabilities.hasCapability(
46
+ NetworkCapabilities .NET_CAPABILITY_VALIDATED
47
+ )
48
+ trySend(connected)
49
+ Log .d(TAG , " Network status changed: $connected " )
50
+ }
49
51
50
- override fun onAvailable (network : Network ) {
51
- networks + = network
52
- channel.trySend(true )
52
+ override fun onUnavailable () {
53
+ super .onUnavailable()
54
+ trySend(false )
55
+ Log .d(TAG , " Network status: onUnavailable" )
53
56
}
54
57
55
58
override fun onLost (network : Network ) {
56
- networks - = network
57
- channel.trySend(networks.isNotEmpty())
59
+ super .onLost(network)
60
+ trySend(false )
61
+ Log .d(TAG , " Network status: onLost" )
58
62
}
59
- }
60
63
61
- connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
64
+ override fun onAvailable (network : Network ) {
65
+ super .onAvailable(network)
66
+ trySend(true )
67
+ Log .d(TAG , " Network status: onAvailable" )
68
+ }
69
+ }
62
70
63
- channel.trySend( connectivityManager.isCurrentlyConnected() )
71
+ connectivityManager.registerDefaultNetworkCallback(callback )
64
72
65
73
awaitClose {
66
- connectivityManager.unregisterNetworkCallback(networkCallback )
74
+ connectivityManager.unregisterNetworkCallback(callback )
67
75
}
68
- }
69
- .distinctUntilChanged()
70
- .flowOn(Dispatchers .IO )
71
- .conflate()
76
+ }.stateIn(
77
+ CoroutineScope (Dispatchers .IO ),
78
+ SharingStarted .WhileSubscribed (COROUTINE_TIMEOUT ),
79
+ false
80
+ )
72
81
73
- private fun ConnectivityManager. isCurrentlyConnected () =
74
- activeNetwork
75
- ?. let (::getNetworkCapabilities)
76
- ?.hasCapability( NetworkCapabilities . NET_CAPABILITY_INTERNET ) ? : false
82
+ companion object {
83
+ private val TAG = NetworkMonitorImpl :: class .java.simpleName
84
+ private const val COROUTINE_TIMEOUT = 5000L
85
+ }
77
86
}
0 commit comments