Skip to content

fix: connectivity service#16232

Open
alperozturk96 wants to merge 21 commits into
masterfrom
fix/connectivity-serv
Open

fix: connectivity service#16232
alperozturk96 wants to merge 21 commits into
masterfrom
fix/connectivity-serv

Conversation

@alperozturk96
Copy link
Copy Markdown
Collaborator

@alperozturk96 alperozturk96 commented Jan 2, 2026

  • Tests written, or not not needed

Fixes: #14681

Deduplicates isNetworkAndServerAvailable logic

Implements ConnectivityManager.NetworkCallback for better network state listening

Removes deprecated logics

Adds better documentation

Adds exception handling for http call to prevent temporary issues thus we don't inform user with incorrect availability state

Uses for metered detection NET_CAPABILITY_NOT_METERED instead of NET_CAPABILITY_NOT_RESTRICTED

Removes network change receiver uses listener for much better reaction to network change

Converts to Kotlin

ZetaTom

This comment was marked as resolved.

@TheCrowned
Copy link
Copy Markdown

I gave this build a try - same error for me (both on upload, and on file listing).
The screenshot clearly shows network is available, both as WiFi and as data.
If it can help troubleshooting, upload works when I turn off WiFi and only leave data.
Screenshot_20260211-190409_Nextcloud QA

@alperozturk96
Copy link
Copy Markdown
Collaborator Author

@TheCrowned Hello. Thank you for the feedback. I updated the PR. Could you please check via latest APK file once its generated?

@nextcloud nextcloud deleted a comment from github-actions Bot Apr 7, 2026
@nextcloud nextcloud deleted a comment from github-actions Bot Apr 7, 2026
@alperozturk96 alperozturk96 force-pushed the fix/connectivity-serv branch 2 times, most recently from 2181611 to 1fb36f6 Compare April 8, 2026 09:59
@alperozturk96 alperozturk96 added performance 🚀 Performance improvement opportunities (non-crash related) 2. developing and removed 3. to review labels Apr 8, 2026
alperozturk96 and others added 12 commits May 11, 2026 15:49
…vice.java

Co-authored-by: Tom <70907959+ZetaTom@users.noreply.github.com>
Signed-off-by: Alper Öztürk <67455295+alperozturk96@users.noreply.github.com>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>

# Conflicts:
#	gradle/libs.versions.toml
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
@alperozturk96 alperozturk96 force-pushed the fix/connectivity-serv branch from 71cfd4c to bfe2f88 Compare May 11, 2026 13:51
@alperozturk96
Copy link
Copy Markdown
Collaborator Author

@TheCrowned Could you explain your setup I cannot reproduce this issue?

Is it local Nextcloud instance?
VPN on or off?

Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
@TheCrowned
Copy link
Copy Markdown

@alperozturk96 nothing fancy I believe. It works fine on older Nextcloud android versions (and on latest on Linux Mint).

Is it local Nextcloud instance?

It's remotely hosted on a VPS, publicly accessible hosted on a subdomain.

VPN on or off?

No VPN.

Signed-off-by: Alper Öztürk <67455295+alperozturk96@users.noreply.github.com>
@nextcloud nextcloud deleted a comment from github-actions Bot May 21, 2026
@nextcloud nextcloud deleted a comment from github-actions Bot May 21, 2026
@nextcloud nextcloud deleted a comment from github-actions Bot May 21, 2026
@nextcloud nextcloud deleted a comment from github-actions Bot May 21, 2026
@nextcloud nextcloud deleted a comment from github-actions Bot May 21, 2026
@nextcloud nextcloud deleted a comment from github-actions Bot May 21, 2026
@alperozturk96 alperozturk96 requested a review from Copilot May 21, 2026 12:30
@github-actions
Copy link
Copy Markdown

Codacy

SpotBugs

