فهرست منبع

Add capability to track multiple download workers

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 1 سال پیش
والد
کامیت
e32d8adbcf

+ 14 - 10
app/src/main/java/com/nextcloud/client/files/downloader/FileDownloadWorker.kt

@@ -36,8 +36,8 @@ import com.google.gson.reflect.TypeToken
 import com.nextcloud.client.account.User
 import com.nextcloud.client.account.User
 import com.nextcloud.client.account.UserAccountManager
 import com.nextcloud.client.account.UserAccountManager
 import com.nextcloud.java.util.Optional
 import com.nextcloud.java.util.Optional
-import com.nextcloud.model.WorkerState
-import com.nextcloud.model.WorkerStateLiveData
+import com.nextcloud.model.DownloadWorkerState
+import com.nextcloud.model.DownloadWorkerStateLiveData
 import com.owncloud.android.datamodel.FileDataStorageManager
 import com.owncloud.android.datamodel.FileDataStorageManager
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.UploadsStorageManager
 import com.owncloud.android.datamodel.UploadsStorageManager
@@ -68,6 +68,7 @@ class FileDownloadWorker(
     companion object {
     companion object {
         private val TAG = FileDownloadWorker::class.java.simpleName
         private val TAG = FileDownloadWorker::class.java.simpleName
 
 
+        const val WORKER_TAG = "WORKER_TAG"
         const val FOLDER = "FOLDER"
         const val FOLDER = "FOLDER"
         const val USER_NAME = "USER"
         const val USER_NAME = "USER"
         const val FILE = "FILE"
         const val FILE = "FILE"
@@ -106,6 +107,7 @@ class FileDownloadWorker(
     private var folder: OCFile? = null
     private var folder: OCFile? = null
     private var isAnyOperationFailed = true
     private var isAnyOperationFailed = true
     private val gson = Gson()
     private val gson = Gson()
+    private var workerTag: String? = null
     private val pendingDownloads = IndexedForest<DownloadFileOperation>()
     private val pendingDownloads = IndexedForest<DownloadFileOperation>()
 
 
     @Suppress("TooGenericExceptionCaught")
     @Suppress("TooGenericExceptionCaught")
@@ -144,6 +146,15 @@ class FileDownloadWorker(
         super.onStopped()
         super.onStopped()
     }
     }
 
 
+    private fun setWorkerState(user: User?, file: DownloadFileOperation?) {
+        val worker = DownloadWorkerState(workerTag ?: "", user, file)
+        DownloadWorkerStateLiveData.instance().addWorker(worker)
+    }
+
+    private fun setIdleWorkerState() {
+        DownloadWorkerStateLiveData.instance().removeWorker(workerTag ?: "")
+    }
+
     private fun notifyForFolderResult(folder: OCFile) {
     private fun notifyForFolderResult(folder: OCFile) {
         notificationManager.notifyForResult(null, null, folder, isAnyOperationFailed)
         notificationManager.notifyForResult(null, null, folder, isAnyOperationFailed)
     }
     }
@@ -153,6 +164,7 @@ class FileDownloadWorker(
         val downloadType = getDownloadType()
         val downloadType = getDownloadType()
         setUser()
         setUser()
 
 
+        workerTag = inputData.keyValueMap[WORKER_TAG] as String? ?: ""
         folder = gson.fromJson(inputData.keyValueMap[FOLDER] as? String, OCFile::class.java) ?: null
         folder = gson.fromJson(inputData.keyValueMap[FOLDER] as? String, OCFile::class.java) ?: null
         conflictUploadId = inputData.keyValueMap[CONFLICT_UPLOAD_ID] as Long?
         conflictUploadId = inputData.keyValueMap[CONFLICT_UPLOAD_ID] as Long?
         val behaviour = inputData.keyValueMap[BEHAVIOUR] as String? ?: ""
         val behaviour = inputData.keyValueMap[BEHAVIOUR] as String? ?: ""
@@ -235,14 +247,6 @@ class FileDownloadWorker(
         }
         }
     }
     }
 
 
-    private fun setWorkerState(user: User?, file: DownloadFileOperation?) {
-        WorkerStateLiveData.instance().setWorkState(WorkerState.Download(user, file))
-    }
-
-    private fun setIdleWorkerState() {
-        WorkerStateLiveData.instance().setWorkState(WorkerState.Idle)
-    }
-
     private fun addAccountUpdateListener() {
     private fun addAccountUpdateListener() {
         val am = AccountManager.get(context)
         val am = AccountManager.get(context)
         am.addOnAccountsUpdatedListener(this, null, false)
         am.addOnAccountsUpdatedListener(this, null, false)

+ 3 - 2
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt

@@ -547,7 +547,10 @@ internal class BackgroundJobManagerImpl(
         packageName: String,
         packageName: String,
         conflictUploadId: Long?
         conflictUploadId: Long?
     ) {
     ) {
+        val tag = startFileDownloadJobTag(user, file)
+
         val data = workDataOf(
         val data = workDataOf(
+            FileDownloadWorker.WORKER_TAG to tag,
             FileDownloadWorker.USER_NAME to user.accountName,
             FileDownloadWorker.USER_NAME to user.accountName,
             FileDownloadWorker.FILE to gson.toJson(file),
             FileDownloadWorker.FILE to gson.toJson(file),
             FileDownloadWorker.BEHAVIOUR to behaviour,
             FileDownloadWorker.BEHAVIOUR to behaviour,
@@ -557,8 +560,6 @@ internal class BackgroundJobManagerImpl(
             FileDownloadWorker.CONFLICT_UPLOAD_ID to conflictUploadId
             FileDownloadWorker.CONFLICT_UPLOAD_ID to conflictUploadId
         )
         )
 
 
-        val tag = startFileDownloadJobTag(user, file)
-
         val request = oneTimeRequestBuilder(FileDownloadWorker::class, JOB_FILES_DOWNLOAD, user)
         val request = oneTimeRequestBuilder(FileDownloadWorker::class, JOB_FILES_DOWNLOAD, user)
             .addTag(tag)
             .addTag(tag)
             .setInputData(data)
             .setInputData(data)

+ 18 - 6
app/src/main/java/com/nextcloud/model/WorkerStateLiveData.kt → app/src/main/java/com/nextcloud/model/DownloadWorkerStateLiveData.kt

@@ -23,18 +23,30 @@ package com.nextcloud.model
 
 
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.LiveData
 
 
-class WorkerStateLiveData private constructor() : LiveData<WorkerState>() {
+class DownloadWorkerStateLiveData private constructor() : LiveData<ArrayList<DownloadWorkerState>>() {
 
 
-    fun setWorkState(state: WorkerState) {
-        postValue(state)
+    private var workers: ArrayList<DownloadWorkerState> = arrayListOf()
+
+    fun removeWorker(tag: String) {
+        workers.forEach {
+            if (it.tag == tag) {
+                workers.remove(it)
+            }
+        }
+        postValue(workers)
+    }
+
+    fun addWorker(state: DownloadWorkerState) {
+        workers.add(state)
+        postValue(workers)
     }
     }
 
 
     companion object {
     companion object {
-        private var instance: WorkerStateLiveData? = null
+        private var instance: DownloadWorkerStateLiveData? = null
 
 
-        fun instance(): WorkerStateLiveData {
+        fun instance(): DownloadWorkerStateLiveData {
             return instance ?: synchronized(this) {
             return instance ?: synchronized(this) {
-                instance ?: WorkerStateLiveData().also { instance = it }
+                instance ?: DownloadWorkerStateLiveData().also { instance = it }
             }
             }
         }
         }
     }
     }

+ 1 - 4
app/src/main/java/com/nextcloud/model/WorkerState.kt

@@ -24,7 +24,4 @@ package com.nextcloud.model
 import com.nextcloud.client.account.User
 import com.nextcloud.client.account.User
 import com.owncloud.android.operations.DownloadFileOperation
 import com.owncloud.android.operations.DownloadFileOperation
 
 
-sealed class WorkerState {
-    object Idle : WorkerState()
-    class Download(var user: User?, var currentDownload: DownloadFileOperation?) : WorkerState()
-}
+data class DownloadWorkerState(var tag: String, var user: User?, var currentDownload: DownloadFileOperation?)

+ 15 - 0
app/src/main/java/com/nextcloud/utils/extensions/ContextExtensions.kt

@@ -24,9 +24,11 @@ package com.nextcloud.utils.extensions
 import android.annotation.SuppressLint
 import android.annotation.SuppressLint
 import android.content.BroadcastReceiver
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Context
+import android.content.ContextWrapper
 import android.content.Intent
 import android.content.Intent
 import android.content.IntentFilter
 import android.content.IntentFilter
 import android.os.Build
 import android.os.Build
+import androidx.lifecycle.LifecycleOwner
 import com.owncloud.android.datamodel.ReceiverFlag
 import com.owncloud.android.datamodel.ReceiverFlag
 
 
 @SuppressLint("UnspecifiedRegisterReceiverFlag")
 @SuppressLint("UnspecifiedRegisterReceiverFlag")
@@ -37,3 +39,16 @@ fun Context.registerBroadcastReceiver(receiver: BroadcastReceiver?, filter: Inte
         registerReceiver(receiver, filter)
         registerReceiver(receiver, filter)
     }
     }
 }
 }
+
+fun Context.lifecycleOwner(): LifecycleOwner? {
+    var curContext = this
+    var maxDepth = 20
+    while (maxDepth-- > 0 && curContext !is LifecycleOwner) {
+        curContext = (curContext as ContextWrapper).baseContext
+    }
+    return if (curContext is LifecycleOwner) {
+        curContext
+    } else {
+        null
+    }
+}

+ 5 - 6
app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -73,8 +73,7 @@ import com.nextcloud.client.network.ConnectivityService;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.nextcloud.client.utils.IntentUtil;
 import com.nextcloud.client.utils.IntentUtil;
 import com.nextcloud.java.util.Optional;
 import com.nextcloud.java.util.Optional;
-import com.nextcloud.model.WorkerState;
-import com.nextcloud.model.WorkerStateLiveData;
+import com.nextcloud.model.DownloadWorkerStateLiveData;
 import com.nextcloud.utils.extensions.BundleExtensionsKt;
 import com.nextcloud.utils.extensions.BundleExtensionsKt;
 import com.nextcloud.utils.extensions.IntentExtensionsKt;
 import com.nextcloud.utils.extensions.IntentExtensionsKt;
 import com.nextcloud.utils.view.FastScrollUtils;
 import com.nextcloud.utils.view.FastScrollUtils;
@@ -287,7 +286,7 @@ public class FileDisplayActivity extends FileActivity
         checkStoragePath();
         checkStoragePath();
 
 
         initSyncBroadcastReceiver();
         initSyncBroadcastReceiver();
-        observeWorkerState();
+        observeDownloadWorkerState();
     }
     }
 
 
     @SuppressWarnings("unchecked")
     @SuppressWarnings("unchecked")
@@ -1562,9 +1561,9 @@ public class FileDisplayActivity extends FileActivity
         return isRoot(getCurrentDir());
         return isRoot(getCurrentDir());
     }
     }
 
 
