diff --git a/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadBroadcastManager.kt b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadBroadcastManager.kt new file mode 100644 index 000000000000..bb7ee4cdc70b --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadBroadcastManager.kt @@ -0,0 +1,86 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * 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) + } +} diff --git a/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadIntents.kt b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadIntents.kt index 5077122c728f..f54a685b807c 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadIntents.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadIntents.kt @@ -1,52 +1,24 @@ /* * Nextcloud - Android Client * - * SPDX-FileCopyrightText: 2023 Alper Ozturk - * SPDX-FileCopyrightText: 2023 Nextcloud GmbH - * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * 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( diff --git a/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadWorker.kt index dfa4c12524ae..47d86585cd30 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadWorker.kt @@ -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), @@ -83,10 +83,6 @@ 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 @@ -94,7 +90,9 @@ class FileDownloadWorker( 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, @@ -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 @@ -266,7 +267,6 @@ class FileDownloadWorker( return } - setWorkerState(user) Log_OC.d(TAG, "downloading: $downloadKey") val isAccountExist = accountManager.exists(currentDownload?.user?.toPlatformAccount()) @@ -342,13 +342,11 @@ class FileDownloadWorker( currentDownload?.run { notifyDownloadResult(this, downloadResult) - val downloadFinishedIntent = intents.downloadFinishedIntent( + fileDownloadBroadcastManager.sendFinished( this, downloadResult, removeResult.second ) - - localBroadcastManager.sendBroadcast(downloadFinishedIntent) } } diff --git a/app/src/main/java/com/owncloud/android/services/SyncFolderHandler.java b/app/src/main/java/com/owncloud/android/services/SyncFolderHandler.java index 4c8d75bc7850..ef033626fc3a 100644 --- a/app/src/main/java/com/owncloud/android/services/SyncFolderHandler.java +++ b/app/src/main/java/com/owncloud/android/services/SyncFolderHandler.java @@ -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; @@ -49,6 +48,7 @@ class SyncFolderHandler extends Handler { private Account mCurrentAccount; private SynchronizeFolderOperation mCurrentSyncOperation; + private FileDownloadBroadcastManager fileDownloadBroadcastManager; public SyncFolderHandler(Looper looper, OperationsService service) { @@ -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); } /** @@ -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); @@ -122,7 +124,7 @@ public void add(Account account, String remotePath, SynchronizeFolderOperation syncFolderOperation){ Pair putResult = mPendingOperations.putIfAbsent(account.name, remotePath, syncFolderOperation); if (putResult != null) { - sendBroadcastNewSyncFolder(account, remotePath); // TODO upgrade! + fileDownloadBroadcastManager.sendAdded(account.name, remotePath, mService.getPackageName(), null); } } @@ -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); } } 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 cd383b4241da..c334cd8c9933 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 @@ -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 @@ -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) { @@ -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 { @@ -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) @@ -1899,6 +1904,7 @@ class FileDisplayActivity : private fun observeWorkerState() { observeWorker { state -> when (state) { + /* is FileDownloadStarted -> { Log_OC.d(TAG, "Download worker started") handleDownloadWorkerState() @@ -1908,6 +1914,8 @@ class FileDisplayActivity : fileDownloadProgressListener = null previewFile(state) } + */ + is FileUploadCompleted -> { state.currentFile?.let { diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.kt index 79bd72d76099..777bf7d82492 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.kt @@ -126,7 +126,7 @@ class ManageAccountsActivity : recyclerView = findViewById(R.id.account_list) recyclerView?.setAdapter(userListAdapter) recyclerView?.setLayoutManager(LinearLayoutManager(this)) - observeWorkerState() + //observeWorkerState() } @Suppress("ReturnCount") diff --git a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt index 505951c20993..5dcddae20f9d 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt @@ -10,7 +10,6 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter -import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.view.MenuItem import android.view.View @@ -24,9 +23,9 @@ import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback import com.nextcloud.client.account.User import com.nextcloud.client.di.Injectable import com.nextcloud.client.editimage.EditImageActivity +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.getDownloadFinishMessage import com.nextcloud.client.jobs.upload.FileUploadWorker.Companion.getUploadFinishMessage import com.nextcloud.client.preferences.AppPreferences import com.nextcloud.model.WorkerState @@ -316,6 +315,7 @@ class PreviewImageActivity : private fun observeWorkerState() { observeWorker { state: WorkerState? -> when (state) { + /* is WorkerState.FileDownloadStarted -> { Log_OC.d(TAG, "Download worker started") isDownloadWorkStarted = true @@ -335,6 +335,8 @@ class PreviewImageActivity : setDownloadedItem() } } + */ + else -> { Log_OC.d(TAG, "Worker stopped") @@ -384,7 +386,7 @@ class PreviewImageActivity : super.onResume() downloadFinishReceiver = DownloadFinishReceiver() - val downloadIntentFilter = IntentFilter(getDownloadFinishMessage()) + val downloadIntentFilter = IntentFilter(FileDownloadBroadcastManager.DOWNLOAD_FINISHED) localBroadcastManager.registerReceiver(downloadFinishReceiver!!, downloadIntentFilter) val uploadFinishReceiver = UploadFinishReceiver()