@@ -36,11 +36,15 @@ class ConnectivityServiceImpl(
3636 private val walledCheckCache : WalledCheckCache
3737) : ConnectivityService {
3838
39- private val scope = CoroutineScope (Dispatchers .IO )
39+ companion object {
40+ private const val TAG = " ConnectivityServiceImpl"
41+ private const val CONNECTIVITY_CHECK_ROUTE = " /index.php/204"
42+ }
4043
44+ // region private values
45+ private val scope = CoroutineScope (Dispatchers .IO )
4146 private var availabilityCheckJob: Job ? = null
4247 private var notifyJob: Job ? = null
43-
4448 private val connectivityManager = context.getSystemService(Context .CONNECTIVITY_SERVICE ) as ConnectivityManager
4549 private val listeners = mutableSetOf<NetworkChangeListener >()
4650
@@ -50,52 +54,92 @@ class ConnectivityServiceImpl(
5054 private val key: ConnectivityKey
5155 get() = ConnectivityKey .getBy(accountManager)
5256
53- override fun addListener (listener : NetworkChangeListener ) {
54- listeners.add(listener)
55- }
57+ private val networkCallback = object : ConnectivityManager .NetworkCallback () {
58+ override fun onLost (network : Network ) {
59+ Log_OC .w(TAG , " connection lost" )
60+ updateConnectivity()
61+ }
5662
57- override fun removeListener (listener : NetworkChangeListener ) {
58- listeners.remove(listener)
63+ override fun onCapabilitiesChanged (network : Network , networkCapabilities : NetworkCapabilities ) {
64+ Log_OC .d(TAG , " capability changed" )
65+ updateConnectivity()
66+ }
5967 }
68+ // endregion
6069
61- private fun notifyListeners () {
62- if (listeners.isEmpty()) {
63- return
64- }
70+ init {
71+ connectivityManager.registerDefaultNetworkCallback(networkCallback)
72+ updateConnectivity()
73+ Log_OC .d(TAG , " connectivity service constructed" )
74+ }
6575
66- notifyJob?.cancel()
67- notifyJob = scope.launch {
76+ // region overridden methods
77+ override fun isNetworkAndServerAvailable (callback : GenericCallback <Boolean >) {
78+ availabilityCheckJob?.cancel()
79+ availabilityCheckJob = scope.launch {
6880 val available = ! isInternetWalled()
81+ Log_OC .d(TAG , " isNetworkAndServerAvailable: $available " )
6982 withContext(Dispatchers .Main ) {
70- listeners.forEach {
71- it.networkAndServerConnectionListener(available)
72- }
83+ callback.onComplete(available)
7384 }
7485 }
7586 }
7687
77- private val networkCallback = object : ConnectivityManager .NetworkCallback () {
78- override fun onLost (network : Network ) {
79- Log_OC .w(TAG , " connection lost" )
80- updateConnectivity()
88+ override fun isConnected () = currentConnectivity.isConnected
89+
90+ override fun isInternetWalled (): Boolean {
91+ val currentKey = key
92+ val cachedValue = walledCheckCache.getValue(currentKey)
93+ if (cachedValue != null ) {
94+ Log_OC .d(TAG , " cached value is used, isWalled: $cachedValue " )
95+ return cachedValue
8196 }
8297
83- override fun onCapabilitiesChanged (network : Network , networkCapabilities : NetworkCapabilities ) {
84- Log_OC .d(TAG , " capability changed" )
85- updateConnectivity()
98+ val baseServerAddress = accountManager.user.server.uri.toString()
99+ if (baseServerAddress.isEmpty()) {
100+ Log_OC .e(TAG , " no base server address, internet is walled" )
101+ return true
86102 }
103+
104+ val resolvedCapabilities = resolveNetworkCapabilities()
105+ if (resolvedCapabilities == null || ! isSupportedTransport(resolvedCapabilities)) {
106+ Log_OC .e(TAG , " no usable network transport at check time, treating as walled" )
107+ return true
108+ }
109+
110+ val get = requestBuilder.invoke(baseServerAddress + CONNECTIVITY_CHECK_ROUTE )
111+ val client = clientFactory.createPlainClient()
112+
113+ val isWalled = try {
114+ val status = get.execute(client)
115+ (! (status == HttpStatus .SC_NO_CONTENT && get.getResponseContentLength() <= 0 )).also {
116+ if (it) Log_OC .w(TAG , " server returned unexpected response, status: $status " )
117+ }
118+ } catch (e: Exception ) {
119+ Log_OC .e(TAG , " exception during server check" , e)
120+ getWalledValueFromException(e)
121+ } finally {
122+ get.releaseConnection()
123+ }
124+
125+ walledCheckCache.setValue(currentKey, isWalled)
126+
127+ Log_OC .d(TAG , " server check, isWalled: $isWalled " )
128+ return isWalled
87129 }
88130
89- fun interface GetRequestBuilder {
90- operator fun invoke (url : String ): GetMethod
131+ override fun getConnectivity () = currentConnectivity
132+
133+ override fun addListener (listener : NetworkChangeListener ) {
134+ listeners.add(listener)
91135 }
92136
93- init {
94- connectivityManager.registerDefaultNetworkCallback(networkCallback)
95- updateConnectivity()
96- Log_OC .d(TAG , " connectivity service constructed" )
137+ override fun removeListener (listener : NetworkChangeListener ) {
138+ listeners.remove(listener)
97139 }
140+ // endregion
98141
142+ // region public methods
99143 fun updateConnectivity () {
100144 val currentKey = key
101145 val previous = currentConnectivity
@@ -135,6 +179,33 @@ class ConnectivityServiceImpl(
135179 }
136180 }
137181
182+ @Suppress(" unused" )
183+ fun unregisterCallback () {
184+ connectivityManager.unregisterNetworkCallback(networkCallback)
185+ }
186+
187+ fun interface GetRequestBuilder {
188+ operator fun invoke (url : String ): GetMethod
189+ }
190+ // endregion
191+
192+ // region private methods
193+ private fun notifyListeners () {
194+ if (listeners.isEmpty()) {
195+ return
196+ }
197+
198+ notifyJob?.cancel()
199+ notifyJob = scope.launch {
200+ val available = ! isInternetWalled()
201+ withContext(Dispatchers .Main ) {
202+ listeners.forEach {
203+ it.networkAndServerConnectionListener(available)
204+ }
205+ }
206+ }
207+ }
208+
138209 @Suppress(" DEPRECATION" )
139210 private fun resolveNetworkCapabilities (): NetworkCapabilities ? {
140211 connectivityManager.activeNetwork
@@ -158,62 +229,6 @@ class ConnectivityServiceImpl(
158229 capabilities.hasTransport(NetworkCapabilities .TRANSPORT_USB )
159230 )
160231
161- override fun isNetworkAndServerAvailable (callback : GenericCallback <Boolean >) {
162- availabilityCheckJob?.cancel()
163- availabilityCheckJob = scope.launch {
164- val available = ! isInternetWalled()
165- Log_OC .d(TAG , " isNetworkAndServerAvailable: $available " )
166- withContext(Dispatchers .Main ) {
167- callback.onComplete(available)
168- }
169- }
170- }
171-
172- override fun isConnected () = currentConnectivity.isConnected
173-
174- override fun isInternetWalled (): Boolean {
175- val currentKey = key
176- val cachedValue = walledCheckCache.getValue(currentKey)
177- if (cachedValue != null ) {
178- Log_OC .d(TAG , " cached value is used, isWalled: $cachedValue " )
179- return cachedValue
180- }
181-
182- val baseServerAddress = accountManager.user.server.uri.toString()
183- if (baseServerAddress.isEmpty()) {
184- Log_OC .e(TAG , " no base server address, internet is walled" )
185- return true
186- }
187-
188- val resolvedCapabilities = resolveNetworkCapabilities()
189- if (resolvedCapabilities == null || ! isSupportedTransport(resolvedCapabilities)) {
190- Log_OC .e(TAG , " no usable network transport at check time, treating as walled" )
191- return true
192- }
193-
194- val get = requestBuilder.invoke(baseServerAddress + CONNECTIVITY_CHECK_ROUTE )
195- val client = clientFactory.createPlainClient()
196-
197- val isWalled = try {
198- val status = get.execute(client)
199- (! (status == HttpStatus .SC_NO_CONTENT && get.getResponseContentLength() <= 0 )).also {
200- if (it) Log_OC .w(TAG , " server returned unexpected response, status: $status " )
201- }
202- } catch (e: Exception ) {
203- Log_OC .e(TAG , " exception during server check" , e)
204- getWalledValueFromException(e)
205- } finally {
206- get.releaseConnection()
207- }
208-
209- walledCheckCache.setValue(currentKey, isWalled)
210-
211- Log_OC .d(TAG , " server check, isWalled: $isWalled " )
212- return isWalled
213- }
214-
215- override fun getConnectivity () = currentConnectivity
216-
217232 private fun getWalledValueFromException (e : Exception ): Boolean = when (e) {
218233 is UnknownHostException ,
219234 is ConnectException -> {
@@ -241,14 +256,5 @@ class ConnectivityServiceImpl(
241256 currentConnectivity.isServerAvailable?.let { ! it } ? : true
242257 }
243258 }
244-
245- @Suppress(" unused" )
246- fun unregisterCallback () {
247- connectivityManager.unregisterNetworkCallback(networkCallback)
248- }
249-
250- companion object {
251- private const val TAG = " ConnectivityServiceImpl"
252- private const val CONNECTIVITY_CHECK_ROUTE = " /index.php/204"
253- }
259+ // endregion
254260}
0 commit comments