Android中的WorkManager用于处理FCM中接收到的数据的生产者/消费者模式



我想知道在我的Android应用程序中创建生产者/消费者模式的解决方案:

我有一个有热敏打印机的专用设备,这个应用程序接收来自FCM的推送通知货一到就打印收据。这就是问题所在:同时有多个通知没有得到很好的管理,有些是打印的,有些不是。

Printing是对startActivity(...)的调用,Intent包含ACTION_VIEW, CC_3有一个要打开的Uri,允许打印机服务(外部的,不是由我管理的)唤醒。

所以,我想创建众所周知的生产者/消费者模式来排队所有的Intent对象,而不是在FCM内调用startActivity这是onMessageReceived(...)。我怎样才能做到呢?应该实现什么样的服务来使用这个队列并通过这些Intents发送同步打印?

我在WorkManager上阅读文档api,我试着写下面这样的东西:

MyFirebaseMessagingService.kt

class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
remoteMessage.data.isNotEmpty().let { _ ->
try{
val content =
remoteMessage.data["content"]?.let { it1 -> Json.parseToJsonElement(it1).jsonObject }
content?.let { it ->
val title = it["title"]?.toString() ?: "Title example"
val body = it["message"]?.toString() ?: "Msg example"
val pushId = it["notificationId"]?.toString() ?: "42"
val data = it["data"]?.jsonObject                    
val intent = sendToPrinterIntent(data)
sendNotification(..., intent)
//startActivity(intent) //TODO add producer-consumer queue
PrintingWorker.enqueueWork(this, intent)
}
} catch (e: Exception){
Log.d("pushMessage", "Error in json data: $e")
}
}
}
private fun sendToPrinterIntent(data: JsonObject?): Intent {
return data?.let {            
val body = getBody(it)
val uri = "customschema://q?text=$body"
return Intent(Intent.ACTION_VIEW, Uri.parse(uri))
} ?: Intent(Intent.ACTION_VIEW, Uri.parse("customschema://q?text="))
}
override fun onNewToken(token: String) {
Log.d("FCMtoken", "Refreshed token: $token")
}
private fun sendNotification(
messageBody: String,
messageTitle: String,
pushId: Int,
pendingIntent: Intent
) {
...
}
}

PrintingWorker.kt

class PrintingWorker(private val appContext: Context, workerParams: WorkerParameters) :
CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
//calls start activity and waits for it to finish
return withContext(Dispatchers.IO){
//appContext.startActivity()
workerParams.inputData.keyValueMap.forEach {
println("key: ${it.key} value: ${it.value}")
}
//setForeground()
Result.success()
}
}
override suspend fun getForegroundInfo(): ForegroundInfo {
return try {
ForegroundInfo(NOTIFICATION_ID,createNotification())
} catch (e: Exception) {
ForegroundInfo(NOTIFICATION_ID,Notification()) //example: can be ignored
}
}
private fun createNotification(): Notification {
return NotificationCompat...
}
companion object{
val TAG = "PrintingWorker"
val NOTIFICATION_ID = 4242
fun enqueueWork(context: Context, workData: Intent) {

val workRequest = OneTimeWorkRequest.Builder(PrintingWorker::class.java)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setInputData(workDataOf(Pair("printingIntent",workData)))
.build()
WorkManager.getInstance(context).enqueue(workRequest)
}
}
}

正如你在PrintingWorker中看到的,我不确定如何让WorkManager调度和消耗排队的intent。使用这个api的想法是允许消费队列,甚至设备重启,例如。

有什么建议吗?

[编辑]在审查了可能的解决方案后,我计划通过使用Room+前景Service来实现我的目标:想法是在通知到达FCM时在RoomDB的表中创建条目。'sonReceiveMessage->然后ForegroundService通过使用Flow或类似的方法消费条目(在打印数据后一次删除一个)。这是一个更合适的解决方案吗?如果是,使用Flow(或LiveData)这样做的正确过程应该是什么,以避免不想要的结果?

您需要将BundleIntent workData转换为Data data

相关内容

最新更新