From 18b446c5b9e1dd058ad2a7b2a34573294a7f98c9 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 23 Jun 2026 11:19:32 +0300 Subject: [PATCH 1/5] Rename .java to .kt Signed-off-by: alperozturk96 --- .../network/{ConnectivityService.java => ConnectivityService.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/com/nextcloud/client/network/{ConnectivityService.java => ConnectivityService.kt} (100%) diff --git a/app/src/main/java/com/nextcloud/client/network/ConnectivityService.java b/app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt similarity index 100% rename from app/src/main/java/com/nextcloud/client/network/ConnectivityService.java rename to app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt From a75f77945c46dc9442b9f7aeaf3eb2cdf3f02f5d Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 23 Jun 2026 11:19:33 +0300 Subject: [PATCH 2/5] fix(connectivity-service): usages Signed-off-by: alperozturk96 --- .../test/ConnectivityServiceOfflineMock.kt | 23 ----- .../java/com/owncloud/android/AbstractIT.java | 37 +------ .../owncloud/android/AbstractOnServerIT.java | 35 +------ .../java/com/owncloud/android/UploadIT.java | 99 +------------------ .../android/files/services/FileUploaderIT.kt | 12 --- .../ui/preview/PreviewImageActivityIT.kt | 3 +- .../java/com/nextcloud/test/TestActivity.kt | 13 +-- .../client/jobs/InternalTwoWaySyncWork.kt | 2 +- .../nextcloud/client/jobs/OfflineSyncWork.kt | 2 +- .../client/jobs/upload/FileUploadHelper.kt | 2 +- .../client/jobs/upload/FileUploadWorker.kt | 2 +- .../network/ConnectivityManagerFactory.kt | 43 ++++++++ .../client/network/ConnectivityService.kt | 82 ++++++++------- .../client/network/ConnectivityServiceImpl.kt | 11 ++- .../extensions/SyncedFolderExtensions.kt | 4 +- .../ui/activity/FileDisplayActivity.kt | 28 +++--- .../ui/dialog/CreateFolderDialogFragment.kt | 11 ++- .../ui/dialog/RenameFileDialogFragment.kt | 6 +- .../ui/fragment/OCFileListFragment.java | 2 + 19 files changed, 132 insertions(+), 285 deletions(-) delete mode 100644 app/src/androidTest/java/com/nextcloud/test/ConnectivityServiceOfflineMock.kt create mode 100644 app/src/main/java/com/nextcloud/client/network/ConnectivityManagerFactory.kt diff --git a/app/src/androidTest/java/com/nextcloud/test/ConnectivityServiceOfflineMock.kt b/app/src/androidTest/java/com/nextcloud/test/ConnectivityServiceOfflineMock.kt deleted file mode 100644 index d9efbb954040..000000000000 --- a/app/src/androidTest/java/com/nextcloud/test/ConnectivityServiceOfflineMock.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2025 Philipp Hasper - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -package com.nextcloud.test - -import com.nextcloud.client.network.Connectivity -import com.nextcloud.client.network.ConnectivityService -import com.nextcloud.client.network.NetworkChangeListener - -/** A mocked connectivity service returning that the device is offline **/ -class ConnectivityServiceOfflineMock : ConnectivityService { - override fun addListener(listener: NetworkChangeListener) = Unit - override fun removeListener(listener: NetworkChangeListener) = Unit - override fun isNetworkAndServerAvailable(callback: ConnectivityService.GenericCallback) { - callback.onComplete(false) - } - override fun isConnected(): Boolean = false - override fun isInternetWalled(): Boolean = false - override fun getConnectivity(): Connectivity = Connectivity.CONNECTED_WIFI -} diff --git a/app/src/androidTest/java/com/owncloud/android/AbstractIT.java b/app/src/androidTest/java/com/owncloud/android/AbstractIT.java index aee8cdd0c636..519976ea9283 100644 --- a/app/src/androidTest/java/com/owncloud/android/AbstractIT.java +++ b/app/src/androidTest/java/com/owncloud/android/AbstractIT.java @@ -30,9 +30,8 @@ import com.nextcloud.client.device.BatteryStatus; import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.jobs.upload.FileUploadWorker; -import com.nextcloud.client.network.Connectivity; +import com.nextcloud.client.network.ConnectivityManagerFactory; import com.nextcloud.client.network.ConnectivityService; -import com.nextcloud.client.network.NetworkChangeListener; import com.nextcloud.client.preferences.AppPreferencesImpl; import com.nextcloud.client.preferences.DarkMode; import com.nextcloud.common.NextcloudClient; @@ -101,6 +100,8 @@ public abstract class AbstractIT { @Rule public GrantPermissionRule notificationsPermissionRule = GrantPermissionRule.grant(Manifest.permission.POST_NOTIFICATIONS); + protected ConnectivityService connectivityServiceMock = ConnectivityManagerFactory.INSTANCE.getMock(); + protected static OwnCloudClient client; protected static NextcloudClient nextcloudClient; protected static Account account; @@ -371,38 +372,6 @@ public void uploadFile(File file, String remotePath) { } public void uploadOCUpload(OCUpload ocUpload) { - ConnectivityService connectivityServiceMock = new ConnectivityService() { - @Override - public void addListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void removeListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void isNetworkAndServerAvailable(@NonNull GenericCallback callback) { - - } - - @Override - public boolean isConnected() { - return false; - } - - @Override - public boolean isInternetWalled() { - return false; - } - - @Override - public Connectivity getConnectivity() { - return Connectivity.CONNECTED_WIFI; - } - }; - PowerManagementService powerManagementServiceMock = new PowerManagementService() { @Override public boolean isIgnoringOptimization() { diff --git a/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java b/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java index b68fea87cf9c..9c1881d90c79 100644 --- a/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java +++ b/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java @@ -39,6 +39,8 @@ import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.GetMethod; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.After; import org.junit.Assert; import org.junit.BeforeClass; @@ -50,6 +52,7 @@ import androidx.annotation.NonNull; import androidx.test.platform.app.InstrumentationRegistry; +import kotlin.coroutines.Continuation; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -203,38 +206,6 @@ public void uploadOCUpload(OCUpload ocUpload) { } public void uploadOCUpload(OCUpload ocUpload, int localBehaviour) { - ConnectivityService connectivityServiceMock = new ConnectivityService() { - @Override - public void addListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void removeListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void isNetworkAndServerAvailable(@NonNull GenericCallback callback) { - callback.onComplete(true); - } - - @Override - public boolean isConnected() { - return true; - } - - @Override - public boolean isInternetWalled() { - return false; - } - - @Override - public Connectivity getConnectivity() { - return Connectivity.CONNECTED_WIFI; - } - }; - PowerManagementService powerManagementServiceMock = new PowerManagementService() { @Override public boolean isIgnoringOptimization() { diff --git a/app/src/androidTest/java/com/owncloud/android/UploadIT.java b/app/src/androidTest/java/com/owncloud/android/UploadIT.java index 34aaaeae5bd9..7b5b416bc10f 100644 --- a/app/src/androidTest/java/com/owncloud/android/UploadIT.java +++ b/app/src/androidTest/java/com/owncloud/android/UploadIT.java @@ -12,9 +12,8 @@ import com.nextcloud.client.device.BatteryStatus; import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.jobs.upload.FileUploadWorker; -import com.nextcloud.client.network.Connectivity; +import com.nextcloud.client.network.ConnectivityManagerFactory; import com.nextcloud.client.network.ConnectivityService; -import com.nextcloud.client.network.NetworkChangeListener; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.UploadsStorageManager; import com.owncloud.android.db.OCUpload; @@ -56,38 +55,6 @@ public class UploadIT extends AbstractOnServerIT { new UploadsStorageManager(UserAccountManagerImpl.fromContext(targetContext), targetContext.getContentResolver()); - private ConnectivityService connectivityServiceMock = new ConnectivityService() { - @Override - public void addListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void removeListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void isNetworkAndServerAvailable(@NonNull GenericCallback callback) { - - } - - @Override - public boolean isConnected() { - return false; - } - - @Override - public boolean isInternetWalled() { - return false; - } - - @Override - public Connectivity getConnectivity() { - return Connectivity.CONNECTED_WIFI; - } - }; - private PowerManagementService powerManagementServiceMock = new PowerManagementService() { @Override public boolean isIgnoringOptimization() { @@ -288,37 +255,7 @@ public BatteryStatus getBattery() { @Test public void testUploadOnWifiOnlyButNoWifi() { - ConnectivityService connectivityServiceMock = new ConnectivityService() { - @Override - public void addListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void removeListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void isNetworkAndServerAvailable(@NonNull GenericCallback callback) { - - } - - @Override - public boolean isConnected() { - return false; - } - - @Override - public boolean isInternetWalled() { - return false; - } - - @Override - public Connectivity getConnectivity() { - return new Connectivity(true, false, false, true, false); - } - }; + ConnectivityService connectivityServiceMock = ConnectivityManagerFactory.INSTANCE.getWifi(); OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt", FOLDER + "noWifi.txt", account.name); ocUpload.setUseWifiOnly(true); @@ -387,37 +324,7 @@ public void testUploadOnWifiOnlyAndWifi() { @Test public void testUploadOnWifiOnlyButMeteredWifi() { - ConnectivityService connectivityServiceMock = new ConnectivityService() { - @Override - public void addListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void removeListener(@NonNull NetworkChangeListener listener) { - - } - - @Override - public void isNetworkAndServerAvailable(@NonNull GenericCallback callback) { - - } - - @Override - public boolean isConnected() { - return false; - } - - @Override - public boolean isInternetWalled() { - return false; - } - - @Override - public Connectivity getConnectivity() { - return new Connectivity(true, true, true, true, false); - } - }; + ConnectivityService connectivityServiceMock = ConnectivityManagerFactory.INSTANCE.getMetered(); OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt", FOLDER + "noWifi.txt", account.name); diff --git a/app/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt b/app/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt index 7f9f9c257622..c4cc67bd56ea 100644 --- a/app/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt +++ b/app/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt @@ -14,9 +14,6 @@ import com.nextcloud.client.device.BatteryStatus import com.nextcloud.client.device.PowerManagementService import com.nextcloud.client.jobs.upload.FileUploadHelper import com.nextcloud.client.jobs.upload.FileUploadWorker -import com.nextcloud.client.network.Connectivity -import com.nextcloud.client.network.ConnectivityService -import com.nextcloud.client.network.NetworkChangeListener import com.owncloud.android.AbstractOnServerIT import com.owncloud.android.datamodel.OCFile import com.owncloud.android.datamodel.UploadsStorageManager @@ -34,15 +31,6 @@ import org.junit.Test abstract class FileUploaderIT : AbstractOnServerIT() { private var uploadsStorageManager: UploadsStorageManager? = null - private val connectivityServiceMock: ConnectivityService = object : ConnectivityService { - override fun addListener(listener: NetworkChangeListener) = Unit - override fun removeListener(listener: NetworkChangeListener) = Unit - override fun isNetworkAndServerAvailable(callback: ConnectivityService.GenericCallback) = Unit - override fun isConnected(): Boolean = false - override fun isInternetWalled(): Boolean = false - override fun getConnectivity(): Connectivity = Connectivity.CONNECTED_WIFI - } - private val powerManagementServiceMock: PowerManagementService = object : PowerManagementService { override val isIgnoringOptimization: Boolean get() = true diff --git a/app/src/androidTest/java/com/owncloud/android/ui/preview/PreviewImageActivityIT.kt b/app/src/androidTest/java/com/owncloud/android/ui/preview/PreviewImageActivityIT.kt index 3ce7a9333b6d..53eb92b1a812 100644 --- a/app/src/androidTest/java/com/owncloud/android/ui/preview/PreviewImageActivityIT.kt +++ b/app/src/androidTest/java/com/owncloud/android/ui/preview/PreviewImageActivityIT.kt @@ -21,7 +21,6 @@ import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText -import com.nextcloud.test.ConnectivityServiceOfflineMock import com.nextcloud.test.FileRemovedIdlingResource import com.nextcloud.test.LoopFailureHandler import com.owncloud.android.AbstractOnServerIT @@ -164,7 +163,7 @@ class PreviewImageActivityIT : AbstractOnServerIT() { launchActivity(intent).use { scenario -> if (offline) { scenario.onActivity { activity -> - activity.connectivityService = ConnectivityServiceOfflineMock() + activity.connectivityService = connectivityServiceMock } } onView(isRoot()).check(matches(isDisplayed())) diff --git a/app/src/debug/java/com/nextcloud/test/TestActivity.kt b/app/src/debug/java/com/nextcloud/test/TestActivity.kt index 5f5bc6fd0c18..bc51c8bd8532 100644 --- a/app/src/debug/java/com/nextcloud/test/TestActivity.kt +++ b/app/src/debug/java/com/nextcloud/test/TestActivity.kt @@ -14,9 +14,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.nextcloud.client.database.NextcloudDatabase import com.nextcloud.client.jobs.download.FileDownloadWorker import com.nextcloud.client.jobs.upload.FileUploadHelper -import com.nextcloud.client.network.Connectivity -import com.nextcloud.client.network.ConnectivityService -import com.nextcloud.client.network.NetworkChangeListener +import com.nextcloud.client.network.ConnectivityManagerFactory import com.nextcloud.utils.EditorUtils import com.owncloud.android.R import com.owncloud.android.databinding.TestLayoutBinding @@ -43,14 +41,7 @@ class TestActivity : private lateinit var fileOperation: FileOperationsHelper private lateinit var binding: TestLayoutBinding - val connectivityServiceMock: ConnectivityService = object : ConnectivityService { - override fun addListener(listener: NetworkChangeListener) = Unit - override fun removeListener(listener: NetworkChangeListener) = Unit - override fun isNetworkAndServerAvailable(callback: ConnectivityService.GenericCallback) = Unit - override fun isConnected(): Boolean = false - override fun isInternetWalled(): Boolean = false - override fun getConnectivity(): Connectivity = Connectivity.CONNECTED_WIFI - } + val connectivityServiceMock = ConnectivityManagerFactory.mock override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/nextcloud/client/jobs/InternalTwoWaySyncWork.kt b/app/src/main/java/com/nextcloud/client/jobs/InternalTwoWaySyncWork.kt index fe0183ddeb78..33876e08ecb5 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/InternalTwoWaySyncWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/InternalTwoWaySyncWork.kt @@ -43,7 +43,7 @@ class InternalTwoWaySyncWork( if (!appPreferences.isTwoWaySyncEnabled || powerManagementService.isPowerSavingEnabled || !connectivityService.isConnected || - connectivityService.isInternetWalled || + connectivityService.isInternetWalled() || !connectivityService.connectivity.isWifi ) { Log_OC.d(TAG, "Not starting due to constraints!") diff --git a/app/src/main/java/com/nextcloud/client/jobs/OfflineSyncWork.kt b/app/src/main/java/com/nextcloud/client/jobs/OfflineSyncWork.kt index b0b863270f3c..500489183895 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/OfflineSyncWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/OfflineSyncWork.kt @@ -139,7 +139,7 @@ class OfflineSyncWork( result?.data?.get(0) as? String } - else -> if (connectivityService.isInternetWalled) { + else -> if (connectivityService.isInternetWalled()) { Log_OC.d(TAG, "No connectivity, skipping sync") null } else { diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt index b4dea7a2b062..816c81898b24 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt @@ -407,7 +407,7 @@ class FileUploadHelper { private fun checkConnectivity(connectivityService: ConnectivityService): Boolean { // check that connection isn't walled off and that the server is reachable - return connectivityService.getConnectivity().isConnected && !connectivityService.isInternetWalled() + return connectivityService.connectivity.isConnected && !connectivityService.isInternetWalled() } /** diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt index 65bb0308e537..02fd23b8c166 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt @@ -370,7 +370,7 @@ class FileUploadWorker( private fun canExitEarly(): Boolean { val result = !connectivityService.isConnected || - connectivityService.isInternetWalled || + connectivityService.isInternetWalled() || isStopped if (result) { diff --git a/app/src/main/java/com/nextcloud/client/network/ConnectivityManagerFactory.kt b/app/src/main/java/com/nextcloud/client/network/ConnectivityManagerFactory.kt new file mode 100644 index 000000000000..d09ebf5b524f --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/network/ConnectivityManagerFactory.kt @@ -0,0 +1,43 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.client.network + +object ConnectivityManagerFactory { + val mock: ConnectivityService = object : ConnectivityService { + override fun isNetworkAndServerAvailable(onCompleted: (Boolean) -> Unit) { + onCompleted(true) + } + override fun addListener(listener: NetworkChangeListener) = Unit + override fun removeListener(listener: NetworkChangeListener) = Unit + override val isConnected = true + override fun isInternetWalled(): Boolean = false + override val connectivity = Connectivity.CONNECTED_WIFI + } + + val metered: ConnectivityService = object : ConnectivityService { + override fun isNetworkAndServerAvailable(onCompleted: (Boolean) -> Unit) { + onCompleted(true) + } + override fun addListener(listener: NetworkChangeListener) = Unit + override fun removeListener(listener: NetworkChangeListener) = Unit + override val isConnected = false + override fun isInternetWalled(): Boolean = false + override val connectivity = Connectivity(true, true, true, true, false) + } + + val wifi: ConnectivityService = object : ConnectivityService { + override fun isNetworkAndServerAvailable(onCompleted: (Boolean) -> Unit) { + onCompleted(true) + } + override fun addListener(listener: NetworkChangeListener) = Unit + override fun removeListener(listener: NetworkChangeListener) = Unit + override val isConnected = false + override fun isInternetWalled(): Boolean = false + override val connectivity = Connectivity(true, false, false, true, false) + } +} diff --git a/app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt b/app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt index fe9ce5638eb1..7249f7ae2a8d 100644 --- a/app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt +++ b/app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt @@ -4,91 +4,87 @@ * SPDX-FileCopyrightText: 2020 Chris Narkiewicz * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only */ -package com.nextcloud.client.network; - - -import androidx.annotation.NonNull; +package com.nextcloud.client.network /** * This service provides information about current network connectivity * and server reachability. */ -public interface ConnectivityService { - void addListener(@NonNull NetworkChangeListener listener); - void removeListener(@NonNull NetworkChangeListener listener); +interface ConnectivityService { + fun addListener(listener: NetworkChangeListener) + fun removeListener(listener: NetworkChangeListener) /** * Asynchronously checks whether both the device's network connection * and the Nextcloud server are available. * - *

This method executes its logic on a background thread and posts the result - * back to the main thread through the provided {@link GenericCallback}.

* - *

The check is based on {@link #isInternetWalled()} — if the Internet is not + * This method executes its logic on a background thread and posts the result + * back to the main thread. + * + * The check is based on [.isInternetWalled] — if the Internet is not * walled (i.e., the server is reachable and not restricted by a captive portal), - * this method reports {@code true}. Otherwise, it reports {@code false}.

+ * this method reports `true`. Otherwise, it reports `false`. * - * @param callback a callback that receives {@code true} when the network and - * Nextcloud server are reachable, or {@code false} otherwise. + * returns `true` when the network and + * Nextcloud server are reachable, or `false` otherwise. */ - void isNetworkAndServerAvailable(@NonNull GenericCallback callback); + fun isNetworkAndServerAvailable(onCompleted: (Boolean) -> Unit) /** * Checks whether the device currently has an active connection using a recognized * transport type. * - *

This method reflects the current connectivity state as exposed by this service + * + * This method reflects the current connectivity state as exposed by this service * and indicates whether a supported transport such as Wi-Fi, Cellular, Ethernet, - * VPN, or Bluetooth is active.

+ * VPN, or Bluetooth is active. + * + * + * For Android 12 (API 31) and newer, USB network transport is also considered supported. * - *

For Android 12 (API 31) and newer, USB network transport is also considered supported.

* - *

Note: This does not guarantee that the active network has + * Note: This does **not** guarantee that the active network has * Android Internet capability, has been system-validated for Internet access, or - * that the Nextcloud server itself is reachable.

+ * that the Nextcloud server itself is reachable. * - * @return {@code true} if the device is connected through a supported transport - * type; {@code false} otherwise. + * @return `true` if the device is connected through a supported transport + * type; `false` otherwise. */ - boolean isConnected(); + val isConnected: Boolean /** * Determines whether the device's current Internet connection is "walled" — that is, * restricted by a captive portal or other form of network access control that prevents * full connectivity to the Nextcloud server. * - *

This method does not test general Internet reachability (e.g. Google or DNS), + * + * This method does **not** test general Internet reachability (e.g. Google or DNS), * but rather focuses on the ability to access the configured Nextcloud server directly. * In other words, it checks whether the server can be reached without network interference - * such as a hotel's captive portal, Wi-Fi login page, or similar restrictions.

+ * such as a hotel's captive portal, Wi-Fi login page, or similar restrictions. + * * - *

Results are cached for subsequent checks to minimize unnecessary HTTP requests.

+ * Results are cached for subsequent checks to minimize unnecessary HTTP requests. * - * @return {@code true} if the Internet appears to be walled (e.g. captive portal or - * restricted access); {@code false} if the Nextcloud server is reachable and - * the network allows normal Internet access. + * @return `true` if the Internet appears to be walled (e.g. captive portal or + * restricted access); `false` if the Nextcloud server is reachable and + * the network allows normal Internet access. */ - boolean isInternetWalled(); + fun isInternetWalled(): Boolean /** - * Returns a {@link Connectivity} object that represents the current network state. + * Returns a [Connectivity] object that represents the current network state. + * * - *

This includes whether the device is connected, whether the network is metered, + * This includes whether the device is connected, whether the network is metered, * and whether it uses Wi-Fi or Ethernet transport. It uses - * {@link #isConnected()} to verify active Internet capability

+ * [.isConnected] to verify active Internet capability * - *

If no active network is found, {@link Connectivity#DISCONNECTED} is returned.

* - * @return a {@link Connectivity} instance describing the current network connection. - */ - Connectivity getConnectivity(); - - /** - * Callback interface for asynchronous results. + * If no active network is found, [Connectivity.DISCONNECTED] is returned. * - * @param The type of result returned by the callback. + * @return a [Connectivity] instance describing the current network connection. */ - interface GenericCallback { - void onComplete(T result); - } + val connectivity: Connectivity } diff --git a/app/src/main/java/com/nextcloud/client/network/ConnectivityServiceImpl.kt b/app/src/main/java/com/nextcloud/client/network/ConnectivityServiceImpl.kt index f0b7c84f225a..8dd24f24d145 100644 --- a/app/src/main/java/com/nextcloud/client/network/ConnectivityServiceImpl.kt +++ b/app/src/main/java/com/nextcloud/client/network/ConnectivityServiceImpl.kt @@ -12,7 +12,6 @@ import android.net.Network import android.net.NetworkCapabilities import android.os.Build import com.nextcloud.client.account.UserAccountManager -import com.nextcloud.client.network.ConnectivityService.GenericCallback import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.utils.Log_OC import kotlinx.coroutines.CoroutineScope @@ -74,18 +73,19 @@ class ConnectivityServiceImpl( } // region overridden methods - override fun isNetworkAndServerAvailable(callback: GenericCallback) { + override fun isNetworkAndServerAvailable(onCompleted: (Boolean) -> Unit) { availabilityCheckJob?.cancel() availabilityCheckJob = scope.launch { val available = !isInternetWalled() Log_OC.d(TAG, "isNetworkAndServerAvailable: $available") withContext(Dispatchers.Main) { - callback.onComplete(available) + onCompleted(available) } } } - override fun isConnected() = currentConnectivity.isConnected + override val isConnected: Boolean + get() = currentConnectivity.isConnected override fun isInternetWalled(): Boolean { val currentKey = key @@ -133,7 +133,8 @@ class ConnectivityServiceImpl( return isWalled } - override fun getConnectivity() = currentConnectivity + override val connectivity: Connectivity + get() = currentConnectivity override fun addListener(listener: NetworkChangeListener) { listeners.add(listener) diff --git a/app/src/main/java/com/nextcloud/utils/extensions/SyncedFolderExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/SyncedFolderExtensions.kt index 991b9b0ee904..aaa112d41a8d 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/SyncedFolderExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/SyncedFolderExtensions.kt @@ -85,11 +85,11 @@ fun SyncedFolder.calculateScanInterval( ): Pair { val defaultIntervalMillis = BackgroundJobManagerImpl.DEFAULT_PERIODIC_JOB_INTERVAL_MINUTES * 60_000L - if (!connectivityService.isConnected() || connectivityService.isInternetWalled()) { + if (!connectivityService.isConnected || connectivityService.isInternetWalled()) { return defaultIntervalMillis * 2 to null } - if (isWifiOnly && !connectivityService.getConnectivity().isWifi) { + if (isWifiOnly && !connectivityService.connectivity.isWifi) { return defaultIntervalMillis * 4 to R.string.auto_upload_wifi_only_warning_info } diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index f6e3670b06e6..9b8d87adc1fd 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -2239,25 +2239,23 @@ class FileDisplayActivity : } } - withContext(Dispatchers.Main) { - connectivityService.isNetworkAndServerAvailable { isAvailable -> - if (isAvailable) { - fileOperationsHelper?.removeFiles( - filesToRemove, - onlyLocalCopy, - true - ) + connectivityService.isNetworkAndServerAvailable { isAvailable -> + if (isAvailable) { + fileOperationsHelper?.removeFiles( + filesToRemove, + onlyLocalCopy, + true + ) + } else { + if (onlyLocalCopy) { + fileOperationsHelper?.removeFiles(filesToRemove, true, true) } else { - if (onlyLocalCopy) { - fileOperationsHelper?.removeFiles(filesToRemove, true, true) - } else { - filesToRemove.forEach { file -> - fileDataStorageManager.addRemoveFileOfflineOperation(file) - } + filesToRemove.forEach { file -> + fileDataStorageManager.addRemoveFileOfflineOperation(file) } } - onFilesRemoved() } + onFilesRemoved() } } } diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/CreateFolderDialogFragment.kt b/app/src/main/java/com/owncloud/android/ui/dialog/CreateFolderDialogFragment.kt index ef2d0e8e12a0..cc3902d3231e 100644 --- a/app/src/main/java/com/owncloud/android/ui/dialog/CreateFolderDialogFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/dialog/CreateFolderDialogFragment.kt @@ -190,9 +190,12 @@ class CreateFolderDialogFragment : newFolderName = AutoRename.rename(newFolderName, capabilities, isFolderPath = true) val path = parentFolder?.decryptedRemotePath + newFolderName + OCFile.PATH_SEPARATOR - connectivityService.isNetworkAndServerAvailable { result -> - if (result) { - typedActivity()?.fileOperationsHelper?.createFolder(path, encrypted) + + val componentGetter = typedActivity() + val fda = typedActivity() + connectivityService.isNetworkAndServerAvailable { + if (it) { + componentGetter?.fileOperationsHelper?.createFolder(path, encrypted) } else { Log_OC.d(TAG, "Network not available, creating offline operation") fileDataStorageManager.addCreateFolderOfflineOperation( @@ -201,7 +204,7 @@ class CreateFolderDialogFragment : parentFolder?.fileId ) - typedActivity()?.refreshCurrentDirectory() + fda?.refreshCurrentDirectory() } } } diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt b/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt index c420fab77023..37875db7ac28 100644 --- a/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt @@ -172,16 +172,18 @@ class RenameFileDialogFragment : return } + val helper = typedActivity()?.fileOperationsHelper + fda?.connectivityService?.isNetworkAndServerAvailable { result -> if (result) { /* * result of it triggered by * [com.owncloud.android.ui.activity.FileDisplayActivity.onRemoteOperationFinish] */ - typedActivity()?.fileOperationsHelper?.renameFile(targetFile, newFileName) + helper?.renameFile(targetFile, newFileName) } else { fileDataStorageManager.addRenameFileOfflineOperation(targetFile, newFileName) - fda?.refreshCurrentDirectory() + fda.refreshCurrentDirectory() } } } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index b82b2c09ed12..3d618b1eba57 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -147,6 +147,7 @@ import androidx.fragment.app.FragmentManager; import androidx.media3.common.util.UnstableApi; import kotlin.Unit; +import kotlin.jvm.functions.Function1; import static com.owncloud.android.datamodel.OCFile.ROOT_PATH; import static com.owncloud.android.ui.dialog.setupEncryption.SetupEncryptionDialogFragment.SETUP_ENCRYPTION_DIALOG_TAG; @@ -1165,6 +1166,7 @@ private void folderOnItemClick(OCFile file, int position) { } else { DisplayUtils.showSnackMessage(fileActivity, R.string.internet_connection_required_for_encrypted_folder_setup); } + return Unit.INSTANCE; }); } } From 42e57f5295bc6f60e1ed6b98a98bed9cc08d6f55 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 23 Jun 2026 11:24:54 +0300 Subject: [PATCH 3/5] wip Signed-off-by: alperozturk96 --- .../java/com/owncloud/android/AbstractOnServerIT.java | 6 ------ .../com/nextcloud/client/network/ConnectivityService.kt | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java b/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java index 9c1881d90c79..66117afa6c84 100644 --- a/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java +++ b/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java @@ -19,9 +19,6 @@ import com.nextcloud.client.device.BatteryStatus; import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.jobs.upload.FileUploadWorker; -import com.nextcloud.client.network.Connectivity; -import com.nextcloud.client.network.ConnectivityService; -import com.nextcloud.client.network.NetworkChangeListener; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.UploadsStorageManager; import com.owncloud.android.db.OCUpload; @@ -39,8 +36,6 @@ import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.GetMethod; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.junit.After; import org.junit.Assert; import org.junit.BeforeClass; @@ -52,7 +47,6 @@ import androidx.annotation.NonNull; import androidx.test.platform.app.InstrumentationRegistry; -import kotlin.coroutines.Continuation; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; diff --git a/app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt b/app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt index 7249f7ae2a8d..4ed3e5e7f36f 100644 --- a/app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt +++ b/app/src/main/java/com/nextcloud/client/network/ConnectivityService.kt @@ -1,6 +1,7 @@ /* * Nextcloud - Android Client * + * SPDX-FileCopyrightText: 2026 Alper Ozturk * SPDX-FileCopyrightText: 2020 Chris Narkiewicz * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only */ From 7b52b6d080b4ee9077fe12365bf5e07fb3de86d9 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 24 Jun 2026 08:11:17 +0300 Subject: [PATCH 4/5] fix tests Signed-off-by: alperozturk96 --- .../client/network/ConnectivityServiceTest.kt | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/test/java/com/nextcloud/client/network/ConnectivityServiceTest.kt b/app/src/test/java/com/nextcloud/client/network/ConnectivityServiceTest.kt index f9311567be55..9bd2502a2a35 100644 --- a/app/src/test/java/com/nextcloud/client/network/ConnectivityServiceTest.kt +++ b/app/src/test/java/com/nextcloud/client/network/ConnectivityServiceTest.kt @@ -242,13 +242,13 @@ class ConnectivityServiceTest { @Test fun `true maintenance status flag is used`() { mockResponse(maintenance = true, httpStatus = HttpStatus.SC_OK) - assertTrue(connectivityService.isInternetWalled) + assertTrue(connectivityService.isInternetWalled()) } @Test fun `maintenance flag is ignored when non-200 HTTP code is returned`() { mockResponse(maintenance = false, httpStatus = HttpStatus.SC_NO_CONTENT) - assertTrue(connectivityService.isInternetWalled) + assertTrue(connectivityService.isInternetWalled()) } // `status endpoint is used to determine internet state` removed: the new impl @@ -280,7 +280,7 @@ class ConnectivityServiceTest { // WHEN // connectivity is checked - val result = connectivityService.isInternetWalled + val result = connectivityService.isInternetWalled() // THEN // connection is walled @@ -311,7 +311,7 @@ class ConnectivityServiceTest { // WHEN // connectivity is checked - val result = connectivityService.isInternetWalled + val result = connectivityService.isInternetWalled() // THEN // assume internet is not walled @@ -342,7 +342,7 @@ class ConnectivityServiceTest { mockResponse(contentLength = 0, status = HttpStatus.SC_NO_CONTENT) // WHEN - val result = connectivityService.isInternetWalled + val result = connectivityService.isInternetWalled() // THEN server reachability check is always performed, even on metered cellular assertEquals(false, result) @@ -357,28 +357,28 @@ class ConnectivityServiceTest { @Test fun `status 204 means internet is not walled`() { mockResponse(contentLength = 0, status = HttpStatus.SC_NO_CONTENT) - assertFalse(connectivityService.isInternetWalled) + assertFalse(connectivityService.isInternetWalled()) verify(getRequest, times(1)).execute(client) } @Test fun `status 204 and no content length means internet is not walled`() { mockResponse(contentLength = -1, status = HttpStatus.SC_NO_CONTENT) - assertFalse(connectivityService.isInternetWalled) + assertFalse(connectivityService.isInternetWalled()) verify(getRequest, times(1)).execute(client) } @Test fun `other status than 204 means internet is walled`() { mockResponse(contentLength = 0, status = HttpStatus.SC_GONE) - assertTrue(connectivityService.isInternetWalled) + assertTrue(connectivityService.isInternetWalled()) verify(getRequest, times(1)).execute(client) } @Test fun `index endpoint is used to determine internet state`() { mockResponse() - connectivityService.isInternetWalled + connectivityService.isInternetWalled() val urlCaptor = argumentCaptor() verify(requestBuilder).invoke(urlCaptor.capture()) assertTrue( @@ -420,7 +420,7 @@ class ConnectivityServiceTest { whenever(getRequest.execute(client)).thenReturn(HttpStatus.SC_NO_CONTENT) whenever(getRequest.getResponseContentLength()).thenReturn(0L) - assertFalse("server should be reachable over local wifi", connectivityService.isInternetWalled) + assertFalse("server should be reachable over local wifi", connectivityService.isInternetWalled()) verify(getRequest, times(1)).execute(client) } @@ -430,7 +430,7 @@ class ConnectivityServiceTest { connectivityService.updateConnectivity() assertFalse(connectivityService.isConnected) - assertTrue(connectivityService.isInternetWalled) + assertTrue(connectivityService.isInternetWalled()) verify(requestBuilder, never()).invoke(any()) } } From 2a526170c3f2843a2b1e8080394e405d8060d014 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 24 Jun 2026 13:01:29 +0300 Subject: [PATCH 5/5] wip Signed-off-by: alperozturk96 --- .../com/nextcloud/client/network/ConnectivityServiceImplIT.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/com/nextcloud/client/network/ConnectivityServiceImplIT.kt b/app/src/androidTest/java/com/nextcloud/client/network/ConnectivityServiceImplIT.kt index c6036b023edd..58f082170650 100644 --- a/app/src/androidTest/java/com/nextcloud/client/network/ConnectivityServiceImplIT.kt +++ b/app/src/androidTest/java/com/nextcloud/client/network/ConnectivityServiceImplIT.kt @@ -36,6 +36,6 @@ class ConnectivityServiceImplIT : AbstractOnServerIT() { ) assertTrue(sut.connectivity.isConnected) - assertFalse(sut.isInternetWalled) + assertFalse(sut.isInternetWalled()) } }