Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync stops after Network switch #4476

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package com.owncloud.android.usecases.transfers.downloads

import androidx.work.BackoffPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.workDataOf
Expand All @@ -29,8 +30,10 @@ import com.owncloud.android.extensions.getTagsForDownload
import com.owncloud.android.usecases.transfers.MAXIMUM_NUMBER_OF_RETRIES
import com.owncloud.android.usecases.transfers.TRANSFER_TAG_DOWNLOAD
import com.owncloud.android.workers.DownloadFileWorker
import com.owncloud.android.workers.DownloadFileWorker.Companion.SECONDS_BACKOFF_DELAY
import timber.log.Timber
import java.util.UUID
import java.util.concurrent.TimeUnit

/**
* We will use [WorkManager] to perform downloads.
Expand Down Expand Up @@ -93,6 +96,7 @@ class DownloadFileUseCase(
)

val downloadFileWork = OneTimeWorkRequestBuilder<DownloadFileWorker>()
.setBackoffCriteria(backoffPolicy = BackoffPolicy.LINEAR, backoffDelay = SECONDS_BACKOFF_DELAY, timeUnit = TimeUnit.MILLISECONDS)
.setInputData(inputData)
.addTag(ocFile.id.toString())
.addTag(accountName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
package com.owncloud.android.usecases.transfers.uploads

import android.net.Uri
import androidx.work.BackoffPolicy
import androidx.work.Constraints
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
Expand All @@ -32,7 +33,9 @@ import com.owncloud.android.domain.BaseUseCase
import com.owncloud.android.domain.camerauploads.model.UploadBehavior
import com.owncloud.android.workers.RemoveSourceFileWorker
import com.owncloud.android.workers.UploadFileFromContentUriWorker
import com.owncloud.android.workers.UploadFileFromContentUriWorker.Companion.SECONDS_BACKOFF_DELAY
import timber.log.Timber
import java.util.concurrent.TimeUnit

class UploadFileFromContentUriUseCase(
private val workManager: WorkManager
Expand All @@ -58,6 +61,7 @@ class UploadFileFromContentUriUseCase(
.build()

val uploadFileFromContentUriWorker = OneTimeWorkRequestBuilder<UploadFileFromContentUriWorker>()
.setBackoffCriteria(backoffPolicy = BackoffPolicy.LINEAR, backoffDelay = SECONDS_BACKOFF_DELAY, timeUnit = TimeUnit.MILLISECONDS)
.setInputData(inputDataUploadFileFromContentUriWorker)
.setConstraints(constraints)
.addTag(params.accountName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* ownCloud Android client application
*
* @author David A. Velasco
* Copyright (C) 2017 ownCloud GmbH.
* @author Aitor Ballesteros Pavón
*
* Copyright (C) 2024 ownCloud GmbH.
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
Expand All @@ -21,6 +23,8 @@

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;

import timber.log.Timber;
Expand Down Expand Up @@ -51,4 +55,24 @@ public static boolean isNetworkActive(Context context) {

return (activeNetwork != null && activeNetwork.isConnectedOrConnecting());
}

public static boolean isInternetAvailable(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

Network network = connectivityManager.getActiveNetwork();
if (network == null) return false;

NetworkCapabilities activeNetwork = connectivityManager.getNetworkCapabilities(network);
if (activeNetwork == null) return false;

if (activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return true;
} else if (activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return true;
} else if (activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
return true;
} else {
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.owncloud.android.data.executeRemoteOperation
import com.owncloud.android.data.providers.LocalStorageProvider
import com.owncloud.android.domain.exceptions.CancelledException
import com.owncloud.android.domain.exceptions.LocalStorageNotMovedException
import com.owncloud.android.domain.exceptions.NetworkErrorException
import com.owncloud.android.domain.exceptions.NoConnectionWithServerException
import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.domain.files.usecases.CleanConflictUseCase
Expand All @@ -58,6 +59,7 @@ import com.owncloud.android.ui.activity.FileDisplayActivity
import com.owncloud.android.ui.errorhandling.ErrorMessageAdapter
import com.owncloud.android.ui.preview.PreviewImageActivity
import com.owncloud.android.ui.preview.PreviewImageFragment.Companion.canBePreviewed
import com.owncloud.android.utils.ConnectivityUtils.isNetworkActive
import com.owncloud.android.utils.DOWNLOAD_NOTIFICATION_CHANNEL_ID
import com.owncloud.android.utils.DOWNLOAD_NOTIFICATION_ID_DEFAULT
import com.owncloud.android.utils.FileStorageUtils
Expand Down Expand Up @@ -125,7 +127,17 @@ class DownloadFileWorker(
notifyDownloadResult(null)
} catch (throwable: Throwable) {
Timber.e(throwable)
notifyDownloadResult(throwable)
val isNetworkError = throwable is NetworkErrorException || throwable is NoConnectionWithServerException
val shouldRetry = isNetworkError && isNetworkActive(appContext)
if (shouldRetry) {
if (runAttemptCount < MAX_RETRIES) {
Result.retry()
} else {
notifyDownloadResult(throwable)
}
} else {
notifyDownloadResult(throwable)
}
}
}

Expand Down Expand Up @@ -358,6 +370,8 @@ class DownloadFileWorker(
}

companion object {
const val SECONDS_BACKOFF_DELAY = 10_000L
const val MAX_RETRIES = 2
const val KEY_PARAM_ACCOUNT = "KEY_PARAM_ACCOUNT"
const val KEY_PARAM_FILE_ID = "KEY_PARAM_FILE_ID"
const val WORKER_KEY_PROGRESS = "KEY_PROGRESS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import com.owncloud.android.data.providers.LocalStorageProvider
import com.owncloud.android.domain.camerauploads.model.UploadBehavior
import com.owncloud.android.domain.capabilities.usecases.GetStoredCapabilitiesUseCase
import com.owncloud.android.domain.exceptions.LocalFileNotFoundException
import com.owncloud.android.domain.exceptions.NetworkErrorException
import com.owncloud.android.domain.exceptions.NoConnectionWithServerException
import com.owncloud.android.domain.exceptions.UnauthorizedException
import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.domain.files.usecases.GetWebDavUrlForSpaceUseCase
Expand All @@ -58,6 +60,7 @@ import com.owncloud.android.lib.resources.files.chunks.ChunkedUploadFromFileSyst
import com.owncloud.android.lib.resources.files.chunks.ChunkedUploadFromFileSystemOperation.Companion.CHUNK_SIZE
import com.owncloud.android.lib.resources.files.services.implementation.OCChunkService
import com.owncloud.android.presentation.authentication.AccountUtils
import com.owncloud.android.utils.ConnectivityUtils.isInternetAvailable
import com.owncloud.android.utils.NotificationUtils
import com.owncloud.android.utils.RemoteFileUtils.Companion.getAvailableRemotePath
import com.owncloud.android.utils.SecurityUtils
Expand Down Expand Up @@ -124,9 +127,22 @@ class UploadFileFromContentUriWorker(
Result.success()
} catch (throwable: Throwable) {
Timber.e(throwable)
showNotification(throwable)
updateUploadsDatabaseWithResult(throwable)
Result.failure()
val isNetworkError = throwable is NetworkErrorException || throwable is NoConnectionWithServerException
val shouldRetry = isNetworkError && isInternetAvailable(appContext)

if (shouldRetry) {
if (runAttemptCount < MAX_RETRIES) {
Result.retry()
} else {
showNotification(throwable)
updateUploadsDatabaseWithResult(throwable)
Result.failure()
}
} else {
showNotification(throwable)
updateUploadsDatabaseWithResult(throwable)
Result.failure()
}
}
}

Expand Down Expand Up @@ -378,6 +394,8 @@ class UploadFileFromContentUriWorker(
}

companion object {
const val SECONDS_BACKOFF_DELAY = 10_000L
const val MAX_RETRIES = 2
const val KEY_PARAM_ACCOUNT_NAME = "KEY_PARAM_ACCOUNT_NAME"
const val KEY_PARAM_BEHAVIOR = "KEY_PARAM_BEHAVIOR"
const val KEY_PARAM_CONTENT_URI = "KEY_PARAM_CONTENT_URI"
Expand Down
Loading