Can someone provide a good Listenable worker example?
Asked Answered
O

4

12

I have been digging into ListenableWorker class to create a service using new workmanager. But nowhere have i found any examples. Any source which describes work manager, gives example of Worker class which has a nice doWork method but it doesn't meet my requirements. So i want your help to write a nice service using ListenableWorker which can handle ListenableFuture

I have tried android developer's documentation and in their documentation, they have written about using guava and using concurrent-futures both of which don't provide any example to write a simple service. I also have watched the workmanager release video in which google engineers explain the new API but their examples are all in Kotlin and i don't get the classes to use.

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.work.ListenableWorker;
import androidx.work.WorkerParameters;

import com.google.common.util.concurrent.ListenableFuture;


public class DistanceWorker extends ListenableWorker {

    public DistanceWorker(Context context, WorkerParameters workerParameters){
        super(context, workerParameters);
    }
    @NonNull
    @Override
    public ListenableFuture<Result> startWork() {
        //what to write here ?
    }
}

I just want to return a future and want to know how to resolve or reject that future when my work is done. Please help me understanding it.

Oleate answered 6/5, 2019 at 15:47 Comment(1)
Google documentation half explained as usual...Ninth
U
10

I've also had questions on how to use ListenableWorkers using Kotlin. So I built this small example to retrieve location, which I believe it's the most common case to use it.

https://github.com/febaisi/ListenableWorkerExample

Here is a generic basic usage (not tested) - I believe it's just easier checking my project out where I added the complete tested version of this. I get data out of the worker in the Github project, and it's kind of hard to exemplify it here.

    //Enqueue work
    val anyWorkListenableWorker = OneTimeWorkRequest.Builder(AnyWorkListenableWorker::class.java).build()
    workManagerInstance.enqueueUniqueWork("ANY_WORK", ExistingWorkPolicy.KEEP, anyWorkListenableWorker)
class AnyWorkListenableWorker(appContext: Context, workerParams: WorkerParameters)
    : ListenableWorker(appContext, workerParams) {

    private val future : ResolvableFuture<Result> = ResolvableFuture.create()

    override fun startWork(): ListenableFuture<Result> {
        //MAIN THREAD

        CoroutineScope(Default).launch {
            //Launch scope to do work out of the main thread
            doAnyWork()
        }

        return future
    }

    private fun doAnyWork() {
        //Do long work
        future.set(Result.success())
    }
}
Unpack answered 7/10, 2019 at 21:53 Comment(4)
I took a look to your example, but I'd like to know if you found out the way to use it periodically with an interval lower than 15 minutesInebriant
Hm. Not the periodic one. You might be able to schedule a new job as soon as your job finished (haven't test this approach) - but there is no way to do it with the periodic one.. If you are doing frequent work you may use a regular foreground service which includes a notification.Unpack
Good one! This is the only example i the internet that makes sense as of 2020 March.Claypoole
Need a new example in 2022 for Android 12 :(Rustyrut
D
5

you can do like this

override fun startWork(): ListenableFuture<ListenableWorker.Result> {
    // Do your work here

    return CallbackToFutureAdapter.getFuture {
      it.set(Result.success())
    } 
}
Delmore answered 3/3, 2020 at 11:43 Comment(3)
credit to this post #56177054Delmore
What about failure cases? For example, if you want to retry? @DanClaypoole
not exactly sure about failure cases - Google docs on this is on the beginning. I personally used the simple Worker (does work on a background thread), not the ListenableWorker (uses the main thread). Some doc on this developer.android.com/topic/libraries/architecture/workmanager/…Delmore
H
0

Sample code from Android Documentation.

class CallbackWorker(
        context: Context,
        params: WorkerParameters
) : ListenableWorker(context, params) {
    override fun startWork(): ListenableFuture<Result> {
        return CallbackToFutureAdapter.getFuture { completer ->
            val callback = object : Callback {
                var successes = 0

                override fun onFailure(call: Call, e: IOException) {
                    completer.setException(e)
                }

                override fun onResponse(call: Call, response: Response) {
                    successes++
                    if (successes == 100) {
                        completer.set(Result.success())
                    }
                }
            }

            repeat(100) {
                downloadAsynchronously("https://example.com", callback)
            }

            callback
        }
    }
}

Reference:- https://developer.android.com/topic/libraries/architecture/workmanager/advanced/listenableworker

Hipparchus answered 15/11, 2022 at 15:14 Comment(0)
M
-2

Worker, CoroutineWorker or RxWorker are all ListenableWorkers. Here is a link to the source:

https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/work/workmanager/src/main/java/androidx/work/Worker.java

https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/work/workmanager-ktx/src/main/java/androidx/work/CoroutineWorker.kt#37

Mcgowen answered 6/5, 2019 at 18:5 Comment(1)
Okay, this might not be the desired response but it did help me write my code. But i wanted to know more about creating a listenable future as they do in guava with thread pool etc. Can you please link some of that example too ? ThanksOleate

© 2022 - 2024 — McMap. All rights reserved.