Skip to content
Draft
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
@@ -0,0 +1,86 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.nextcloud.client.jobs.download

import android.content.Context
import android.content.Intent
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.operations.DownloadFileOperation
import com.owncloud.android.ui.dialog.SendShareDialog
import com.owncloud.android.ui.fragment.OCFileListFragment

class FileDownloadBroadcastManager(
private val context: Context,
private val broadcastManager: LocalBroadcastManager
) {
companion object {
private const val TAG = "📣" + "FileDownloadBroadcastManager"

const val DOWNLOAD_ADDED = "DOWNLOAD_ADDED"
const val DOWNLOAD_FINISHED = "DOWNLOAD_FINISHED"
}

fun sendAdded(accountName: String, remotePath: String, packageName: String, linkedToRemotePath: String?) {
Log_OC.d(TAG, "download added broadcast sent")

val intent = Intent(DOWNLOAD_ADDED).apply {
putExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME, accountName)
putExtra(FileDownloadWorker.EXTRA_REMOTE_PATH, remotePath)

linkedToRemotePath?.let {
putExtra(FileDownloadWorker.EXTRA_LINKED_TO_PATH, linkedToRemotePath)
}
setPackage(packageName)
}

broadcastManager.sendBroadcast(intent)
}

fun sendFinished(
download: DownloadFileOperation,
downloadResult: RemoteOperationResult<*>,
unlinkedFromRemotePath: String?
) {
Log_OC.d(TAG, "download finish broadcast sent")

val intent = Intent(DOWNLOAD_FINISHED).apply {
putExtra(FileDownloadWorker.EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess)
putExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME, download.user.accountName)
putExtra(FileDownloadWorker.EXTRA_REMOTE_PATH, download.remotePath)
putExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR, download.behaviour)
putExtra(SendShareDialog.ACTIVITY_NAME, download.activityName)
putExtra(SendShareDialog.PACKAGE_NAME, download.packageName)
if (unlinkedFromRemotePath != null) {
putExtra(FileDownloadWorker.EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath)
}
setPackage(context.packageName)
}

broadcastManager.sendBroadcast(intent)
}

fun sendFinished(
accountName: String,
remotePath: String?,
packageName: String,
success: Boolean
) {
Log_OC.d(TAG, "download finish broadcast sent")

val intent = Intent(DOWNLOAD_FINISHED).apply {
putExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME, accountName)
putExtra(FileDownloadWorker.EXTRA_REMOTE_PATH, remotePath)
putExtra(FileDownloadWorker.EXTRA_DOWNLOAD_RESULT, success)
setPackage(packageName)
}

broadcastManager.sendBroadcast(intent)
}
}
Original file line number Diff line number Diff line change
@@ -1,52 +1,24 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.client.jobs.download

import android.content.Context
import android.content.Intent
import com.nextcloud.client.account.User
import com.owncloud.android.authentication.AuthenticatorActivity
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.operations.DownloadFileOperation
import com.owncloud.android.ui.activity.FileActivity
import com.owncloud.android.ui.activity.FileDisplayActivity
import com.owncloud.android.ui.dialog.SendShareDialog
import com.owncloud.android.ui.fragment.OCFileListFragment
import com.owncloud.android.ui.preview.PreviewImageActivity
import com.owncloud.android.ui.preview.PreviewImageFragment

class FileDownloadIntents(private val context: Context) {

fun newDownloadIntent(download: DownloadFileOperation, linkedToRemotePath: String): Intent =
Intent(FileDownloadWorker.getDownloadAddedMessage()).apply {
putExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME, download.user.accountName)
putExtra(FileDownloadWorker.EXTRA_REMOTE_PATH, download.remotePath)
putExtra(FileDownloadWorker.EXTRA_LINKED_TO_PATH, linkedToRemotePath)
setPackage(context.packageName)
}

fun downloadFinishedIntent(
download: DownloadFileOperation,
downloadResult: RemoteOperationResult<*>,
unlinkedFromRemotePath: String?
): Intent = Intent(FileDownloadWorker.getDownloadFinishMessage()).apply {
putExtra(FileDownloadWorker.EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess)
putExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME, download.user.accountName)
putExtra(FileDownloadWorker.EXTRA_REMOTE_PATH, download.remotePath)
putExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR, download.behaviour)
putExtra(SendShareDialog.ACTIVITY_NAME, download.activityName)
putExtra(SendShareDialog.PACKAGE_NAME, download.packageName)
if (unlinkedFromRemotePath != null) {
putExtra(FileDownloadWorker.EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath)
}
setPackage(context.packageName)
}

