Browse Source

Rebase master

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 1 year ago
parent
commit
a2a1ce4f23

+ 1 - 7
app/src/main/AndroidManifest.xml

@@ -239,12 +239,6 @@
             android:exported="false"
             android:configChanges="orientation|screenLayout|screenSize|keyboardHidden"
             android:theme="@style/Theme.ownCloud.Media" />
-        <service
-            android:name="androidx.work.impl.foreground.SystemForegroundService"
-            android:directBootAware="false"
-            android:enabled="@bool/enable_system_foreground_service_default"
-            android:exported="false"
-            android:foregroundServiceType="dataSync" />
         <service
             android:name=".authentication.AccountAuthenticatorService"
             android:exported="false">
@@ -400,7 +394,7 @@
             android:name=".services.OperationsService"
             android:exported="false" />
         <service
-            android:name="com.nextcloud.client.files.transfer.FileTransferService"
+            android:name="com.nextcloud.client.files.downloader.FileTransferService"
             android:foregroundServiceType="dataSync"
             android:exported="false" />
         <service

+ 2 - 0
app/src/main/java/com/nextcloud/client/di/ComponentsModule.java

@@ -135,6 +135,8 @@ import com.owncloud.android.ui.preview.pdf.PreviewPdfFragment;
 import com.owncloud.android.ui.trashbin.TrashbinActivity;
 import com.owncloud.android.utils.FilesUploadHelper;
 
+import java.io.File;
+
 import dagger.Module;
 import dagger.android.ContributesAndroidInjector;
 

+ 26 - 7
app/src/main/java/com/nextcloud/client/files/downloader/DownloadWorker.kt → app/src/main/java/com/nextcloud/client/files/downloader/FilesDownloadWorker.kt

@@ -22,18 +22,37 @@
 package com.nextcloud.client.files.downloader
 
 import android.content.Context
-import android.content.Intent
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
 import androidx.work.Worker
 import androidx.work.WorkerParameters
-import com.owncloud.android.files.services.FileDownloader
+import com.nextcloud.client.account.UserAccountManager
+import com.owncloud.android.datamodel.UploadsStorageManager
+import com.owncloud.android.utils.theme.ViewThemeUtils
 