-    private void observeWorkerState() {
-        WorkerStateLiveData.Companion.instance().observe(this, state -> {
-            if (state instanceof WorkerState.Download) {
+    private void observeDownloadWorkerState() {
+        DownloadWorkerStateLiveData.Companion.instance().observe(this, state -> {
+            if (!state.isEmpty()) {
                 Log_OC.d(TAG, "Download worker started");
                 Log_OC.d(TAG, "Download worker started");
                 handleDownloadWorkerState();
                 handleDownloadWorkerState();
             }
             }

+ 21 - 16
app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.java

@@ -37,7 +37,6 @@ import android.os.Handler;
 import android.os.IBinder;
 import android.os.IBinder;
 import android.view.MenuItem;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View;
-
 import com.google.common.collect.Sets;
 import com.google.common.collect.Sets;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.UserAccountManager;
 import com.nextcloud.client.account.UserAccountManager;
@@ -45,8 +44,8 @@ import com.nextcloud.client.files.downloader.FileDownloadHelper;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.onboarding.FirstRunActivity;
 import com.nextcloud.client.onboarding.FirstRunActivity;
 import com.nextcloud.java.util.Optional;
 import com.nextcloud.java.util.Optional;
-import com.nextcloud.model.WorkerState;
-import com.nextcloud.model.WorkerStateLiveData;
+import com.nextcloud.model.DownloadWorkerState;
+import com.nextcloud.model.DownloadWorkerStateLiveData;
 import com.nextcloud.utils.extensions.BundleExtensionsKt;
 import com.nextcloud.utils.extensions.BundleExtensionsKt;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
@@ -115,8 +114,7 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
     private ArbitraryDataProvider arbitraryDataProvider;
     private ArbitraryDataProvider arbitraryDataProvider;
     private boolean multipleAccountsSupported;
     private boolean multipleAccountsSupported;
 
 
-    private String workerAccountName;
-    private DownloadFileOperation workerCurrentDownload;
+    private final ArrayList<DownloadWorkerState> downloadWorkerStates = new ArrayList<>();
 
 
     @Inject BackgroundJobManager backgroundJobManager;
     @Inject BackgroundJobManager backgroundJobManager;
     @Inject UserAccountManager accountManager;
     @Inject UserAccountManager accountManager;
@@ -165,7 +163,7 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
         recyclerView.setAdapter(userListAdapter);
         recyclerView.setAdapter(userListAdapter);
         recyclerView.setLayoutManager(new LinearLayoutManager(this));
         recyclerView.setLayoutManager(new LinearLayoutManager(this));
         initializeComponentGetters();
         initializeComponentGetters();
-        observeWorkerState();
+        observeDownloadWorkerState();
     }
     }
 
 
 
 
@@ -342,7 +340,7 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
                     mUploaderBinder.cancel(accountName);
                     mUploaderBinder.cancel(accountName);
                 }
                 }
 
 
-                FileDownloadHelper.Companion.instance().cancelAllDownloadsForAccount(workerAccountName, workerCurrentDownload);
+                cancelAllDownloadsForAccount();
             }
             }
 
 
             User currentUser = getUserAccountManager().getUser();
             User currentUser = getUserAccountManager().getUser();
