使用Coroutine进行网络调用的服务内部的sendBroadcast。

问题描述 投票:0回答:1

我有一个JobIntentService,它应该做一个API调用,一旦有了结果,就做一个广播,我使用一个Coroutine来做网络调用,使用Retrofit.然而,如果我在CoroutineScope内做sendBroadcast,它没有触发BroadcastReceiver。

然而,如果我在CoroutineScope中发送广播,它不会触发BroadcastReceiver。

这是我的服务代码

廣播接收機

class MyService : JobIntentService() {

    private val TAG = MyService::class.java.simpleName
    private var databaseHelper: DatabaseHelper = DatabaseHelper(this)
    private var imageFetcher: ImageFetcher = ImageFetcher(this)
    private var imageSaver: ImageSaver = ImageSaver(this)
    private val receiver = ServiceBroadcastReceiver()


    override fun onHandleWork(intent: Intent) {
        val filter = IntentFilter()
        filter.addAction("ACTION_FINISHED_SERVICE")
        registerReceiver(receiver, filter)

        when (intent.action) {
            "ACTION_FETCH_FROM_API" -> {
                handleFetchFromAPI()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(receiver)
    }

    private fun handleFetchFromAPI() {
        val API = ServiceBuilder.buildWebService(WebService::class.java)
        CoroutineScope(IO).launch {
            try {
                var apiSuccess : Boolean = false
                val apiResponse = API.getImageOfTheDay()
                if (apiResponse.isSuccessful) {
                    apiSuccess = true
                    val imageAPIResponse = apiResponse.body()
                    val bitmap = imageFetcher.getImageBitmapFromURL(imageAPIResponse.url)
                    val filePath = imageSaver.saveBitmapToFile(bitmap, "image.jpg")
                    withContext(Main) {
                        databaseHelper.saveImageInRoom(imageAPIResponse, filePath)
                    }
                }
                if(apiSuccess){
                    val broadCastIntent = Intent()
                    broadCastIntent.action = "ACTION_FINISHED_SERVICE"
                    sendBroadcast(broadCastIntent)
                } 
            } catch (exception: Exception) {
                Log.d(TAG, "Exception occurred ${exception.message}")
            }
        }
    }

    companion object {
        private const val JOB_ID = 2
        @JvmStatic
        fun enqueueWork(context: Context, intent: Intent) {
            enqueueWork(context, MyService::class.java, JOB_ID, intent)
        }
    }
}

ServiceBroadcastReceiver.ktclass ServiceBroadcastReceiver : BroadcastReceiver() {

private val TAG = ServiceBroadcastReceiver::class.java.simpleName
private lateinit var _mNotificationManager: NotificationManager
private val _notificationId = 0
private val _primaryChannelId = "primary_notification_channel"

override fun onReceive(context: Context, intent: Intent) {
    _mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    when (intent.action) {
        "ACTION_FINISHED_SERVICE" -> {
            deliverNotification(context)
        }
    }
}

private fun deliverNotification(context: Context) {
    val contentIntent = Intent(context, MainActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(context,_notificationId,contentIntent,
            PendingIntent.FLAG_UPDATE_CURRENT)
    val builder = NotificationCompat.Builder(context,_primaryChannelId)
    builder.setSmallIcon(R.mipmap.ic_launcher)
    builder.setContentTitle("Hi There")
    builder.setContentText("Service finished its job")
    builder.setContentIntent(pendingIntent)
    builder.priority = NotificationCompat.PRIORITY_HIGH
    builder.setAutoCancel(true)
    builder.setDefaults(NotificationCompat.DEFAULT_ALL)
    _mNotificationManager.notify(_notificationId,builder.build())
}

}

getImageOfTheDay()是WebService.kt内部的一个暂停函数。

@Headers("Content-Type: application/json")
@GET("/v1/getImageOfTheDay")
suspend fun getImageOfTheDay(): Response<ImageAPIResponse>

如果我把代码移到Coroutine作用域之外,广播就会正确发送。如何解决这个问题?

android kotlin broadcastreceiver kotlin-coroutines jobintentservice
1个回答
2
投票

你不应该在这里使用一个coroutine。在这里,你不应该使用coroutine。onHandleWork 方法是在后台线程上调用的,从该方法返回时,表示工作已经完成,可以终止服务。

由于你在启动一个coroutine时使用了 launchజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ onHandleWork 立即返回,你的服务就会终止。

你应该直接调用你的网络API,而不是在一个coroutine中调用,因为...。JobIntentService 已经被设计成这样的工作方式。

© www.soinside.com 2019 - 2024. All rights reserved.