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)
}