@@ -410,6 +408,17 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
         return new ManageAccountsServiceConnection();
         return new ManageAccountsServiceConnection();
     }
     }
 
 
+    private void cancelAllDownloadsForAccount() {
+        for (DownloadWorkerState workerState : downloadWorkerStates) {
+            User currentUser =  workerState.getUser();
+            DownloadFileOperation currentDownload = workerState.getCurrentDownload();
+
+            if (currentUser != null && currentDownload != null) {
+                FileDownloadHelper.Companion.instance().cancelAllDownloadsForAccount(currentUser.getAccountName(), currentDownload);
+            }
+        }
+    }
+
     private void performAccountRemoval(User user) {
     private void performAccountRemoval(User user) {
         // disable account in recycler view
         // disable account in recycler view
         for (int i = 0; i < userListAdapter.getItemCount(); i++) {
         for (int i = 0; i < userListAdapter.getItemCount(); i++) {
@@ -432,8 +441,7 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
             mUploaderBinder.cancel(user);
             mUploaderBinder.cancel(user);
         }
         }
 
 
-        FileDownloadHelper.Companion.instance().cancelAllDownloadsForAccount(workerAccountName, workerCurrentDownload);
-
+        cancelAllDownloadsForAccount();
         backgroundJobManager.startAccountRemovalJob(user.getAccountName(), false);
         backgroundJobManager.startAccountRemovalJob(user.getAccountName(), false);
 
 
         // immediately select a new account
         // immediately select a new account
@@ -517,13 +525,10 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
         }
         }
     }
     }
 
 
