diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e2caa58f4ad7b577fcfda369d3654a990adcf113..b4bdbf181ae61d6c80d56f991db39da3b460e7e8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,6 +4,7 @@
package="foundation.e.drive">
+
diff --git a/app/src/main/java/foundation/e/drive/account/receivers/AccountRemoveCallbackReceiver.java b/app/src/main/java/foundation/e/drive/account/receivers/AccountRemoveCallbackReceiver.java
index 668fb93d9f05257c6d556e2a18d91038e868b64c..23f8d392f28b6defaf08487c8d0bee3a50dbb2ea 100644
--- a/app/src/main/java/foundation/e/drive/account/receivers/AccountRemoveCallbackReceiver.java
+++ b/app/src/main/java/foundation/e/drive/account/receivers/AccountRemoveCallbackReceiver.java
@@ -29,6 +29,7 @@ import foundation.e.drive.EdriveApplication;
import foundation.e.drive.R;
import foundation.e.drive.database.DbHelper;
import foundation.e.drive.database.FailedSyncPrefsManager;
+import foundation.e.drive.synchronization.SyncProgressNotifier;
import foundation.e.drive.synchronization.SyncWorker;
import foundation.e.drive.utils.AppConstants;
import foundation.e.drive.utils.DavClientProvider;
@@ -153,7 +154,7 @@ public class AccountRemoveCallbackReceiver extends BroadcastReceiver {
notificationManager.cancelAll();
try {
notificationManager.deleteNotificationChannel(AppConstants.notificationChannelID);
- notificationManager.deleteNotificationChannel(SyncWorker.NOTIF_CHANNEL_ID);
+ notificationManager.deleteNotificationChannel(SyncProgressNotifier.NOTIF_CHANNEL_ID);
} catch (Exception exception) {
Timber.e(exception, "Cannot delete notification Channel");
}
diff --git a/app/src/main/java/foundation/e/drive/synchronization/SyncProgressNotifier.kt b/app/src/main/java/foundation/e/drive/synchronization/SyncProgressNotifier.kt
new file mode 100644
index 0000000000000000000000000000000000000000..79772ea3784ff5b70a715e79d1899aecfc488cb1
--- /dev/null
+++ b/app/src/main/java/foundation/e/drive/synchronization/SyncProgressNotifier.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright © MURENA SAS 2023.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the GNU Public License v3.0
+ * which accompanies this distribution, and is available at
+ * http://www.gnu.org/licenses/gpl.html
+ */
+
+package foundation.e.drive.synchronization
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+import android.content.pm.ServiceInfo
+import android.os.Build
+import androidx.core.app.NotificationCompat
+import androidx.work.ForegroundInfo
+import foundation.e.drive.R
+
+class SyncProgressNotifier(private val context: Context) {
+ companion object {
+ const val NOTIFICATION_ID = 2003004
+ const val NOTIF_CHANNEL_ID = "syncChannelId"
+ }
+
+ private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+
+ private fun createNotification(requestCounter: Int): Notification {
+ val text = getNotificationText(requestCounter)
+ val title = context.getString(R.string.notif_sync_is_running_title)
+
+ return NotificationCompat.Builder(context, NOTIF_CHANNEL_ID)
+ .setOngoing(true)
+ .setContentTitle(title)
+ .setContentText(text)
+ .setSmallIcon(R.drawable.ic_synchronization)
+ .build()
+ }
+
+ fun notifyTaskFinished(requestCounter: Int) {
+ notificationManager.notify(NOTIFICATION_ID, createNotification(requestCounter))
+ }
+
+ fun cancelAllSyncNotifications() {
+ notificationManager.cancel(NOTIFICATION_ID)
+ }
+
+ private fun getNotificationText(requestCount: Int): String {
+ return context.resources
+ .getQuantityString(R.plurals.notif_sync_is_running_txt, requestCount, requestCount)
+ }
+
+ fun createNotificationChannel() {
+ val channelName = context.getString(R.string.notif_sync_channel_name)
+ val importance = NotificationManager.IMPORTANCE_MIN
+ val channel = NotificationChannel(NOTIF_CHANNEL_ID, channelName, importance)
+ val channelDescription = context.getString(R.string.notif_sync_channel_description)
+ channel.description = channelDescription
+
+ notificationManager.createNotificationChannel(channel)
+ }
+
+ internal fun createForegroundInfo(requestCount: Int): ForegroundInfo {
+ val notification = createNotification(requestCount)
+
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ ForegroundInfo(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
+ } else {
+ ForegroundInfo(NOTIFICATION_ID, notification)
+ }
+ }
+}
diff --git a/app/src/main/java/foundation/e/drive/synchronization/SyncTask.kt b/app/src/main/java/foundation/e/drive/synchronization/SyncTask.kt
index 497d547b89a196712b4629ed5b939b24df0aa1c0..7a43489f3fd09f217f6d547edb77b47a71cc4a2f 100644
--- a/app/src/main/java/foundation/e/drive/synchronization/SyncTask.kt
+++ b/app/src/main/java/foundation/e/drive/synchronization/SyncTask.kt
@@ -38,6 +38,8 @@ class SyncTask(
private val fileName = request.syncedFileState.name
private val fileLocalPath = request.syncedFileState.localPath
+ private val syncNotifier = SyncProgressNotifier(context)
+
override fun run() {
if (!canStart()) {
@@ -55,6 +57,7 @@ class SyncTask(
DISABLE_SYNCING -> runSyncDisabling()
}
+ syncNotifier.notifyTaskFinished(SyncWorker.pendingTaskCounter.decrementAndGet())
updateFailureCounter(request, succeed)
syncManager.removeStartedRequest(fileLocalPath)
Timber.d("${request.operationType.name} finished for $fileLocalPath")
diff --git a/app/src/main/java/foundation/e/drive/synchronization/SyncWorker.kt b/app/src/main/java/foundation/e/drive/synchronization/SyncWorker.kt
index 861d7b7cfef126e7535c9eeb6b292a8261e7dae4..c394766783bfb9e1b41ac31e2b451df1da431e98 100644
--- a/app/src/main/java/foundation/e/drive/synchronization/SyncWorker.kt
+++ b/app/src/main/java/foundation/e/drive/synchronization/SyncWorker.kt
@@ -8,26 +8,19 @@
package foundation.e.drive.synchronization
import android.accounts.Account
-import android.app.NotificationChannel
-import android.app.NotificationManager
import android.content.Context
-import android.content.Context.NOTIFICATION_SERVICE
-import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
-import android.os.Build
-import androidx.core.app.NotificationCompat
-import androidx.work.ForegroundInfo
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.owncloud.android.lib.common.OwnCloudClient
import foundation.e.drive.EdriveApplication
-import foundation.e.drive.R
import foundation.e.drive.account.AccountUtils
import foundation.e.drive.utils.DavClientProvider
import timber.log.Timber
import java.util.concurrent.Executors
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicInteger
class SyncWorker(
context: Context,
@@ -36,20 +29,19 @@ class SyncWorker(
companion object {
const val UNIQUE_WORK_NAME = "syncWorker"
- const val NOTIF_CHANNEL_ID = "syncChannelId"
- const val NOTIFICATION_ID = 2003004
+ internal lateinit var pendingTaskCounter: AtomicInteger
private const val threadAmount = 2
private val syncManager = SyncProxy as SyncManager
}
private var account: Account? = null
private var ocClient: OwnCloudClient? = null
- private val notificationManager = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
private var executor = Executors.newFixedThreadPool(threadAmount)
+ private val syncNotifier = SyncProgressNotifier(applicationContext)
override fun onStopped() {
Timber.d("SyncWorker has been stopped")
- notificationManager.cancel(NOTIFICATION_ID)
+ syncNotifier.cancelAllSyncNotifications()
executor.shutdownNow()
super.onStopped()
@@ -70,15 +62,16 @@ class SyncWorker(
syncManager.startListeningFiles(applicationContext as EdriveApplication)
return Result.failure()
}
-
- createNotificationChannel()
+ syncNotifier.createNotificationChannel()
while (!syncManager.isQueueEmpty()) {
- setForegroundAsync(createForegroundInfo())
+ val requestCount = syncManager.getQueueSize()
+ pendingTaskCounter = AtomicInteger(requestCount)
+ setForegroundAsync(syncNotifier.createForegroundInfo(requestCount))
executeRequests()
}
- notificationManager.cancel(NOTIFICATION_ID)
+ syncNotifier.cancelAllSyncNotifications()
syncManager.startListeningFiles(applicationContext as EdriveApplication)
} catch (exception: Exception) {
Timber.w(exception)
@@ -120,35 +113,4 @@ class SyncWorker(
executor.awaitTermination(30, TimeUnit.SECONDS)
}
}
-
- private fun createForegroundInfo(): ForegroundInfo {
- val title = applicationContext.getString(R.string.notif_sync_is_running_title)
- val requestCount = syncManager.getQueueSize()
- val text = applicationContext.resources
- .getQuantityString(R.plurals.notif_sync_is_running_txt, requestCount, requestCount)
-
- val notification = NotificationCompat.Builder(applicationContext, NOTIF_CHANNEL_ID)
- .setOngoing(true)
- .setContentTitle(title)
- .setContentText(text)
- .setSmallIcon(R.drawable.ic_synchronization)
-
- .build()
-
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- ForegroundInfo(NOTIFICATION_ID, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC)
- } else {
- ForegroundInfo(NOTIFICATION_ID, notification)
- }
- }
-
- private fun createNotificationChannel() {
- val channelName = applicationContext.getString(R.string.notif_sync_channel_name)
- val importance = NotificationManager.IMPORTANCE_MIN
- val channel = NotificationChannel(NOTIF_CHANNEL_ID, channelName, importance)
- val channelDescription = applicationContext.getString(R.string.notif_sync_channel_description)
- channel.description = channelDescription
-
- notificationManager.createNotificationChannel(channel)
- }
}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fda41306fe16f9966de42198a8c4576956b5c720..1ebbd1a25159a0a0efefca494dc111b8152bd573 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -31,7 +31,7 @@
99% of your allotted cloud storage is used. Please take action.
You\'ve filled your allotted cloud storage up to 90%.
You\'ve filled your allotted cloud storage up to 80%.
- File synchronization in progress
+ File synchronization
- %d file to sync
- %d files to sync