CategoryBaseNew
Bad practice3535
Correctness6767
Dodgy code216215
Experimental11
Internationalization77
Malicious code vulnerability22
Multithreaded correctness3434
Performance4242
Security1616
Total420419

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the app’s connectivity detection and server reachability logic to address incorrect “No internet connection” states (issue #14681), by switching from a broadcast receiver approach to ConnectivityManager.NetworkCallback, deduplicating availability checks, and migrating the connectivity service implementation to Kotlin.

Changes:

  • Replaces the Java ConnectivityServiceImpl with a Kotlin implementation that tracks network state via NetworkCallback and notifies listeners.
  • Introduces keyed caching (ConnectivityKey) and updates cache invalidation/usage points accordingly.
  • Updates activities/tests to use the new listener API and adds/updates unit + instrumentation test scaffolding.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
gradle/verification-metadata.xml Adds verification metadata entry for coroutines BOM used by new test dependency.
gradle/libs.versions.toml Adds version + coordinate for kotlinx-coroutines-test.
app/build.gradle.kts Adds kotlinx-coroutines-test to unit test dependencies.
app/src/main/java/com/nextcloud/client/network/ConnectivityServiceImpl.kt New Kotlin connectivity implementation using NetworkCallback, listener notifications, and server reachability checks.
app/src/main/java/com/nextcloud/client/network/ConnectivityServiceImpl.java Removes legacy Java implementation.
app/src/main/java/com/nextcloud/client/network/ConnectivityService.java Expands API with listener registration and updates documentation.
app/src/main/java/com/nextcloud/client/network/NetworkChangeListener.kt New listener interface replacing the receiver-based listener.
app/src/main/java/com/nextcloud/client/network/ConnectivityKey.kt Adds a cache key type for per-account/per-baseUrl caching.
app/src/main/java/com/nextcloud/client/network/Connectivity.kt Extends connectivity model with isVPN.
app/src/main/java/com/nextcloud/client/network/WalledCheckCache.kt Reworks caching to be keyed and adds connectivity cache storage.
app/src/main/java/com/nextcloud/client/network/NetworkModule.java Updates DI wiring to construct the service from Context instead of providing ConnectivityManager.
app/src/main/java/com/owncloud/android/ui/activity/FileActivity.java Removes broadcast receiver registration and registers/unregisters as a connectivity listener in lifecycle.
app/src/main/java/com/owncloud/android/MainApp.java Removes broadcast receiver usage and registers as a connectivity listener.
app/src/main/java/com/owncloud/android/utils/ReceiversHelper.java Updates cache clearing to clear keyed connectivity state.
app/src/main/java/com/nextcloud/client/di/ComponentsModule.java Removes injector binding for the deleted NetworkChangeReceiver.
app/src/main/java/com/nextcloud/receiver/NetworkChangeReceiver.kt Deletes the legacy BroadcastReceiver-based implementation.
app/src/test/java/com/nextcloud/client/network/ConnectivityServiceTest.kt Updates unit tests for the new implementation and adds coverage for local-network fallback.
app/src/androidTest/java/com/nextcloud/client/network/ConnectivityServiceImplIT.kt Updates instrumentation test to construct the service with Context.
app/src/androidTest/java/com/owncloud/android/UploadIT.java Updates test connectivity mocks for the new listener API and Connectivity signature.
app/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt Updates test connectivity mocks for the new listener API.
app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java Updates test connectivity mocks for the new listener API.
app/src/androidTest/java/com/owncloud/android/AbstractIT.java Updates test connectivity mocks for the new listener API.
app/src/androidTest/java/com/nextcloud/test/ConnectivityServiceOfflineMock.kt Updates mock to implement the new listener methods.
app/src/debug/java/com/nextcloud/test/TestActivity.kt Updates debug mock to implement the new listener methods.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +53 to +62
private fun notifyListeners() {
scope.launch {
val available = !isInternetWalled()
withContext(Dispatchers.Main) {
listeners.forEach {
Log_OC.d(TAG, "notifying listeners")
it.networkAndServerConnectionListener(available)
}
}
}
Comment on lines +191 to +194
} catch (e: Exception) {
Log_OC.e(TAG, "exception during server check", e)
getWalledValueFromException(e)
} finally {
Comment on lines +39 to +52
* Checks whether the device currently has an active, validated Internet connection
* via a recognized transport type.
*
* <p>This method queries the Android {@link ConnectivityManager} to determine
* whether there is an active {@link Network} with Internet capability and an
* acceptable transport such as Wi-Fi, Cellular, Ethernet, VPN, or Bluetooth.</p>
*
* <p>For Android 12 (API 31) and newer, USB network transport is also considered valid.</p>
*
* <p>Note: This only confirms that the Android system has validated Internet access,
* not necessarily that the Nextcloud server itself is reachable.</p>
*
* @return {@code true} if the device is connected to the Internet through a supported
* transport type; {@code false} otherwise.
Comment on lines +17 to +43
private var connectivityCache = mutableMapOf<ConnectivityKey, Connectivity>()
private val walledStatusCache = mutableMapOf<ConnectivityKey, Pair<Long, Boolean>>()

@Synchronized
fun isExpired(): Boolean = when (val timestamp = cachedEntry?.first) {
null -> true

else -> {
val diff = clock.currentTime - timestamp
diff >= CACHE_TIME_MS
}
fun setValue(key: ConnectivityKey, isWalled: Boolean) {
walledStatusCache[key] = Pair(clock.currentTime, isWalled)
}

@Synchronized
fun setValue(isWalled: Boolean) {
this.cachedEntry = Pair(clock.currentTime, isWalled)
fun clear(key: ConnectivityKey) {
walledStatusCache.remove(key)
}

@Synchronized
fun getValue(): Boolean? = when (isExpired()) {
true -> null
else -> cachedEntry?.second
fun getValue(key: ConnectivityKey): Boolean? {
val entry = walledStatusCache[key] ?: return null
val isExpired = (clock.currentTime - entry.first) >= CACHE_TIME_MS
return if (isExpired) null else entry.second
}

@Synchronized
fun clear() {
cachedEntry = null
fun putConnectivityValue(key: ConnectivityKey, connectivity: Connectivity) {
connectivityCache[key] = connectivity
}

@Synchronized
fun getConnectivity(key: ConnectivityKey): Connectivity? = connectivityCache[key]
whenever(networkInfo.type).thenReturn(ConnectivityManager.TYPE_WIFI)
whenever(accountManager.getServerVersion(any())).thenReturn(OwnCloudVersion.nextcloud_20)
connectivityService.updateConnectivity()
Thread.sleep(200)
@github-actions
Copy link
Copy Markdown

blue-Light-Screenshot test failed, but no output was generated. Maybe a preliminary stage failed.

@github-actions
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

APK file: https://github.com/nextcloud/android/actions/runs/26225901991/artifacts/7135975879
To test this change/fix you can simply download above APK file and install and test it in parallel to your existing Nextcloud app.
qrcode (please click on link to get QR code displayed)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2. developing performance 🚀 Performance improvement opportunities (non-crash related)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upload Failure with "No Internet Connection" Message After Upgrading to Version 3.31.0 on Android App

5 participants