-    private void observeWorkerState() {
-        WorkerStateLiveData.Companion.instance().observe(this, state -> {
-            if (state instanceof WorkerState.Download) {
-                Log_OC.d(TAG, "Download worker started");
-                workerAccountName = ((WorkerState.Download) state).getUser().getAccountName();
-                workerCurrentDownload = ((WorkerState.Download) state).getCurrentDownload();
-            }
+    private void observeDownloadWorkerState() {
+        DownloadWorkerStateLiveData.Companion.instance().observe(this, state -> {
+            Log_OC.d(TAG, "Download worker started");
+            downloadWorkerStates.addAll(state);
         });
         });
     }
     }
 
 

+ 1 - 0
app/src/main/java/com/owncloud/android/ui/adapter/GalleryAdapter.kt

@@ -31,6 +31,7 @@ import android.os.Looper
 import android.view.LayoutInflater
 import android.view.LayoutInflater
 import android.view.ViewGroup
 import android.view.ViewGroup
 import androidx.annotation.VisibleForTesting
 import androidx.annotation.VisibleForTesting
+import androidx.lifecycle.LifecycleOwner
 import com.afollestad.sectionedrecyclerview.SectionedRecyclerViewAdapter
 import com.afollestad.sectionedrecyclerview.SectionedRecyclerViewAdapter
 import com.afollestad.sectionedrecyclerview.SectionedViewHolder
 import com.afollestad.sectionedrecyclerview.SectionedViewHolder
 import com.nextcloud.client.account.User
 import com.nextcloud.client.account.User

+ 19 - 1
app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt

@@ -34,7 +34,9 @@ import com.nextcloud.android.common.ui.theme.utils.ColorRole
 import com.nextcloud.client.account.User
 import com.nextcloud.client.account.User
 import com.nextcloud.client.files.downloader.FileDownloadHelper
 import com.nextcloud.client.files.downloader.FileDownloadHelper
 import com.nextcloud.client.preferences.AppPreferences
 import com.nextcloud.client.preferences.AppPreferences
