Implement AccountRemoverWorker.getForegroundInfo()

This is required to run expedited jobs on older Android versions.
This commit is contained in:
cketti 2023-08-07 18:06:43 +02:00
parent d8e09b5790
commit 09240fec56
13 changed files with 92 additions and 3 deletions

View file

@ -0,0 +1,9 @@
package com.fsck.k9.notification
import android.app.Notification
interface BackgroundWorkNotificationController {
val notificationId: Int
fun createNotification(text: String): Notification
}

View file

@ -130,4 +130,11 @@ val coreNotificationModule = module {
notificationConfigurationConverter = get(),
)
}
factory<BackgroundWorkNotificationController> {
RealBackgroundWorkNotificationController(
context = get(),
resourceProvider = get(),
notificationChannelManager = get(),
)
}
}

View file

@ -23,6 +23,7 @@ class NotificationChannelManager(
private val notificationLightDecoder: NotificationLightDecoder,
) {
val pushChannelId = "push"
val miscellaneousChannelId = "misc"
enum class ChannelType {
MESSAGES, MISCELLANEOUS
@ -50,6 +51,7 @@ class NotificationChannelManager(
@RequiresApi(api = Build.VERSION_CODES.O)
private fun addGeneralChannels() {
notificationManager.createNotificationChannel(getChannelPush())
notificationManager.createNotificationChannel(getChannelMiscellaneous())
}
@RequiresApi(api = Build.VERSION_CODES.O)
@ -101,6 +103,21 @@ class NotificationChannelManager(
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private fun getChannelMiscellaneous(): NotificationChannel {
val channelName = resourceProvider.miscellaneousChannelName
val channelDescription = resourceProvider.miscellaneousChannelDescription
val importance = NotificationManager.IMPORTANCE_LOW
return NotificationChannel(miscellaneousChannelId, channelName, importance).apply {
description = channelDescription
setShowBadge(false)
enableLights(false)
enableVibration(false)
setSound(null, null)
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private fun getChannelMessages(account: Account): NotificationChannel {
val channelName = resourceProvider.messagesChannelName

View file

@ -4,8 +4,9 @@ import com.fsck.k9.Account
internal object NotificationIds {
const val PUSH_NOTIFICATION_ID = 1
const val BACKGROUND_WORK_NOTIFICATION_ID = 2
private const val NUMBER_OF_GENERAL_NOTIFICATIONS = 1
private const val NUMBER_OF_GENERAL_NOTIFICATIONS = 2
private const val OFFSET_SEND_FAILED_NOTIFICATION = 0
private const val OFFSET_CERTIFICATE_ERROR_INCOMING = 1
private const val OFFSET_CERTIFICATE_ERROR_OUTGOING = 2

View file

@ -8,6 +8,7 @@ interface NotificationResourceProvider {
val iconNewMail: Int
val iconSendingMail: Int
val iconCheckingMail: Int
val iconBackgroundWorkNotification: Int
val wearIconMarkAsRead: Int
val wearIconDelete: Int
val wearIconArchive: Int

View file

@ -0,0 +1,28 @@
package com.fsck.k9.notification
import android.app.Notification
import android.content.Context
import androidx.core.app.NotificationCompat
class RealBackgroundWorkNotificationController(
private val context: Context,
private val resourceProvider: NotificationResourceProvider,
private val notificationChannelManager: NotificationChannelManager,
) : BackgroundWorkNotificationController {
override val notificationId = NotificationIds.BACKGROUND_WORK_NOTIFICATION_ID
override fun createNotification(text: String): Notification {
val notificationChannel = notificationChannelManager.miscellaneousChannelId
return NotificationCompat.Builder(context, notificationChannel)
.setSmallIcon(resourceProvider.iconBackgroundWorkNotification)
.setContentTitle(text)
.setOngoing(true)
.setNotificationSilent()
.setPriority(NotificationCompat.PRIORITY_MIN)
.setBadgeIconType(NotificationCompat.BADGE_ICON_NONE)
.setLocalOnly(true)
.setShowWhen(false)
.build()
}
}

View file

@ -96,7 +96,7 @@ class NotificationIdsTest {
}
private fun getGeneralNotificationIds(): List<Int> {
return listOf(NotificationIds.PUSH_NOTIFICATION_ID)
return listOf(NotificationIds.PUSH_NOTIFICATION_ID, NotificationIds.BACKGROUND_WORK_NOTIFICATION_ID)
}
private fun getAccountNotificationIds(account: Account): List<Int> {

View file

@ -13,6 +13,7 @@ class TestNotificationResourceProvider : NotificationResourceProvider {
override val wearIconArchive: Int = 10
override val wearIconReplyAll: Int = 11
override val wearIconMarkAsSpam: Int = 12
override val iconBackgroundWorkNotification: Int = 13
override val pushChannelName = "Synchronize (Push)"
override val pushChannelDescription = "Displayed while waiting for new messages"

View file

@ -11,6 +11,7 @@ class K9NotificationResourceProvider(private val context: Context) : Notificatio
override val iconNewMail: Int = R.drawable.notification_icon_new_mail
override val iconSendingMail: Int = R.drawable.notification_icon_check_mail
override val iconCheckingMail: Int = R.drawable.notification_icon_check_mail
override val iconBackgroundWorkNotification: Int = R.drawable.notification_icon_background_work
override val wearIconMarkAsRead: Int = R.drawable.notification_action_mark_as_read
override val wearIconDelete: Int = R.drawable.notification_action_delete
override val wearIconArchive: Int = R.drawable.notification_action_archive

View file

@ -2,17 +2,21 @@ package com.fsck.k9.account
import android.content.Context
import androidx.work.Data
import androidx.work.ForegroundInfo
import androidx.work.OneTimeWorkRequest
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.fsck.k9.notification.BackgroundWorkNotificationController
import com.fsck.k9.ui.R
/**
* A [Worker] to remove an account in the background.
*/
class AccountRemoverWorker(
private val accountRemover: AccountRemover,
private val notificationController: BackgroundWorkNotificationController,
context: Context,
workerParams: WorkerParameters,
) : Worker(context, workerParams) {
@ -25,6 +29,13 @@ class AccountRemoverWorker(
return Result.success()
}
override fun getForegroundInfo(): ForegroundInfo {
val notificationText = applicationContext.getString(R.string.background_work_notification_remove_account)
val notificationId = notificationController.notificationId
val notification = notificationController.createNotification(notificationText)
return ForegroundInfo(notificationId, notification)
}
companion object {
private const val ARG_ACCOUNT_UUID = "accountUuid"

View file

@ -16,6 +16,6 @@ val accountModule = module {
factory { BackgroundAccountRemover(get()) }
factory { AccountCreatorHelper(get(), get()) }
factory { (parameters: WorkerParameters) ->
AccountRemoverWorker(accountRemover = get(), context = get(), parameters)
AccountRemoverWorker(accountRemover = get(), notificationController = get(), context = get(), parameters)
}
}

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M11,21h-1l1,-7H7.5c-0.58,0 -0.57,-0.32 -0.38,-0.66 0.19,-0.34 0.05,-0.08 0.07,-0.12C8.48,10.94 10.42,7.54 13,3h1l-1,7h3.5c0.49,0 0.56,0.33 0.47,0.51l-0.07,0.15C12.96,17.55 11,21 11,21z" />
</vector>

View file

@ -1338,4 +1338,7 @@ You can keep this message and use it as a backup for your secret key. If you wan
<string name="clipboard_label_email_address">Email address</string>
<!-- A user visible label for the name and email address copied to the clipboard -->
<string name="clipboard_label_name_and_email_address">Name and email address</string>
<!-- Might be displayed in a notification when deleting an account (in the background) -->
<string name="background_work_notification_remove_account">Removing account…</string>
</resources>