Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I implement CoroutineWorker using a third-party library that uses callbacks?

I'm trying to implement a CoroutineWorker to do some background work in an Android app. The third-party library I'm using uses callbacks like onConnected, onChanged, etc. How can I use this library inside a CoroutineWorker?

This is what I have so far

override suspend fun doWork(): Result {
    return try {
        val appContext = applicationContext
        var mReporter: StepCountReporter?

        val mStepCountObserver = object : StepCountReporter.StepCountObserver {
            override fun onChanged(count: Int) {
                Log.d(APP_TAG, "Step reported : $count")
                // This is where the work is completed
            }
        }

        val mConnectionListener = object : HealthDataStore.ConnectionListener {

            override fun onConnected() {
                Log.d(APP_TAG, "Health data service is connected.")
                mReporter = StepCountReporter(mStore!!)
                if (isPermissionAcquired) {
                    mReporter!!.start(mStepCountObserver)
                } else {
                    Log.e(APP_TAG, "permissions not acquired")
                }
            }

            override fun onConnectionFailed(error: HealthConnectionErrorResult) {
                Log.d(APP_TAG, "Health data service is not available.")
            }

            override fun onDisconnected() {
                Log.d(APP_TAG, "Health data service is disconnected.")
            }
        }
        mStore = HealthDataStore(appContext, mConnectionListener)
        mStore!!.connectService()
        // wait for mStepCountObserver.onChanged to be called
    } catch (error: Throwable) {
        Result.failure()
    }
}

I'm trying to finish the coroutine inside mStepCountObserver.onChanged, but it looks like I'm supposed to call Result.success at the end of the function.

like image 411
dstaley Avatar asked Oct 30 '25 16:10

dstaley


1 Answers

You can use suspendCoroutine function, which helps to connect coroutines with Callbacks.

'suspendCoroutine' suspends the coroutine which it is called from and only resumes that coroutine when 'resume()' or 'resumeWithException()' is called.


In your case,

override suspend fun doWork(): Result {
        return try {
            val outputCount = suspendCoroutine<Int> {
                val appContext = applicationContext
                var mReporter: StepCountReporter?

                val mStepCountObserver = object : StepCountReporter.StepCountObserver {
                    override fun onChanged(count: Int) {
                        Log.d(APP_TAG, "Step reported : $count")
                        // This is where the work is completed
                        it.resume(Result.success(count))
                    }
                }

                val mConnectionListener = object : HealthDataStore.ConnectionListener {

                    override fun onConnected() {
                        Log.d(APP_TAG, "Health data service is connected.")
                        mReporter = StepCountReporter(mStore!!)
                        if (isPermissionAcquired) {
                            mReporter!!.start(mStepCountObserver)
                        } else {
                            Log.e(APP_TAG, "permissions not acquired")
                            it.resumeWithException(Exception("permissions not acquired"))
                        }
                    }

                    override fun onConnectionFailed(error: HealthConnectionErrorResult) {
                        Log.d(APP_TAG, "Health data service is not available.")
                        it.resumeWithException(Exception("Health data service is not available."))
                    }

                    override fun onDisconnected() {
                        Log.d(APP_TAG, "Health data service is disconnected.")
                        it.resumeWithException(Exception("Health data service is disconnected."))
                    }
                }
                mStore = HealthDataStore(appContext, mConnectionListener)
                mStore!!.connectService()
                // wait for mStepCountObserver.onChanged to be called

            }

            Result.success()
        } catch (error: Throwable) {
            Result.failure()
        }
    }
like image 110
Pavan Varma Avatar answered Nov 01 '25 06:11

Pavan Varma



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!