refactor: background notification checks (#43)

* migrate worker to coroutines

and remove dispatcher constructor params which prevent proper instantiation

* refactor DefaultInboxNotificationChecker
This commit is contained in:
akesi seli 2024-10-24 14:29:52 +02:00 committed by GitHub
parent 114ac8032e
commit 05bee093bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 62 additions and 33 deletions

View File

@ -6,59 +6,43 @@ import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.work.Worker
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.livefast.eattrash.raccoonforlemmy.domain.inbox.InboxCoordinator
import com.livefast.eattrash.raccoonforlemmy.domain.inbox.R
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import org.koin.java.KoinJavaComponent
import kotlinx.coroutines.withContext
import org.koin.java.KoinJavaComponent.inject
import java.util.Collections.max
import com.livefast.eattrash.raccoonforlemmy.core.resources.R as resourcesR
internal class CheckNotificationWorker(
private val context: Context,
parameters: WorkerParameters,
dispatcher: CoroutineDispatcher = Dispatchers.IO,
) : Worker(context, parameters) {
private val inboxCoordinator by KoinJavaComponent.inject<InboxCoordinator>(InboxCoordinator::class.java)
private val scope: CoroutineScope = CoroutineScope(SupervisorJob() + dispatcher)
) : CoroutineWorker(context, parameters) {
private val inboxCoordinator by inject<InboxCoordinator>(InboxCoordinator::class.java)
override fun doWork(): Result {
scope.launch {
override suspend fun doWork() =
withContext(Dispatchers.IO) {
inboxCoordinator.updateUnreadCount()
val unread = inboxCoordinator.totalUnread.value
if (unread > 0) {
sendNotification(unread)
}
Result.success()
}
return Result.success()
}
@SuppressLint("StringFormatInvalid")
private fun sendNotification(count: Int) {
val intent =
Intent(
context,
Class.forName("com.livefast.eattrash.raccoonforlemmy.android.MainActivity"),
).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val title = context.getString(R.string.inbox_notification_title)
val content = context.getString(R.string.inbox_notification_content, count)
val notification =
Notification.Builder(context, NotificationConstants.CHANNEL_ID)
Notification
.Builder(context, NotificationConstants.CHANNEL_ID)
.setContentTitle(title)
.setContentText(content)
.setSmallIcon(resourcesR.drawable.ic_monochrome)
.setContentIntent(pendingIntent)
.setContentIntent(getPendingIntent())
.setNumber(count)
.build()
val notificationManager: NotificationManager =
@ -71,6 +55,19 @@ internal class CheckNotificationWorker(
)
}
private fun getPendingIntent(): PendingIntent {
val intent =
Intent(
context,
Class.forName(MAIN_ACTIVITY_NAME),
).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
return pendingIntent
}
private fun getNextNotificationId(): Int {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@ -82,4 +79,9 @@ internal class CheckNotificationWorker(
max(activeNotifications.map { it.id }) + 1
}
}
companion object {
private const val MAIN_ACTIVITY_NAME =
"com.livefast.eattrash.raccoonforlemmy.android.MainActivity"
}
}

View File

@ -3,12 +3,14 @@ package com.livefast.eattrash.raccoonforlemmy.domain.inbox.notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import androidx.work.Constraints
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import java.util.concurrent.TimeUnit
private const val TAG = "InboxNotificationCheck"
class DefaultInboxNotificationChecker(
private val context: Context,
) : InboxNotificationChecker {
@ -23,13 +25,34 @@ class DefaultInboxNotificationChecker(
WorkManager.getInstance(context).cancelAllWorkByTag(TAG)
createNotificationChannel()
val constraints =
Constraints
.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
// check immediately with an expedited one-time request
OneTimeWorkRequestBuilder<CheckNotificationWorker>()
.addTag(TAG)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setConstraints(constraints)
.build()
.also { req ->
WorkManager.getInstance(context).enqueue(req)
}
PeriodicWorkRequestBuilder<CheckNotificationWorker>(
repeatInterval = intervalMinutes,
repeatIntervalTimeUnit = TimeUnit.MINUTES,
)
.addTag(TAG)
.build().apply {
WorkManager.getInstance(context).enqueue(this)
).addTag(TAG)
.setConstraints(constraints)
.setInitialDelay(
5,
TimeUnit.MINUTES,
).build()
.also { req ->
WorkManager.getInstance(context).enqueue(req)
}
}
@ -52,4 +75,8 @@ class DefaultInboxNotificationChecker(
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
companion object {
private const val TAG = "InboxNotificationChecker"
}
}