implement new receivesms worker.

modify sms receive interactor to be used by new worker and add more logging.
create custom workfactory that supports injection into workers.
modify housekeeping worker to use injection.
This commit is contained in:
gavine99
2025-03-28 16:27:20 +11:00
parent aee49985b1
commit be1896e53f
10 changed files with 246 additions and 69 deletions
@@ -22,24 +22,48 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.provider.Telephony.Sms
import dev.octoshrimpy.quik.interactor.ReceiveSms
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
import androidx.work.workDataOf
import dagger.android.AndroidInjection
import dev.octoshrimpy.quik.repository.MessageRepository
import dev.octoshrimpy.quik.worker.ReceiveSmsWorker
import dev.octoshrimpy.quik.worker.ReceiveSmsWorker.Companion.INPUT_DATA_KEY_MESSAGE_ID
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import javax.inject.Inject
class SmsReceiver : BroadcastReceiver() {
@Inject lateinit var receiveMessage: ReceiveSms
@Inject lateinit var messageRepo: MessageRepository
override fun onReceive(context: Context, intent: Intent) {
AndroidInjection.inject(this, context)
Timber.v("onReceive")
Sms.Intents.getMessagesFromIntent(intent)?.let { messages ->
val subId = intent.extras?.getInt("subscription", -1) ?: -1
// reduce list of messages to single message and save in db
val messageId = Single.just(messages)
.observeOn(Schedulers.io())
.map {
Timber.v("onReceive() new sms") // here so runs on io thread
val pendingResult = goAsync()
receiveMessage.execute(ReceiveSms.Params(subId, messages)) { pendingResult.finish() }
messageRepo.insertReceivedSms(
intent.extras?.getInt("subscription", -1) ?: -1,
messages[0].displayOriginatingAddress,
messages.mapNotNull { it.displayMessageBody }.reduce { body, new -> body + new },
messages[0].timestampMillis
).id
}
.blockingGet()
// start worker with message id as param
WorkManager.getInstance(context).enqueue(
OneTimeWorkRequestBuilder<ReceiveSmsWorker>()
.setInputData(workDataOf(INPUT_DATA_KEY_MESSAGE_ID to messageId))
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
)
}
}
@@ -16,25 +16,31 @@
* You should have received a copy of the GNU General Public License
* along with QUIK. If not, see <http://www.gnu.org/licenses/>.
*/
package com.moez.QKSMS.manager
package dev.octoshrimpy.quik.worker
import android.content.Context
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.moez.QKSMS.manager.MediaRecorderManager
import com.moez.QKSMS.manager.MediaRecorderManager.AUDIO_FILE_PREFIX
import dev.octoshrimpy.quik.repository.ScheduledMessageRepository
import dev.octoshrimpy.quik.repository.ScheduledMessageRepositoryImpl
import dev.octoshrimpy.quik.worker.ReceiveSmsWorker.Companion.INPUT_DATA_KEY_MESSAGE_ID
import java.io.File
import java.util.concurrent.TimeUnit
import javax.inject.Inject
class HousekeepingWorkManager(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {
class HousekeepingWorker(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {
companion object {
private val WORKER_TAG: String = HousekeepingWorkManager::class.java.simpleName
private val WORKER_TAG: String = HousekeepingWorker::class.java.simpleName
fun register(context: Context) {
// don't check return value because, well, we can't do much about a failure
@@ -42,7 +48,7 @@ class HousekeepingWorkManager(appContext: Context, workerParams: WorkerParameter
WORKER_TAG,
ExistingPeriodicWorkPolicy.KEEP,
PeriodicWorkRequest.Builder(
HousekeepingWorkManager::class.java,
HousekeepingWorker::class.java,
24,
TimeUnit.HOURS
)
@@ -57,14 +63,16 @@ class HousekeepingWorkManager(appContext: Context, workerParams: WorkerParameter
)
.addTag(WORKER_TAG)
.build()
)
}
fun cancel(context: Context) {
WorkManager.getInstance(context).cancelUniqueWork(WORKER_TAG)
}
)
}
fun cancel(context: Context) {
WorkManager.getInstance(context).cancelUniqueWork(WORKER_TAG)
}
}
@Inject lateinit var scheduledMessageRepository: ScheduledMessageRepository
override fun doWork(): Result {
removeOrphanedScheduledMessageAttachmentFiles()
@@ -75,7 +83,7 @@ class HousekeepingWorkManager(appContext: Context, workerParams: WorkerParameter
private fun removeOrphanedScheduledMessageAttachmentFiles() {
// get list of all scheduled message ids
val scheduledMessageIds = ScheduledMessageRepositoryImpl().getAllScheduledMessageIdsSnapshot()
val scheduledMessageIds = scheduledMessageRepository.getAllScheduledMessageIdsSnapshot()
// remove orphaned scheduled message dirs in files dir
File(applicationContext.filesDir,"")
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2025
*
* This file is part of QUIK.
*
* QUIK is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* QUIK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with QUIK. If not, see <http://www.gnu.org/licenses/>.
*/
package dev.octoshrimpy.quik.worker
import android.content.Context
import androidx.work.ListenableWorker
import androidx.work.Worker
import androidx.work.WorkerFactory
import androidx.work.WorkerParameters
import dev.octoshrimpy.quik.interactor.ReceiveSms
import dev.octoshrimpy.quik.repository.ScheduledMessageRepository
import javax.inject.Inject
class InjectionWorkerFactory @Inject constructor(
private val receiveSms: ReceiveSms,
private val scheduledMessageRepository: ScheduledMessageRepository
)
: WorkerFactory() {
override fun createWorker(
appContext: Context,
workerClassName: String,
workerParameters: WorkerParameters
): ListenableWorker? {
val instance = Class
.forName(workerClassName)
.asSubclass(Worker::class.java)
.getDeclaredConstructor(Context::class.java, WorkerParameters::class.java)
.newInstance(appContext, workerParameters)
when (instance) {
is HousekeepingWorker -> {
instance.scheduledMessageRepository = scheduledMessageRepository
}
is ReceiveSmsWorker -> {
instance.receiveSms = receiveSms
}
}
return instance
}
}
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2025
*
* This file is part of QUIK.
*
* QUIK is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* QUIK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with QUIK. If not, see <http://www.gnu.org/licenses/>.
*/
package dev.octoshrimpy.quik.worker
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import dev.octoshrimpy.quik.interactor.ReceiveSms
import timber.log.Timber
import javax.inject.Inject
class ReceiveSmsWorker(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {
companion object {
const val INPUT_DATA_KEY_MESSAGE_ID = "messageId"
}
@Inject lateinit var receiveSms: ReceiveSms
override fun doWork(): Result {
Timber.v("started")
val messageId = inputData.getLong(INPUT_DATA_KEY_MESSAGE_ID, -1)
if (messageId == -1L) {
Timber.v("failed. message id was -1")
return Result.failure(inputData)
}
// process the new message
receiveSms.execute(messageId)
Timber.v("finished")
return Result.success()
}
}