-class DownloadWorker(
-    private val context: Context,
+class FilesDownloadWorker(
+    private val viewThemeUtils: ViewThemeUtils,
+    private val accountManager: UserAccountManager,
+    private val uploadsStorageManager: UploadsStorageManager,
+    private var localBroadcastManager: LocalBroadcastManager,
+    context: Context,
     params: WorkerParameters,
-    private val intent: Intent,
-    private val fileDownloader: FileDownloader,
 ) : Worker(context, params) {
+
+    companion object {
+        const val USER = "USER"
+        const val FILE = "FILE"
+        const val BEHAVIOUR = "BEHAVIOUR"
+        const val DOWNLOAD_TYPE = "DOWNLOAD_TYPE"
+        const val ACTIVITY_NAME = "ACTIVITY_NAME"
+        const val PACKAGE_NAME = "PACKAGE_NAME"
+        const val CONFLICT_UPLOAD_ID = "CONFLICT_UPLOAD_ID"
+    }
+
     override fun doWork(): Result {
-        TODO("Not yet implemented")
+        return try {
+            Result.success()
+        } catch (t: Throwable) {
+            Result.failure()
+        }
     }
 }

+ 5 - 4
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt

@@ -34,7 +34,7 @@ import com.nextcloud.client.device.DeviceInfo
 import com.nextcloud.client.device.PowerManagementService
 import com.nextcloud.client.documentscan.GeneratePDFUseCase
 import com.nextcloud.client.documentscan.GeneratePdfFromImagesWork
-import com.nextcloud.client.files.downloader.FileDownloadWorker
+import com.nextcloud.client.files.downloader.FilesDownloadWorker
 import com.nextcloud.client.integrations.deck.DeckApi
 import com.nextcloud.client.logger.Logger
 import com.nextcloud.client.network.ConnectivityService
@@ -103,7 +103,7 @@ class BackgroundJobFactory @Inject constructor(
                 CalendarImportWork::class -> createCalendarImportWork(context, workerParameters)
                 FilesExportWork::class -> createFilesExportWork(context, workerParameters)
                 FilesUploadWorker::class -> createFilesUploadWorker(context, workerParameters)
-                FileDownloadWorker::class -> createFilesDownloadWorker(context, workerParameters)
+                FilesDownloadWorker::class -> createFilesDownloadWorker(context, workerParameters)
                 GeneratePdfFromImagesWork::class -> createPDFGenerateWork(context, workerParameters)
                 HealthStatusWork::class -> createHealthStatusWork(context, workerParameters)
                 TestJob::class -> createTestJob(context, workerParameters)
@@ -255,10 +255,11 @@ class BackgroundJobFactory @Inject constructor(
         )
     }
 
-    private fun createFilesDownloadWorker(context: Context, params: WorkerParameters): FileDownloadWorker {
-        return FileDownloadWorker(
+    private fun createFilesDownloadWorker(context: Context, params: WorkerParameters): FilesDownloadWorker {
+        return FilesDownloadWorker(
             viewThemeUtils.get(),
             accountManager,
+            uploadsStorageManager,
             localBroadcastManager.get(),
             context,
             params

+ 4 - 15
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManager.kt

@@ -145,25 +145,14 @@ interface BackgroundJobManager {
     fun getFileUploads(user: User): LiveData<List<JobInfo>>
     fun cancelFilesUploadJob(user: User)
 
-    fun cancelFilesDownloadJob(user: User, fileId: Long)
-
-    fun isStartFileDownloadJobScheduled(user: User, fileId: Long): Boolean
-
-    @Suppress("LongParameterList")
-    fun startFileDownloadJob(
+    fun startFilesDownloadJob(
         user: User,
-        file: OCFile,
+        ocFile: OCFile,
         behaviour: String,
-        downloadType: DownloadType?,
+        downloadType: DownloadType,
         activityName: String,
         packageName: String,
-        conflictUploadId: Long?
-    )
-
-    fun startFolderDownloadJob(
-        folder: OCFile,
-        user: User,
-        filesPath: List<String>
+        conflictUploadId: Long
     )
 
     fun startPdfGenerateAndUploadWork(user: User, uploadFolder: String, imagePaths: List<String>, pdfPath: String)

+ 16 - 52
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt

@@ -38,11 +38,11 @@ import com.nextcloud.client.account.User
 import com.nextcloud.client.core.Clock
 import com.nextcloud.client.di.Injectable
 import com.nextcloud.client.documentscan.GeneratePdfFromImagesWork
-import com.nextcloud.client.files.downloader.FileDownloadWorker
+import com.nextcloud.client.files.downloader.FilesDownloadWorker
 import com.nextcloud.client.preferences.AppPreferences
-import com.nextcloud.utils.extensions.isWorkScheduled
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.operations.DownloadType
+import java.io.File
 import java.util.Date
 import java.util.UUID
 import java.util.concurrent.TimeUnit
@@ -86,7 +86,6 @@ internal class BackgroundJobManagerImpl(
         const val JOB_NOTIFICATION = "notification"
         const val JOB_ACCOUNT_REMOVAL = "account_removal"
         const val JOB_FILES_UPLOAD = "files_upload"
-        const val JOB_FOLDER_DOWNLOAD = "folder_download"
         const val JOB_FILES_DOWNLOAD = "files_download"
         const val JOB_PDF_GENERATION = "pdf_generation"
         const val JOB_IMMEDIATE_CALENDAR_BACKUP = "immediate_calendar_backup"
@@ -499,6 +498,7 @@ internal class BackgroundJobManagerImpl(
 
         workManager.enqueue(request)
     }
+
     override fun startFilesUploadJob(user: User) {
         val data = workDataOf(FilesUploadWorker.ACCOUNT to user.accountName)
 
@@ -509,62 +509,30 @@ internal class BackgroundJobManagerImpl(
         workManager.enqueueUniqueWork(JOB_FILES_UPLOAD + user.accountName, ExistingWorkPolicy.KEEP, request)
     }
 
-    private fun startFileDownloadJobTag(user: User, fileId: Long): String {
-        return JOB_FOLDER_DOWNLOAD + user.accountName + fileId
-    }
-
-    override fun isStartFileDownloadJobScheduled(user: User, fileId: Long): Boolean {
-        return workManager.isWorkScheduled(startFileDownloadJobTag(user, fileId))
-    }
-
-    override fun startFolderDownloadJob(folder: OCFile, user: User, filesPath: List<String>) {
-        val data = workDataOf(
-            FileDownloadWorker.WORKER_ID to folder.fileId.toInt(),
-            FileDownloadWorker.ACCOUNT_NAME to user.accountName,
-            FileDownloadWorker.FOLDER_REMOTE_PATH to folder.remotePath,
-            FileDownloadWorker.FILES_REMOTE_PATH to filesPath.joinToString(FileDownloadWorker.FILES_SEPARATOR),
-            FileDownloadWorker.DOWNLOAD_TYPE to DownloadType.DOWNLOAD.toString()
-        )
-
-        val tag = startFileDownloadJobTag(user, folder.fileId)
-
-        val request = oneTimeRequestBuilder(FileDownloadWorker::class, JOB_FILES_DOWNLOAD, user)
-            .addTag(tag)
-            .setInputData(data)
-            .build()
-
-        workManager
-            .enqueueUniqueWork(tag, ExistingWorkPolicy.REPLACE, request)
-    }
-
-    override fun startFileDownloadJob(
+    override fun startFilesDownloadJob(
         user: User,
-        file: OCFile,
+        ocFile: OCFile,
         behaviour: String,
-        downloadType: DownloadType?,
+        downloadType: DownloadType,
         activityName: String,
         packageName: String,
-        conflictUploadId: Long?
+        conflictUploadId: Long
     ) {
-        val tag = startFileDownloadJobTag(user, file.fileId)
-
         val data = workDataOf(
-            FileDownloadWorker.WORKER_ID to file.fileId.toInt(),
-            FileDownloadWorker.ACCOUNT_NAME to user.accountName,
-            FileDownloadWorker.FILE_REMOTE_PATH to file.remotePath,
-            FileDownloadWorker.BEHAVIOUR to behaviour,
-            FileDownloadWorker.DOWNLOAD_TYPE to downloadType.toString(),
-            FileDownloadWorker.ACTIVITY_NAME to activityName,
-            FileDownloadWorker.PACKAGE_NAME to packageName,
-            FileDownloadWorker.CONFLICT_UPLOAD_ID to conflictUploadId
+            FilesDownloadWorker.USER to user,
+            FilesDownloadWorker.FILE to ocFile,
+            FilesDownloadWorker.BEHAVIOUR to behaviour,
+            FilesDownloadWorker.DOWNLOAD_TYPE to downloadType,
+            FilesDownloadWorker.ACTIVITY_NAME to activityName,
+            FilesDownloadWorker.PACKAGE_NAME to packageName,
+            FilesDownloadWorker.CONFLICT_UPLOAD_ID to conflictUploadId,
         )
 
-        val request = oneTimeRequestBuilder(FileDownloadWorker::class, JOB_FILES_DOWNLOAD, user)
-            .addTag(tag)
+        val request = oneTimeRequestBuilder(FilesDownloadWorker::class, JOB_FILES_DOWNLOAD, user)
             .setInputData(data)
             .build()
 
-        workManager.enqueueUniqueWork(tag, ExistingWorkPolicy.REPLACE, request)
+        workManager.enqueueUniqueWork(JOB_FILES_DOWNLOAD + user.accountName, ExistingWorkPolicy.REPLACE, request)
     }
 
     override fun getFileUploads(user: User): LiveData<List<JobInfo>> {
@@ -576,10 +544,6 @@ internal class BackgroundJobManagerImpl(
         workManager.cancelJob(JOB_FILES_UPLOAD, user)
     }
 
-    override fun cancelFilesDownloadJob(user: User, fileId: Long) {
-        workManager.cancelAllWorkByTag(startFileDownloadJobTag(user, fileId))
-    }
-
     override fun startPdfGenerateAndUploadWork(
         user: User,
         uploadFolder: String,

+ 10 - 6
app/src/main/java/com/nextcloud/client/jobs/FilesExportWork.kt

@@ -33,12 +33,13 @@ import androidx.core.app.NotificationCompat
 import androidx.work.Worker
 import androidx.work.WorkerParameters
 import com.nextcloud.client.account.User
-import com.nextcloud.client.files.downloader.FileDownloadHelper
 import com.owncloud.android.R
 import com.owncloud.android.datamodel.FileDataStorageManager
 import com.owncloud.android.datamodel.OCFile
+import com.owncloud.android.files.services.FileDownloader
 import com.owncloud.android.lib.common.utils.Log_OC
 import com.owncloud.android.operations.DownloadType
+import com.owncloud.android.ui.dialog.SendShareDialog
 import com.owncloud.android.ui.notifications.NotificationUtils
 import com.owncloud.android.utils.FileExportUtils
 import com.owncloud.android.utils.FileStorageUtils
@@ -111,11 +112,14 @@ class FilesExportWork(
     }
 
     private fun downloadFile(ocFile: OCFile) {
-        FileDownloadHelper.instance().downloadFile(
-            user,
-            ocFile,
-            downloadType = DownloadType.EXPORT
-        )
+        val i = Intent(appContext, FileDownloader::class.java)
+        i.putExtra(FileDownloader.EXTRA_USER, user)
+        i.putExtra(FileDownloader.EXTRA_FILE, ocFile)
+        i.putExtra(SendShareDialog.PACKAGE_NAME, "")
+        i.putExtra(SendShareDialog.ACTIVITY_NAME, "")
+        i.putExtra(FileDownloader.DOWNLOAD_TYPE, DownloadType.EXPORT)
+
+        FileDownloader(i)
     }
 
     private fun showErrorNotification(successfulExports: Int) {

+ 38 - 49
app/src/main/java/com/owncloud/android/files/services/FileDownloader.java

@@ -23,11 +23,10 @@ package com.owncloud.android.files.services;
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.OnAccountsUpdateListener;
-import android.app.Activity;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.Service;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.BitmapFactory;
 import android.os.Binder;
@@ -42,13 +41,13 @@ import android.util.Pair;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.UserAccountManager;
 import com.nextcloud.client.files.downloader.DownloadTask;
+import com.nextcloud.client.files.downloader.FilesDownloadWorker;
 import com.nextcloud.java.util.Optional;
-import com.nextcloud.utils.ForegroundServiceHelper;
 import com.nextcloud.utils.extensions.IntentExtensionsKt;
+import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.ForegroundServiceType;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.UploadsStorageManager;
 import com.owncloud.android.lib.common.OwnCloudAccount;
@@ -86,16 +85,17 @@ import javax.inject.Inject;
 
 import androidx.core.app.NotificationCompat;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
-import dagger.android.AndroidInjection;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkManager;
+import androidx.work.WorkRequest;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 import static android.content.Context.NOTIFICATION_SERVICE;
 
 public class FileDownloader implements OnDatatransferProgressListener, OnAccountsUpdateListener {
 
-    private final Activity activity;
+    private final Context context = MainApp.getAppContext();
     private final Intent intent;
-    private final int startId;
 
     public static final String EXTRA_USER = "USER";
     public static final String EXTRA_FILE = "FILE";
@@ -146,25 +146,21 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
         return FileDownloader.class.getName() + DOWNLOAD_FINISH_MESSAGE;
     }
 
-    public FileDownloader(Activity activity, Intent intent, int startId) {
-        this.activity = activity;
+    public FileDownloader(Intent intent) {
         this.intent = intent;
-        this.startId = startId;
-
-        AndroidInjection.inject(activity);
         Log_OC.d(TAG, "Creating service");
-        mNotificationManager = (NotificationManager) activity.getSystemService(NOTIFICATION_SERVICE);
+        mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
         HandlerThread thread = new HandlerThread("FileDownloaderThread", Process.THREAD_PRIORITY_BACKGROUND);
         thread.start();
         mServiceLooper = thread.getLooper();
         mServiceHandler = new ServiceHandler(mServiceLooper, this);
         mBinder = new FileDownloaderBinder();
 
-        NotificationCompat.Builder builder = NotificationUtils.newNotificationBuilder(activity, viewThemeUtils).setContentTitle(
-                activity.getResources().getString(R.string.app_name))
-            .setContentText(activity.getResources().getString(R.string.foreground_service_download))
+        NotificationCompat.Builder builder = NotificationUtils.newNotificationBuilder(context, viewThemeUtils).setContentTitle(
+                context.getResources().getString(R.string.app_name))
+            .setContentText(context.getResources().getString(R.string.foreground_service_download))
             .setSmallIcon(R.drawable.notification_icon)
-            .setLargeIcon(BitmapFactory.decodeResource(activity.getResources(), R.drawable.notification_icon));
+            .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.notification_icon));
 
 
         if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
@@ -174,11 +170,10 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
         mNotification = builder.build();
 
         // add AccountsUpdatedListener
-        AccountManager am = AccountManager.get(activity);
+        AccountManager am = AccountManager.get(context);
         am.addOnAccountsUpdatedListener(this, null, false);
     }
 
-
     @Override
     protected void finalize() throws Throwable {
         Log_OC.v(TAG, "Destroying service");
@@ -189,7 +184,7 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
         mNotificationManager = null;
 
         // remove AccountsUpdatedListener
-        AccountManager am = AccountManager.get(activity);
+        AccountManager am = AccountManager.get(context);
         am.removeOnAccountsUpdatedListener(this);
         super.finalize();
     }
@@ -213,7 +208,7 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
                                                                           behaviour,
                                                                           activityName,
                                                                           packageName,
-                                                                          activity,
+                                                                          context,
                                                                           downloadType);
             newDownload.addDatatransferProgressListener(this);
             newDownload.addDatatransferProgressListener((FileDownloaderBinder) mBinder);
@@ -232,7 +227,7 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
 
         if (requestedDownloads.size() > 0) {
             Message msg = mServiceHandler.obtainMessage();
-            msg.arg1 = startId;
+            // msg.arg1 = startId;
             msg.obj = requestedDownloads;
             mServiceHandler.sendMessage(msg);
         }
@@ -247,7 +242,6 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
         // The rest of downloads are cancelled when they try to start
     }
 
-
     /**
      * Binder to let client components to perform operations on the queue of downloads.
      * <p/>
@@ -296,11 +290,6 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
             cancelPendingDownloads(accountName);
         }
 
-        public void clearListeners() {
-            mBoundListeners.clear();
-        }
-
-
         /**
          * Returns True when the file described by 'file' in the ownCloud account 'account'
          * is downloading or waiting to download.
@@ -422,14 +411,14 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
                     Optional<User> currentDownloadUser = accountManager.getUser(currentDownloadAccount.name);
                     if (!currentUser.equals(currentDownloadUser)) {
                         currentUser = currentDownloadUser;
-                        mStorageManager = new FileDataStorageManager(currentUser.get(), activity.getContentResolver());
+                        mStorageManager = new FileDataStorageManager(currentUser.get(), context.getContentResolver());
                     }   // else, reuse storage manager from previous operation
 
                     // always get client from client manager, to get fresh credentials in case
                     // of update
                     OwnCloudAccount ocAccount = currentDownloadUser.get().toOwnCloudAccount();
                     mDownloadClient = OwnCloudClientManagerFactory.getDefaultSingleton().
-                            getClientFor(ocAccount, activity);
+                            getClientFor(ocAccount, context);
 
 
                     /// perform the download
@@ -506,15 +495,15 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
     private void notifyDownloadStart(DownloadFileOperation download) {
         /// create status notification with a progress bar
         mLastPercent = 0;
-        mNotificationBuilder = NotificationUtils.newNotificationBuilder(activity, viewThemeUtils);
+        mNotificationBuilder = NotificationUtils.newNotificationBuilder(context, viewThemeUtils);
         mNotificationBuilder
             .setSmallIcon(R.drawable.notification_icon)
-            .setTicker(activity.getString(R.string.downloader_download_in_progress_ticker))
-            .setContentTitle(activity.getString(R.string.downloader_download_in_progress_ticker))
+            .setTicker(context.getString(R.string.downloader_download_in_progress_ticker))
+            .setContentTitle(context.getString(R.string.downloader_download_in_progress_ticker))
             .setOngoing(true)
             .setProgress(100, 0, download.getSize() < 0)
             .setContentText(
-                String.format(activity.getString(R.string.downloader_download_in_progress_content), 0,
+                String.format(context.getString(R.string.downloader_download_in_progress_content), 0,
                               new File(download.getSavePath()).getName()));
 
         if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
@@ -524,20 +513,20 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
         /// includes a pending intent in the notification showing the details view of the file
         Intent showDetailsIntent = null;
         if (PreviewImageFragment.canBePreviewed(download.getFile())) {
-            showDetailsIntent = new Intent(activity, PreviewImageActivity.class);
+            showDetailsIntent = new Intent(context, PreviewImageActivity.class);
         } else {
-            showDetailsIntent = new Intent(activity, FileDisplayActivity.class);
+            showDetailsIntent = new Intent(context, FileDisplayActivity.class);
         }
         showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, download.getFile());
         showDetailsIntent.putExtra(FileActivity.EXTRA_USER, download.getUser());
         showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
-        mNotificationBuilder.setContentIntent(PendingIntent.getActivity(activity, (int) System.currentTimeMillis(),
+        mNotificationBuilder.setContentIntent(PendingIntent.getActivity(context, (int) System.currentTimeMillis(),
                                                                         showDetailsIntent, PendingIntent.FLAG_IMMUTABLE));
 
 
         if (mNotificationManager == null) {
-            mNotificationManager = (NotificationManager) activity.getSystemService(NOTIFICATION_SERVICE);
+            mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
         }
         if (mNotificationManager != null) {
             mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotificationBuilder.build());
@@ -555,11 +544,11 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
         if (percent != mLastPercent) {
             mNotificationBuilder.setProgress(100, percent, totalToTransfer < 0);
             String fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1);
-            String text = String.format(activity.getString(R.string.downloader_download_in_progress_content), percent, fileName);
+            String text = String.format(context.getString(R.string.downloader_download_in_progress_content), percent, fileName);
             mNotificationBuilder.setContentText(text);
 
             if (mNotificationManager == null) {
-                mNotificationManager = (NotificationManager) activity.getSystemService(NOTIFICATION_SERVICE);
+                mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
             }
 
             if (mNotificationManager != null) {
@@ -581,7 +570,7 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
     private void notifyDownloadResult(DownloadFileOperation download,
                                       RemoteOperationResult downloadResult) {
         if (mNotificationManager == null) {
-            mNotificationManager = (NotificationManager) activity.getSystemService(NOTIFICATION_SERVICE);
+            mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
         }
 
         if (!downloadResult.isCancelled()) {
@@ -600,8 +589,8 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
                     R.string.downloader_download_failed_credentials_error : tickerId;
 
             mNotificationBuilder
-                    .setTicker(activity.getString(tickerId))
-                    .setContentTitle(activity.getString(tickerId))
+                    .setTicker(context.getString(tickerId))
+                    .setContentTitle(context.getString(tickerId))
                     .setAutoCancel(true)
                     .setOngoing(false)
                     .setProgress(0, 0, false);
@@ -612,12 +601,12 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
             } else {
                 // TODO put something smart in showDetailsIntent
                 Intent showDetailsIntent = new Intent();
-                mNotificationBuilder.setContentIntent(PendingIntent.getActivity(activity, (int) System.currentTimeMillis(),
+                mNotificationBuilder.setContentIntent(PendingIntent.getActivity(context, (int) System.currentTimeMillis(),
                                                                                 showDetailsIntent, PendingIntent.FLAG_IMMUTABLE));
             }
 
             mNotificationBuilder.setContentText(ErrorMessageAdapter.getErrorCauseMessage(downloadResult,
-                    download, activity.getResources()));
+                                                                                         download, context.getResources()));
 
             if (mNotificationManager != null) {
                 mNotificationManager.notify((new SecureRandom()).nextInt(), mNotificationBuilder.build());
@@ -634,7 +623,7 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
 
     private void configureUpdateCredentialsNotification(User user) {
         // let the user update credentials with one click
-        Intent updateAccountCredentials = new Intent(activity, AuthenticatorActivity.class);
+        Intent updateAccountCredentials = new Intent(context, AuthenticatorActivity.class);
         updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, user.toPlatformAccount());
         updateAccountCredentials.putExtra(
                 AuthenticatorActivity.EXTRA_ACTION,
@@ -644,7 +633,7 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
         updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
         updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
         mNotificationBuilder.setContentIntent(
-            PendingIntent.getActivity(activity,
+            PendingIntent.getActivity(context,
                                       (int) System.currentTimeMillis(),
                                       updateAccountCredentials,
                                       PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE)
@@ -675,7 +664,7 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
         if (unlinkedFromRemotePath != null) {
             end.putExtra(EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath);
         }
-        end.setPackage(activity.getPackageName());
+        end.setPackage(context.getPackageName());
         localBroadcastManager.sendBroadcast(end);
     }
 
@@ -692,7 +681,7 @@ public class FileDownloader implements OnDatatransferProgressListener, OnAccount
         added.putExtra(ACCOUNT_NAME, download.getUser().getAccountName());
         added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
         added.putExtra(EXTRA_LINKED_TO_PATH, linkedToRemotePath);
-        added.setPackage(activity.getPackageName());
+        added.setPackage(context.getPackageName());
         localBroadcastManager.sendBroadcast(added);
     }
 

+ 15 - 4
app/src/main/java/com/owncloud/android/operations/SynchronizeFileOperation.java

@@ -22,12 +22,13 @@
 package com.owncloud.android.operations;
 
 import android.content.Context;
+import android.content.Intent;
 import android.text.TextUtils;
 
 import com.nextcloud.client.account.User;
-import com.nextcloud.client.files.downloader.FileDownloadHelper;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.NameCollisionPolicy;
 import com.owncloud.android.lib.common.OwnCloudClient;
@@ -309,19 +310,29 @@ public class SynchronizeFileOperation extends SyncOperation {
         mTransferWasRequested = true;
     }
 
+
+    /**
+     * Requests for a download to the FileDownloader service
+     *
+     * @param file OCFile object representing the file to download
+     */
     private void requestForDownload(OCFile file) {
-        FileDownloadHelper.Companion.instance().downloadFile(
-            mUser,
-            file);
+        Intent i = new Intent(mContext, FileDownloader.class);
+        i.putExtra(FileDownloader.EXTRA_USER, mUser);
+        i.putExtra(FileDownloader.EXTRA_FILE, file);
 
+        new FileDownloader(i);
         mTransferWasRequested = true;
     }
 
+
     public boolean transferWasRequested() {
         return mTransferWasRequested;
     }
 
+
     public OCFile getLocalFile() {
         return mLocalFile;
     }
+
 }

+ 7 - 8
app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt

@@ -21,13 +21,13 @@ import android.content.Intent
 import android.os.Bundle
 import android.widget.Toast
 import com.nextcloud.client.account.User
-import com.nextcloud.client.files.downloader.FileDownloadHelper
 import com.nextcloud.model.HTTPStatusCodes
 import com.nextcloud.utils.extensions.getParcelableArgument
 import com.owncloud.android.R
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.UploadsStorageManager
 import com.owncloud.android.db.OCUpload
+import com.owncloud.android.files.services.FileDownloader
 import com.owncloud.android.files.services.FileUploader
 import com.owncloud.android.files.services.NameCollisionPolicy
 import com.owncloud.android.lib.common.utils.Log_OC
@@ -114,13 +114,12 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
 
                 Decision.KEEP_SERVER -> if (!shouldDeleteLocal()) {
                     // Overwrite local file
-                    file?.let {
-                        FileDownloadHelper.instance().downloadFile(
-                            getUser().orElseThrow { RuntimeException() },
-                            file,
-                            conflictUploadId = conflictUploadId
-                        )
-                    }
+                    val intent = Intent(baseContext, FileDownloader::class.java)
+                    intent.putExtra(FileDownloader.EXTRA_USER, getUser().orElseThrow { RuntimeException() })
+                    intent.putExtra(FileDownloader.EXTRA_FILE, file)
+                    intent.putExtra(EXTRA_CONFLICT_UPLOAD_ID, conflictUploadId)
+
+                    FileDownloader(intent)
                 } else {
                     uploadsStorageManager!!.removeUpload(upload)
                 }

+ 16 - 8
app/src/main/java/com/owncloud/android/ui/activity/FileActivity.java

@@ -43,8 +43,6 @@ import android.text.TextUtils;
 import com.google.android.material.snackbar.Snackbar;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.UserAccountManager;
-import com.nextcloud.client.files.downloader.FileDownloadHelper;
-import com.nextcloud.client.files.downloader.FileDownloadWorker;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.network.ConnectivityService;
 import com.nextcloud.utils.EditorUtils;
@@ -56,6 +54,8 @@ import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.ArbitraryDataProvider;
 import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileDownloader;
+import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.lib.common.OwnCloudAccount;
@@ -166,8 +166,9 @@ public abstract class FileActivity extends DrawerActivity
 
     private boolean mResumed;
 
-    protected FileDownloadWorker.FileDownloadProgressListener fileDownloadProgressListener;
+    protected FileDownloaderBinder mDownloaderBinder;
     protected FileUploaderBinder mUploaderBinder;
+    private ServiceConnection mDownloadServiceConnection;
     private ServiceConnection mUploadServiceConnection;
 
     @Inject
@@ -205,7 +206,6 @@ public abstract class FileActivity extends DrawerActivity
         super.onCreate(savedInstanceState);
         mHandler = new Handler();
         mFileOperationsHelper = new FileOperationsHelper(this, getUserAccountManager(), connectivityService, editorUtils);
-        User user = null;
 
         if (savedInstanceState != null) {
             mFile = BundleExtensionsKt.getParcelableArgument(savedInstanceState, FileActivity.EXTRA_FILE, OCFile.class);
@@ -218,20 +218,24 @@ public abstract class FileActivity extends DrawerActivity
                 viewThemeUtils.files.themeActionBar(this, actionBar, savedInstanceState.getString(KEY_ACTION_BAR_TITLE));
             }
         } else {
-            user = IntentExtensionsKt.getParcelableArgument(getIntent(), FileActivity.EXTRA_USER, User.class);
+            User user = IntentExtensionsKt.getParcelableArgument(getIntent(), FileActivity.EXTRA_USER, User.class);
             mFile = IntentExtensionsKt.getParcelableArgument(getIntent(), FileActivity.EXTRA_FILE, OCFile.class);
             mFromNotification = getIntent().getBooleanExtra(FileActivity.EXTRA_FROM_NOTIFICATION,
                     false);
-
             if (user != null) {
                 setUser(user);
             }
         }
 
+
         mOperationsServiceConnection = new OperationsServiceConnection();
         bindService(new Intent(this, OperationsService.class), mOperationsServiceConnection,
                 Context.BIND_AUTO_CREATE);
 
+        mDownloadServiceConnection = newTransferenceServiceConnection();
+        if (mDownloadServiceConnection != null) {
+            new FileDownloader(new Intent(this, FileDownloader.class));
+        }
         mUploadServiceConnection = newTransferenceServiceConnection();
         if (mUploadServiceConnection != null) {
             bindService(new Intent(this, FileUploader.class), mUploadServiceConnection,
@@ -275,6 +279,10 @@ public abstract class FileActivity extends DrawerActivity
             unbindService(mOperationsServiceConnection);
             mOperationsServiceBinder = null;
         }
+        if (mDownloadServiceConnection != null) {
+            unbindService(mDownloadServiceConnection);
+            mDownloadServiceConnection = null;
+        }
         if (mUploadServiceConnection != null) {
             unbindService(mUploadServiceConnection);
             mUploadServiceConnection = null;
@@ -607,8 +615,8 @@ public abstract class FileActivity extends DrawerActivity
     }
 
     @Override
-    public FileDownloadWorker.FileDownloadProgressListener getFileDownloadProgressListener() {
-        return fileDownloadProgressListener;
+    public FileDownloaderBinder getFileDownloaderBinder() {
+        return mDownloaderBinder;
     }
 
     @Override

+ 36 - 36
app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.java

@@ -37,25 +37,22 @@ import android.view.View;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.di.Injectable;
 import com.nextcloud.client.editimage.EditImageActivity;
-import com.nextcloud.client.files.downloader.FileDownloadHelper;
-import com.nextcloud.client.files.downloader.FileDownloadWorker;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.nextcloud.java.util.Optional;
-import com.nextcloud.model.WorkerState;
-import com.nextcloud.model.WorkerStateLiveData;
 import com.nextcloud.utils.extensions.IntentExtensionsKt;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.VirtualFolderType;
+import com.owncloud.android.files.services.FileDownloader;
+import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
 import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.operations.DownloadType;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.ui.activity.FileActivity;
@@ -102,8 +99,6 @@ public class PreviewImageActivity extends FileActivity implements
     private DownloadFinishReceiver mDownloadFinishReceiver;
     private UploadFinishReceiver mUploadFinishReceiver;
     private View mFullScreenAnchorView;
-    private boolean isDownloadWorkStarted = false;
-
     @Inject AppPreferences preferences;
     @Inject LocalBroadcastManager localBroadcastManager;
 
@@ -151,8 +146,6 @@ public class PreviewImageActivity extends FileActivity implements
         } else {
             mRequestWaitingForBinder = false;
         }
-
-        observeWorkerState();
     }
 
     public void toggleActionBarVisibility(boolean hide) {
@@ -306,25 +299,6 @@ public class PreviewImageActivity extends FileActivity implements
         }
     }
 
-    private void observeWorkerState() {
-       WorkerStateLiveData.Companion.instance().observe(this, state -> {
-            if (state instanceof WorkerState.Download) {
-                Log_OC.d(TAG, "Download worker started");
-                isDownloadWorkStarted = true;
-
-                if (mRequestWaitingForBinder) {
-                    mRequestWaitingForBinder = false;
-                    Log_OC.d(TAG, "Simulating reselection of current page after connection " +
-                        "of download binder");
-                    onPageSelected(mViewPager.getCurrentItem());
-                }
-            } else {
-                Log_OC.d(TAG, "Download worker stopped");
-                isDownloadWorkStarted = false;
-            }
-        });
-    }
-
     @Override
     protected ServiceConnection newTransferenceServiceConnection() {
         return new PreviewImageServiceConnection();
@@ -335,7 +309,18 @@ public class PreviewImageActivity extends FileActivity implements
 
         @Override
         public void onServiceConnected(ComponentName component, IBinder service) {
+
             if (component.equals(new ComponentName(PreviewImageActivity.this,
+                    FileDownloader.class))) {
+                mDownloaderBinder = (FileDownloaderBinder) service;
+                if (mRequestWaitingForBinder) {
+                    mRequestWaitingForBinder = false;
+                    Log_OC.d(TAG, "Simulating reselection of current page after connection " +
+                            "of download binder");
+                    onPageSelected(mViewPager.getCurrentItem());
+                }
+
+            } else if (component.equals(new ComponentName(PreviewImageActivity.this,
                     FileUploader.class))) {
                 Log_OC.d(TAG, "Upload service connected");
                 mUploaderBinder = (FileUploaderBinder) service;
@@ -346,6 +331,10 @@ public class PreviewImageActivity extends FileActivity implements
         @Override
         public void onServiceDisconnected(ComponentName component) {
             if (component.equals(new ComponentName(PreviewImageActivity.this,
+                    FileDownloader.class))) {
+                Log_OC.d(TAG, "Download service suddenly disconnected");
+                mDownloaderBinder = null;
+            } else if (component.equals(new ComponentName(PreviewImageActivity.this,
                     FileUploader.class))) {
                 Log_OC.d(TAG, "Upload service suddenly disconnected");
                 mUploaderBinder = null;
@@ -370,7 +359,7 @@ public class PreviewImageActivity extends FileActivity implements
         super.onResume();
 
         mDownloadFinishReceiver = new DownloadFinishReceiver();
-        IntentFilter downloadIntentFilter = new IntentFilter(FileDownloadWorker.Companion.getDownloadFinishMessage());
+        IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.getDownloadFinishMessage());
         localBroadcastManager.registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
 
         mUploadFinishReceiver = new UploadFinishReceiver();
@@ -419,8 +408,19 @@ public class PreviewImageActivity extends FileActivity implements
     }
 
     public void requestForDownload(OCFile file, String downloadBehaviour) {
-        final User user = getUser().orElseThrow(RuntimeException::new);
-        FileDownloadHelper.Companion.instance().downloadFileIfNotStartedBefore(user, file);
+        if (mDownloaderBinder == null) {
+            Log_OC.d(TAG, "requestForDownload called without binder to download service");
+
+        } else if (!mDownloaderBinder.isDownloading(getUserAccountManager().getUser(), file)) {
+            final User user = getUser().orElseThrow(RuntimeException::new);
+            Intent i = new Intent(this, FileDownloader.class);
+            i.putExtra(FileDownloader.EXTRA_USER, user);
+            i.putExtra(FileDownloader.EXTRA_FILE, file);
+            if (downloadBehaviour != null) {
+                i.putExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR, downloadBehaviour);
+            }
+            new FileDownloader(i);
+        }
     }
 
     /**
@@ -433,7 +433,7 @@ public class PreviewImageActivity extends FileActivity implements
     public void onPageSelected(int position) {
         mSavedPosition = position;
         mHasSavedPosition = true;
-        if (!isDownloadWorkStarted) {
+        if (mDownloaderBinder == null) {
             mRequestWaitingForBinder = true;
         } else {
             OCFile currentFile = mPreviewImagePagerAdapter.getFileAt(position);
@@ -484,7 +484,7 @@ public class PreviewImageActivity extends FileActivity implements
     }
 
     /**
-     * Class waiting for broadcast events from the {@link FileDownloadWorker} service.
+     * Class waiting for broadcast events from the {@link FileDownloader} service.
      *
      * Updates the UI when a download is started or finished, provided that it is relevant for the
      * folder displayed in the gallery.
@@ -504,12 +504,12 @@ public class PreviewImageActivity extends FileActivity implements
     }
 
     private void previewNewImage(Intent intent) {
-        String accountName = intent.getStringExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME);
-        String downloadedRemotePath = intent.getStringExtra(FileDownloadWorker.EXTRA_REMOTE_PATH);
+        String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
+        String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
         String downloadBehaviour = intent.getStringExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR);
         if (getAccount().name.equals(accountName) && downloadedRemotePath != null) {
             OCFile file = getStorageManager().getFileByPath(downloadedRemotePath);
-            boolean downloadWasFine = intent.getBooleanExtra(FileDownloadWorker.EXTRA_DOWNLOAD_RESULT, false);
+            boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
 
             if (EditImageActivity.OPEN_IMAGE_EDITOR.equals(downloadBehaviour)) {
                 startImageEditor(file);

+ 7 - 2
app/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java

@@ -53,7 +53,6 @@ import android.view.ViewGroup;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.UserAccountManager;
 import com.nextcloud.client.di.Injectable;
-import com.nextcloud.client.files.downloader.FileDownloadHelper;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.media.ExoplayerListener;
 import com.nextcloud.client.media.NextcloudExoPlayer;
@@ -67,6 +66,7 @@ import com.owncloud.android.databinding.FragmentPreviewMediaBinding;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 import com.owncloud.android.files.StreamMediaFileOperation;
+import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -478,7 +478,12 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
                                                                     getView(),
                                                                     backgroundJobManager);
         } else if (itemId == R.id.action_download_file) {
-            FileDownloadHelper.Companion.instance().downloadFileIfNotStartedBefore(user, getFile());
+            if (!containerActivity.getFileDownloaderBinder().isDownloading(user, getFile())) {
+                Intent i = new Intent(requireActivity(), FileDownloader.class);
+                i.putExtra(FileDownloader.EXTRA_USER, user);
+                i.putExtra(FileDownloader.EXTRA_FILE, getFile());
+                new FileDownloader(i);
+            }
         }
     }