diff --git a/app/src/main/java/me/capcom/smsgateway/data/entities/MessageWithRecipients.kt b/app/src/main/java/me/capcom/smsgateway/data/entities/MessageWithRecipients.kt index d6d0a55..c1f18a2 100644 --- a/app/src/main/java/me/capcom/smsgateway/data/entities/MessageWithRecipients.kt +++ b/app/src/main/java/me/capcom/smsgateway/data/entities/MessageWithRecipients.kt @@ -14,7 +14,7 @@ data class MessageWithRecipients( parentColumn = "id", entityColumn = "messageId", ) - val states: List = emptyList() + val states: List = emptyList() ) { val state: Message.State get() = when { diff --git a/app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayApi.kt b/app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayApi.kt index 91a441d..dbce9be 100644 --- a/app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayApi.kt +++ b/app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayApi.kt @@ -95,6 +95,7 @@ class GatewayApi( val id: String, val state: MessageState, val recipients: List, + val states: Map ) data class Message( diff --git a/app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayModule.kt b/app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayModule.kt index cce8fcc..25af539 100644 --- a/app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayModule.kt +++ b/app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayModule.kt @@ -9,11 +9,13 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import me.capcom.smsgateway.data.entities.Message +import me.capcom.smsgateway.data.entities.MessageWithRecipients import me.capcom.smsgateway.domain.MessageState import me.capcom.smsgateway.modules.events.EventBus import me.capcom.smsgateway.modules.gateway.events.DeviceRegisteredEvent +import me.capcom.smsgateway.modules.gateway.workers.PullMessagesWorker +import me.capcom.smsgateway.modules.gateway.workers.SendStateWorker import me.capcom.smsgateway.modules.messages.MessagesService import me.capcom.smsgateway.modules.messages.data.MessageSource import me.capcom.smsgateway.modules.messages.data.SendParams @@ -56,11 +58,7 @@ class GatewayModule( val event = event as? MessageStateChangedEvent ?: return@collect if (event.source != MessageSource.Gateway) return@collect - try { - sendState(event) - } catch (th: Throwable) { - th.printStackTrace() - } + SendStateWorker.start(context, event.id) } } } @@ -74,29 +72,28 @@ class GatewayModule( this._api = null } - private suspend fun sendState( - event: MessageStateChangedEvent + internal suspend fun sendState( + message: MessageWithRecipients ) { val settings = settings.registrationInfo ?: return - withContext(Dispatchers.IO) { - api.patchMessages( - settings.token, - listOf( - GatewayApi.MessagePatchRequest( - event.id, - event.state.toApiState(), - event.recipients.map { - GatewayApi.RecipientState( - it.phoneNumber, - it.state.toApiState(), - it.error - ) - } - ) + api.patchMessages( + settings.token, + listOf( + GatewayApi.MessagePatchRequest( + message.message.id, + message.message.state.toApiState(), + message.recipients.map { + GatewayApi.RecipientState( + it.phoneNumber, + it.state.toApiState(), + it.error + ) + }, + message.states.associate { it.state.toApiState() to it.updatedAt } ) ) - } + ) } suspend fun registerFcmToken(pushToken: String) { @@ -148,35 +145,22 @@ class GatewayModule( ) } - internal suspend fun getNewMessages() { + internal suspend fun getNewMessages(context: Context) { val settings = settings.registrationInfo ?: return val messages = api.getMessages(settings.token) for (message in messages) { try { - processMessage(message) + processMessage(context, message) } catch (th: Throwable) { th.printStackTrace() } } } - private suspend fun processMessage(message: GatewayApi.Message) { + private fun processMessage(context: Context, message: GatewayApi.Message) { val messageState = messagesService.getMessage(message.id) if (messageState != null) { - sendState( - MessageStateChangedEvent( - messageState.message.id, - messageState.message.state, - messageState.message.source, - messageState.recipients.map { rcp -> - MessageStateChangedEvent.Recipient( - rcp.phoneNumber, - rcp.state, - rcp.error - ) - } - ) - ) + SendStateWorker.start(context, message.id) return } diff --git a/app/src/main/java/me/capcom/smsgateway/modules/gateway/PullMessagesWorker.kt b/app/src/main/java/me/capcom/smsgateway/modules/gateway/workers/PullMessagesWorker.kt similarity index 90% rename from app/src/main/java/me/capcom/smsgateway/modules/gateway/PullMessagesWorker.kt rename to app/src/main/java/me/capcom/smsgateway/modules/gateway/workers/PullMessagesWorker.kt index 534a076..44ebbe9 100644 --- a/app/src/main/java/me/capcom/smsgateway/modules/gateway/PullMessagesWorker.kt +++ b/app/src/main/java/me/capcom/smsgateway/modules/gateway/workers/PullMessagesWorker.kt @@ -1,4 +1,4 @@ -package me.capcom.smsgateway.modules.gateway +package me.capcom.smsgateway.modules.gateway.workers import android.content.Context import androidx.lifecycle.map @@ -24,7 +24,11 @@ class PullMessagesWorker( ) : CoroutineWorker(appContext, params) { override suspend fun doWork(): Result { try { - withContext(Dispatchers.IO) { App.instance.gatewayModule.getNewMessages() } + withContext(Dispatchers.IO) { + App.instance.gatewayModule.getNewMessages( + applicationContext + ) + } return Result.success() } catch (th: Throwable) { th.printStackTrace() diff --git a/app/src/main/java/me/capcom/smsgateway/modules/gateway/RegistrationWorker.kt b/app/src/main/java/me/capcom/smsgateway/modules/gateway/workers/RegistrationWorker.kt similarity index 78% rename from app/src/main/java/me/capcom/smsgateway/modules/gateway/RegistrationWorker.kt rename to app/src/main/java/me/capcom/smsgateway/modules/gateway/workers/RegistrationWorker.kt index d85e52c..a0d095a 100644 --- a/app/src/main/java/me/capcom/smsgateway/modules/gateway/RegistrationWorker.kt +++ b/app/src/main/java/me/capcom/smsgateway/modules/gateway/workers/RegistrationWorker.kt @@ -1,7 +1,16 @@ -package me.capcom.smsgateway.modules.gateway +package me.capcom.smsgateway.modules.gateway.workers import android.content.Context -import androidx.work.* +import androidx.work.BackoffPolicy +import androidx.work.Constraints +import androidx.work.CoroutineWorker +import androidx.work.ExistingWorkPolicy +import androidx.work.NetworkType +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkManager +import androidx.work.WorkRequest +import androidx.work.WorkerParameters +import androidx.work.workDataOf import me.capcom.smsgateway.App import java.util.concurrent.TimeUnit diff --git a/app/src/main/java/me/capcom/smsgateway/modules/gateway/workers/SendStateWorker.kt b/app/src/main/java/me/capcom/smsgateway/modules/gateway/workers/SendStateWorker.kt new file mode 100644 index 0000000..3bd7d83 --- /dev/null +++ b/app/src/main/java/me/capcom/smsgateway/modules/gateway/workers/SendStateWorker.kt @@ -0,0 +1,67 @@ +package me.capcom.smsgateway.modules.gateway.workers + +import android.content.Context +import androidx.work.BackoffPolicy +import androidx.work.Constraints +import androidx.work.CoroutineWorker +import androidx.work.NetworkType +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkManager +import androidx.work.WorkRequest +import androidx.work.WorkerParameters +import androidx.work.workDataOf +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import me.capcom.smsgateway.modules.gateway.GatewayModule +import me.capcom.smsgateway.modules.messages.MessagesService +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject +import java.util.concurrent.TimeUnit + +class SendStateWorker(appContext: Context, params: WorkerParameters) : + CoroutineWorker(appContext, params), KoinComponent { + private val messagesService: MessagesService by inject() + private val gatewayModule: GatewayModule by inject() + override suspend fun doWork(): Result { + try { + val messageId = inputData.getString(MESSAGE_ID) ?: return Result.failure() + val message = messagesService.getMessage(messageId) ?: return Result.failure() + + withContext(Dispatchers.IO) { + gatewayModule.sendState(message) + } + return Result.success() + } catch (th: Throwable) { + th.printStackTrace() + return when { + this.runAttemptCount < RETRY_COUNT -> Result.retry() + else -> Result.failure() + } + } + } + + companion object { + private const val RETRY_COUNT = 3 + + private const val MESSAGE_ID = "messageId" + + fun start(context: Context, messageId: String) { + val work = OneTimeWorkRequestBuilder() + .setInputData(workDataOf(MESSAGE_ID to messageId)) + .setBackoffCriteria( + BackoffPolicy.EXPONENTIAL, + WorkRequest.MIN_BACKOFF_MILLIS, + TimeUnit.MILLISECONDS + ) + .setConstraints( + Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + ) + .build() + + WorkManager.getInstance(context) + .enqueue(work) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt b/app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt index 280159f..0936a5e 100644 --- a/app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt +++ b/app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt @@ -212,15 +212,7 @@ class MessagesService( events.emitEvent( MessageStateChangedEvent( id, - msg.state, msg.message.source, - msg.recipients.map { - MessageStateChangedEvent.Recipient( - it.phoneNumber, - it.state, - it.error - ) - } ) ) } diff --git a/app/src/main/java/me/capcom/smsgateway/modules/messages/events/MessageStateChangedEvent.kt b/app/src/main/java/me/capcom/smsgateway/modules/messages/events/MessageStateChangedEvent.kt index d827e80..e94638b 100644 --- a/app/src/main/java/me/capcom/smsgateway/modules/messages/events/MessageStateChangedEvent.kt +++ b/app/src/main/java/me/capcom/smsgateway/modules/messages/events/MessageStateChangedEvent.kt @@ -1,22 +1,13 @@ package me.capcom.smsgateway.modules.messages.events -import me.capcom.smsgateway.data.entities.Message import me.capcom.smsgateway.modules.events.AppEvent import me.capcom.smsgateway.modules.messages.data.MessageSource class MessageStateChangedEvent( val id: String, - val state: Message.State, val source: MessageSource, - val recipients: List, ): AppEvent(NAME) { companion object { const val NAME = "MessageStateChangedEvent" } - - data class Recipient( - val phoneNumber: String, - val state: Message.State, - val error: String?, - ) } \ No newline at end of file diff --git a/app/src/main/java/me/capcom/smsgateway/services/PushService.kt b/app/src/main/java/me/capcom/smsgateway/services/PushService.kt index f441bf3..1db0a14 100644 --- a/app/src/main/java/me/capcom/smsgateway/services/PushService.kt +++ b/app/src/main/java/me/capcom/smsgateway/services/PushService.kt @@ -7,8 +7,8 @@ import com.google.firebase.messaging.FirebaseMessaging import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import me.capcom.smsgateway.helpers.SettingsHelper -import me.capcom.smsgateway.modules.gateway.PullMessagesWorker -import me.capcom.smsgateway.modules.gateway.RegistrationWorker +import me.capcom.smsgateway.modules.gateway.workers.PullMessagesWorker +import me.capcom.smsgateway.modules.gateway.workers.RegistrationWorker class PushService : FirebaseMessagingService() { private val settingsHelper by lazy { SettingsHelper(this) }