0

I'm having troubles implementing android WorkManager with Kodein. I want to use the WorkManager to track background location updates and send post requests to my server periodically with the users new location.

I've seen multiple ways to implement this with Dagger2 but I was wondering if a similar solution was available with kodein?

This is the error I'm getting:

2019-09-23 12:44:06.690 17462-17500/com.rainparrot.app E/WM-WorkerFactory: Could not instantiate com.rainparrot.app.utility.TrackLocationWorker java.lang.NoSuchMethodException: <init> [class android.content.Context, class androidx.work.WorkerParameters] at java.lang.Class.getConstructor0(Class.java:2204) at java.lang.Class.getDeclaredConstructor(Class.java:2050) at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:96) at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:228) at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:127) at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) at java.lang.Thread.run(Thread.java:761) 2019-09-23 12:44:06.690 17462-17500/com.rainparrot.app E/WM-WorkerWrapper: Could not create Worker com.rainparrot.app.utility.TrackLocationWorker 2019-09-23 12:44:06.830 17462-17462/com.rainparrot.app D/MainActivity$onCreate: Work Manager Status: FAILED

This is my main application file which holds all of my kodein bindings:

    override val kodein = Kodein.lazy {
    import(androidXModule(this@ForecastApplication))
    val prefs = PreferenceManager.getDefaultSharedPreferences(this@ForecastApplication)
    bind<ICurrentWeatherDao>() with singleton { CurrentWeatherDao(prefs) }
    bind<IConnectivityInterceptor>() with singleton { ConnectivityInterceptor(instance()) }
    bind() from singleton { ApiService(instance()) }
    bind<IWeatherNetworkDataSource>() with singleton { WeatherNetworkDataSource(instance(), instance()) }
    bind<ILocationService>() with singleton { LocationService() }
    bind<IForecastRepository>() with singleton { ForecastRepository(instance(), instance(), instance(), instance(), instance(), instance()) }
    bind() from provider { LocationRepository(instance()) }
    bind() from provider { TrackLocationWorker(instance(), instance(), instance()) }
    bind() from provider { WeatherViewModelFactory(instance()) }
}

TrackLocationWorker:

class TrackLocationWorker (
        private val repository: LocationRepository,
        context: Context,
        workerParams: WorkerParameters
) : Worker(context, workerParams){

    override fun doWork(): Result {
        return try {
            repository.getLocation()
            Result.success()
        } catch (e: Exception) {
            Timber.e(e, "Failure in doing work")
            Result.failure()
        }
    }
}

MainActivity instantiation:

fun getFromLocation() = if (isGPSEnabled()) forecastRepository.trackLocation() else forecastRepository.locationSetup()

Forecast repository setup:

override fun locationSetup() {
        enableLocation.value = Response.loading()
        LocationServices.getSettingsClient(application)
                .checkLocationSettings(
                        LocationSettingsRequest.Builder()
                                .addLocationRequest(locationRequest())
                                .setAlwaysShow(true)
                                .build())
                .addOnSuccessListener { enableLocation.value = Response.success(true) }
                .addOnFailureListener {
                    Timber.e(it, "Gps not enabled")
                    enableLocation.value = Response.error(it)
                }
    }

    override fun trackLocation() {
        val locationWorker = PeriodicWorkRequestBuilder<TrackLocationWorker>(15, TimeUnit.MINUTES).addTag(LOCATION_WORK_TAG).build()
        WorkManager.getInstance(this@ForecastRepository.context).enqueueUniquePeriodicWork(LOCATION_WORK_TAG, ExistingPeriodicWorkPolicy.KEEP, locationWorker)
    }
mikle
  • 21
  • 3
  • You are declaring bindings, but you don't seem to retrieve them... – romainbsl Sep 25 '19 at 05:25
  • For example, if you declare `bind() from provider { TrackLocationWorker(instance(), instance(), instance())`, to use it you should do something like `val locationWorker: TrackLocationWorker by kodein.instance()` – romainbsl Sep 25 '19 at 05:27
  • @romainbsl Where would i put `val locationWorker: TrackLocationWorker by kodein.instance()` – mikle Sep 25 '19 at 06:04
  • Wherever you need it, you don't have to instantiate it. – romainbsl Sep 25 '19 at 08:44
  • you can find samples here https://github.com/Kodein-Framework/Kodein-Samples/tree/master/di/coffee-maker/android – romainbsl Sep 25 '19 at 08:45
  • Any solutions you found @mikle I am also getting the same problem..Let me know if you have any findings. – Sai Durga Nov 27 '20 at 05:22

0 Answers0