fun credentialContentIntent(user: User): Intent = Intent(context, AuthenticatorActivity::class.java).apply {
putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, user.toPlatformAccount())
putExtra(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import kotlin.random.Random
class FileDownloadWorker(
viewThemeUtils: ViewThemeUtils,
private val accountManager: UserAccountManager,
private var localBroadcastManager: LocalBroadcastManager,
localBroadcastManager: LocalBroadcastManager,
private val context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params),
Expand Down Expand Up @@ -83,18 +83,16 @@ class FileDownloadWorker(
const val EXTRA_REMOTE_PATH = "EXTRA_REMOTE_PATH"
const val EXTRA_LINKED_TO_PATH = "EXTRA_LINKED_TO_PATH"
const val EXTRA_ACCOUNT_NAME = "EXTRA_ACCOUNT_NAME"

fun getDownloadAddedMessage(): String = FileDownloadWorker::class.java.name + "DOWNLOAD_ADDED"

fun getDownloadFinishMessage(): String = FileDownloadWorker::class.java.name + "DOWNLOAD_FINISH"
}

private var currentDownload: DownloadFileOperation? = null

private var conflictUploadId: Long? = null
private var lastPercent = 0

private val fileDownloadBroadcastManager = FileDownloadBroadcastManager(context, localBroadcastManager)
private val intents = FileDownloadIntents(context)

private var notificationManager = DownloadNotificationManager(
Random.nextInt(),
context,
Expand Down Expand Up @@ -216,9 +214,12 @@ class FileDownloadWorker(
requestedDownloads.add(downloadKey)
}

linkedToRemotePath?.let {
localBroadcastManager.sendBroadcast(intents.newDownloadIntent(operation, linkedToRemotePath))
}
fileDownloadBroadcastManager.sendAdded(
operation.user.accountName,
operation.remotePath,
context.packageName,
linkedToRemotePath
)
}

requestedDownloads
Expand Down Expand Up @@ -266,7 +267,6 @@ class FileDownloadWorker(
return
}

setWorkerState(user)
Log_OC.d(TAG, "downloading: $downloadKey")

val isAccountExist = accountManager.exists(currentDownload?.user?.toPlatformAccount())
Expand Down Expand Up @@ -342,13 +342,11 @@ class FileDownloadWorker(
currentDownload?.run {
notifyDownloadResult(this, downloadResult)

val downloadFinishedIntent = intents.downloadFinishedIntent(
fileDownloadBroadcastManager.sendFinished(
this,
downloadResult,
removeResult.second
)

localBroadcastManager.sendBroadcast(downloadFinishedIntent)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@

import android.accounts.Account;
import android.accounts.AccountsException;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Pair;

import com.nextcloud.client.account.User;
import com.nextcloud.client.jobs.download.FileDownloadWorker;
import com.nextcloud.client.jobs.download.FileDownloadBroadcastManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.IndexedForest;
import com.owncloud.android.lib.common.OwnCloudAccount;
Expand Down Expand Up @@ -49,6 +48,7 @@ class SyncFolderHandler extends Handler {

private Account mCurrentAccount;
private SynchronizeFolderOperation mCurrentSyncOperation;
private FileDownloadBroadcastManager fileDownloadBroadcastManager;


public SyncFolderHandler(Looper looper, OperationsService service) {
Expand All @@ -57,6 +57,10 @@ public SyncFolderHandler(Looper looper, OperationsService service) {
throw new IllegalArgumentException("Received invalid NULL in parameter 'service'");
}
mService = service;

final var context = mService.getApplicationContext();
final var broadcastManager = LocalBroadcastManager.getInstance(context);
fileDownloadBroadcastManager = new FileDownloadBroadcastManager(context, broadcastManager);
}

/**
Expand Down Expand Up @@ -104,13 +108,11 @@ private void doOperation(Account account, String remotePath) {
getClientFor(ocAccount, mService);

result = mCurrentSyncOperation.execute(mOwnCloudClient);
sendBroadcastFinishedSyncFolder(account, remotePath, result.isSuccess());
fileDownloadBroadcastManager.sendFinished(account.name, remotePath, mService.getPackageName(), result.isSuccess());
mService.dispatchResultToOperationListeners(mCurrentSyncOperation, result);

} catch (AccountsException | IOException e) {
sendBroadcastFinishedSyncFolder(account, remotePath, false);
mService.dispatchResultToOperationListeners(mCurrentSyncOperation, new RemoteOperationResult(e));

fileDownloadBroadcastManager.sendFinished(account.name, remotePath, mService.getPackageName(), false);
mService.dispatchResultToOperationListeners(mCurrentSyncOperation, new RemoteOperationResult<>(e));
Log_OC.e(TAG, "Error while trying to get authorization", e);
} finally {
mPendingOperations.removePayload(account.name, remotePath);
Expand All @@ -122,7 +124,7 @@ public void add(Account account, String remotePath,
SynchronizeFolderOperation syncFolderOperation){
Pair<String, String> putResult = mPendingOperations.putIfAbsent(account.name, remotePath, syncFolderOperation);
if (putResult != null) {
sendBroadcastNewSyncFolder(account, remotePath); // TODO upgrade!
fileDownloadBroadcastManager.sendAdded(account.name, remotePath, mService.getPackageName(), null);
}
}

Expand Down Expand Up @@ -151,33 +153,5 @@ public void cancel(Account account, OCFile file){
mCurrentSyncOperation.cancel();
}
}

//sendBroadcastFinishedSyncFolder(account, file.getRemotePath());
}

/**
* TODO review this method when "folder synchronization" replaces "folder download";
* this is a fast and ugly patch.
*/
private void sendBroadcastNewSyncFolder(Account account, String remotePath) {
Intent added = new Intent(FileDownloadWorker.Companion.getDownloadAddedMessage());
added.putExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME, account.name);
added.putExtra(FileDownloadWorker.EXTRA_REMOTE_PATH, remotePath);
added.setPackage(mService.getPackageName());
LocalBroadcastManager.getInstance(mService.getApplicationContext()).sendBroadcast(added);
}

/**
* TODO review this method when "folder synchronization" replaces "folder download";
* this is a fast and ugly patch.
*/
private void sendBroadcastFinishedSyncFolder(Account account, String remotePath,
boolean success) {
Intent finished = new Intent(FileDownloadWorker.Companion.getDownloadFinishMessage());
finished.putExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME, account.name);
finished.putExtra(FileDownloadWorker.EXTRA_REMOTE_PATH, remotePath);
finished.putExtra(FileDownloadWorker.EXTRA_DOWNLOAD_RESULT, success);
finished.setPackage(mService.getPackageName());
LocalBroadcastManager.getInstance(mService.getApplicationContext()).sendBroadcast(finished);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,9 @@ import com.nextcloud.client.core.Clock
import com.nextcloud.client.di.Injectable
import com.nextcloud.client.editimage.EditImageActivity
import com.nextcloud.client.files.DeepLinkHandler
import com.nextcloud.client.jobs.download.FileDownloadBroadcastManager
import com.nextcloud.client.jobs.download.FileDownloadHelper
import com.nextcloud.client.jobs.download.FileDownloadWorker
import com.nextcloud.client.jobs.download.FileDownloadWorker.Companion.getDownloadAddedMessage
import com.nextcloud.client.jobs.download.FileDownloadWorker.Companion.getDownloadFinishMessage
import com.nextcloud.client.jobs.upload.FileUploadHelper
import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.jobs.upload.FileUploadWorker.Companion.getUploadFinishMessage
Expand Down Expand Up @@ -835,11 +834,15 @@ class FileDisplayActivity :
if (fileInFragment != null && downloadedRemotePath != fileInFragment.remotePath) {
// the user browsed to other file ; forget the automatic preview
mWaitingToPreview = null
} else if (downloadEvent == getDownloadAddedMessage()) {
} else if (downloadEvent == FileDownloadBroadcastManager.DOWNLOAD_ADDED) {
Log_OC.d(TAG, "REFRESH: download added received broadcast")

// grant that the details fragment updates the progress bar
leftFragment.listenForTransferProgress()
leftFragment.updateFileDetails(true, false)
} else if (downloadEvent == getDownloadFinishMessage()) {
} else if (downloadEvent == FileDownloadBroadcastManager.DOWNLOAD_FINISHED) {
Log_OC.d(TAG, "REFRESH: download finish received broadcast")

// update the details panel
var detailsFragmentChanged = false
if (waitedPreview) {
Expand Down Expand Up @@ -1417,8 +1420,8 @@ class FileDisplayActivity :
}

private fun registerDownloadFinishReceiver() {
val filter = IntentFilter(getDownloadAddedMessage()).apply {
addAction(getDownloadFinishMessage())
val filter = IntentFilter(FileDownloadBroadcastManager.DOWNLOAD_ADDED).apply {
addAction(FileDownloadBroadcastManager.DOWNLOAD_FINISHED)
}
mDownloadFinishReceiver = DownloadFinishReceiver()
mDownloadFinishReceiver?.let {
Expand Down Expand Up @@ -1751,6 +1754,8 @@ class FileDisplayActivity :
*/
private inner class DownloadFinishReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
Log_OC.d(TAG, "DownloadFinishReceiver: download finish received broadcast")

val sameAccount = isSameAccount(intent)
val downloadedRemotePath = intent.getStringExtra(FileDownloadWorker.EXTRA_REMOTE_PATH)
val downloadBehaviour = intent.getStringExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR)
Expand Down Expand Up @@ -1899,6 +1904,7 @@ class FileDisplayActivity :
private fun observeWorkerState() {
observeWorker { state ->
when (state) {
/*
is FileDownloadStarted -> {
Log_OC.d(TAG, "Download worker started")
handleDownloadWorkerState()
Expand All @@ -1908,6 +1914,8 @@ class FileDisplayActivity :
fileDownloadProgressListener = null
previewFile(state)
}
*/


is FileUploadCompleted -> {
state.currentFile?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class ManageAccountsActivity :
recyclerView = findViewById(R.id.account_list)
recyclerView?.setAdapter(userListAdapter)
recyclerView?.setLayoutManager(LinearLayoutManager(this))
observeWorkerState()
//observeWorkerState()
}

@Suppress("ReturnCount")
Expand Down
Loading
Loading