+import com.nextcloud.model.DownloadWorkerStateLiveData
 import com.nextcloud.utils.extensions.createRoundedOutline
 import com.nextcloud.utils.extensions.createRoundedOutline
+import com.nextcloud.utils.extensions.lifecycleOwner
 import com.owncloud.android.R
 import com.owncloud.android.R
 import com.owncloud.android.datamodel.FileDataStorageManager
 import com.owncloud.android.datamodel.FileDataStorageManager
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.OCFile
@@ -74,6 +76,11 @@ class OCFileListDelegate(
     fun setHighlightedItem(highlightedItem: OCFile?) {
     fun setHighlightedItem(highlightedItem: OCFile?) {
         this.highlightedItem = highlightedItem
         this.highlightedItem = highlightedItem
     }
     }
+    private var isDownloading = false
+
+    init {
+        isDownloading()
+    }
 
 
     fun isCheckedFile(file: OCFile): Boolean {
     fun isCheckedFile(file: OCFile): Boolean {
         return checkedFiles.contains(file)
         return checkedFiles.contains(file)
@@ -339,13 +346,24 @@ class OCFileListDelegate(
         }
         }
     }
     }
 
 
+    // FIXME
+    private fun isDownloading() {
+        context.lifecycleOwner()?.let {
+            DownloadWorkerStateLiveData.instance().observe(it) { downloadWorkerStates ->
+                downloadWorkerStates.forEach { state ->
+                    isDownloading = FileDownloadHelper.instance().isDownloading(user, state.currentDownload?.file)
+                }
+            }
+        }
+    }
+
     private fun showLocalFileIndicator(file: OCFile, gridViewHolder: ListGridImageViewHolder) {
     private fun showLocalFileIndicator(file: OCFile, gridViewHolder: ListGridImageViewHolder) {
         val operationsServiceBinder = transferServiceGetter.operationsServiceBinder
         val operationsServiceBinder = transferServiceGetter.operationsServiceBinder
         val fileUploaderBinder = transferServiceGetter.fileUploaderBinder
         val fileUploaderBinder = transferServiceGetter.fileUploaderBinder
 
 
         val icon: Int? = when {
         val icon: Int? = when {
             operationsServiceBinder?.isSynchronizing(user, file) == true ||
             operationsServiceBinder?.isSynchronizing(user, file) == true ||
-                FileDownloadHelper.instance().isDownloading(user, file) ||
+                isDownloading ||
                 fileUploaderBinder?.isUploading(user, file) == true -> {
                 fileUploaderBinder?.isUploading(user, file) == true -> {
                 // synchronizing, downloading or uploading
                 // synchronizing, downloading or uploading
                 R.drawable.ic_synchronizing
                 R.drawable.ic_synchronizing

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

@@ -41,8 +41,7 @@ import com.nextcloud.client.files.downloader.FileDownloadHelper;
 import com.nextcloud.client.files.downloader.FileDownloadWorker;
 import com.nextcloud.client.files.downloader.FileDownloadWorker;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.nextcloud.java.util.Optional;
 import com.nextcloud.java.util.Optional;
-import com.nextcloud.model.WorkerState;
-import com.nextcloud.model.WorkerStateLiveData;
+import com.nextcloud.model.DownloadWorkerStateLiveData;
 import com.nextcloud.utils.extensions.IntentExtensionsKt;
 import com.nextcloud.utils.extensions.IntentExtensionsKt;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
@@ -152,7 +151,7 @@ public class PreviewImageActivity extends FileActivity implements
             mRequestWaitingForBinder = false;
             mRequestWaitingForBinder = false;
         }
         }
 
 
-        observeWorkerState();
+        observeDownloadWorkerState();
     }
     }
 
 
     public void toggleActionBarVisibility(boolean hide) {
     public void toggleActionBarVisibility(boolean hide) {
@@ -306,9 +305,9 @@ public class PreviewImageActivity extends FileActivity implements
         }
         }
     }
     }
 
 
-    private void observeWorkerState() {
-        WorkerStateLiveData.Companion.instance().observe(this, state -> {
-            if (state instanceof WorkerState.Download) {
+    private void observeDownloadWorkerState() {
+        DownloadWorkerStateLiveData.Companion.instance().observe(this, state -> {
+            if (!state.isEmpty()) {
                 Log_OC.d(TAG, "Download worker started");
                 Log_OC.d(TAG, "Download worker started");
                 isDownloadWorkStarted = true;
                 isDownloadWorkStarted = true;