Reputation: 1610
I've followed the Android Developer's tutorial on using the Worker Manager structure to run my code in background but anytime I try to enqueue my worker it doesn't run and I get the following error:
2018-10-04 22:25:47.004 28669-28885/app.package.com.debug E/DefaultWorkerFactory: Could not instantiate app.package.com.MyWorker
java.lang.NoSuchMethodException: <init> []
at java.lang.Class.getConstructor0(Class.java:2320)
at java.lang.Class.getDeclaredConstructor(Class.java:2166)
at androidx.work.DefaultWorkerFactory.createWorker(DefaultWorkerFactory.java:58)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:180)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
2018-10-04 22:25:47.005 28669-28885/app.package.com.debug E/WorkerWrapper: Could for create Worker app.package.com.MyWorker
I've seen that this problem could be related to the default constructor on the worker but I already use the correct one instead of the deprecated default function.
My worker is declared as:
public class MyWorker extends Worker {
public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
// Doesn't even get called
}
}
And it gets queued like so:
WorkManager workManager = WorkManager.getInstance();
if (myWorkerRequest == null) {
myWorkerRequest = new OneTimeWorkRequest.Builder(MyWorker.class)
.setConstraints(new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build())
.build();
}
WorkStatus workStatus = workManager.getStatusById(myWorkerRequest.getId()).getValue();
if (workStatus == null || !workStatus.getState().isFinished()) {
workManager.enqueue(myWorkerRequest);
}
I'm not seeing anything different from the examples so I'd like to understand what else could affect my code to cause this crash. Could it be something ProGuard related?
My version is 1.0.0-alpha09
Thanks!
Upvotes: 40
Views: 30157
Reputation: 102
Add below dependency in build.gradle
implementation("com.google.dagger:hilt-android:2.49")
kapt("com.google.dagger:hilt-compiler:2.49")
implementation("androidx.hilt:hilt-work:1.1.0")
kapt("androidx.hilt:hilt-compiler:1.1.0")
kapt("com.google.dagger:hilt-android-compiler:2.49")
implementation("androidx.hilt:hilt-navigation-fragment:1.1.0")
implementation ("androidx.work:work-runtime-ktx:$workManagerVersion")
implementation ("androidx.work:work-runtime:$workManagerVersion")
Add below code in Manifest
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
Your Application class
@HiltAndroidApp
class MyApp : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
And Your Worker class
@HiltWorker
class ImageFormUpload @AssistedInject constructor(
@Assisted appContext: Context, @Assisted params: WorkerParameters,
private val notificationBuilder: NotificationCompat.Builder,
private val notificationManager: NotificationManagerCompat
) : CoroutineWorker(appContext, params) {
companion object {
private const val TAG = "ImageFormUpload"
}
override suspend fun doWork(): Result {
Log.d(TAG, "doWork: Worked thread")
return Result.success()
}
}
Upvotes: 1
Reputation: 3181
As I had to update
implementation 'androidx.work:work-runtime:2.5.0'
to
implementation 'androidx.work:work-runtime:2.7.1'
and WorkManagerInitializer
wasn't available in the last version
the following change in AndroidManifest.xml
resolved the issue:
Before:
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
After:
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
The solution with "merge"
suggested by others still caused the error.
Upvotes: 0
Reputation: 3916
Try downgrading from OneSignal 4.8.5+ to 4.8.4.
Just in case you tried all the above solutions and are still having problems with Hilt Workers. OneSignal 4.8.5 introduced a bug that initialized the WorkManager before hilt could do so. I noticed it because in my application class getWorkManagerConfiguration() was never called. Downgrading to OneSignal 4.8.4. It took me a couple days to figure this out.
There is a bug filed here: https://github.com/OneSignal/OneSignal-Android-SDK/issues/1748
Upvotes: 0
Reputation: 597
This issue came to me when i copy pasted Worker class to create new Worker class
Solution
Clean Project and Running app solved my issue
Upvotes: 0
Reputation: 1919
I've added this kapt "androidx.hilt:hilt-compiler:1.0.0"
dependency in the app.gradle and error has gone.
Upvotes: 4
Reputation: 1162
I found another case where you might run into NoSuchMethodException
If you have these gradle properties enabled:
kapt.classloaders.cache.size=6
kapt.include.compile.classpath=false
this does aggressive caching of KAPT which results in WorkManager not initialized by hilt
I removed these properties and it worked.
Upvotes: 0
Reputation: 404
I faced the same issue and my solution is here
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
@HiltAndroidApp
class App: Application(), Configuration.Provider {
@Inject
lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
Upvotes: 8
Reputation: 1284
I got the same error then i realized to add app start up library which resolved my issue
manifest file
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
build.gradle.app
def work_version = "2.6.0"
// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"
implementation 'androidx.hilt:hilt-work:1.0.0'
kapt "com.google.dagger:hilt-android-compiler:2.37"
//app start up
implementation("androidx.startup:startup-runtime:1.1.0")
i just added app startup library and set up in Android menifest
Upvotes: 2
Reputation: 195
In addition to Tony's answer:
Another thing to keep in mind if you're using Kotlin is that the Worker class can be nested, but it cannot be marked as inner
.
I suspect that if you're using Java, you might also be able to use a nested class if you mark it as static
. But I haven't tested this.
Upvotes: 6
Reputation: 2218
If you are using Worker
with Hilt
, then, in addition to all other requirements, make sure you are also adding HiltWorkerFactory
to your Application
class
@HiltAndroidApp
class App: Application(), Configuration.Provider {
@Inject
lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
Upvotes: 5
Reputation: 483
If you are using on-demand initialization and Dagger to inject the whole configuration, make sure to remove WorkManager default initialization by adding the following provider in AndroidManifest, as suggested by the pull request. This was the only thing which helped me. For more details, check the blog.
<!-- Remove WorkManager default initialization -->
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
Upvotes: 16
Reputation: 131
The problem for me was the constructor of my kotlin class:
WRONG
class MyWorker(val app: Application, workerParams: WorkerParameters): Worker(app, workerParams)
GOOD
class MyWorker(val context: Context, workerParams: WorkerParameters): Worker(context, workerParams)
Upvotes: 13
Reputation: 2451
I had the same issue. The cause of the issue for me was that my Worker class was a nested class. The moment I made it an independent class, it worked.
Upvotes: 38
Reputation: 3621
I had this problem in stable version 1.0.0 and I fixed it by making my worker class public.
class MyWorker extends Worker {...} > public class MyWorker extends Worker {...}
Upvotes: 9
Reputation: 199805
This is a known issue with WorkManager 1.0.0-alpha09 that is already marked as fixed for alpha10.
As a workaround, you can add the following lines to your proguard configuration:
-keepclassmembers class * extends androidx.work.Worker {
public <init>(android.content.Context,androidx.work.WorkerParameters);
}
Upvotes: 19