Skip to content

[Bug]: Version 4.8.5 breaks Hilt dependency injection of CoroutineWorkers #1748

@sebastinto

Description

@sebastinto

What happened?

I've recently started experiencing java.lang.NoSuchMethodException when building CoroutineWorker classes.

The issue disappears when specifying version 4.8.4 of the OneSignal Android SDK in libs.version.toml. So instead of declaring the dependency as onesignal = "[4.0.0, 4.99.99]", declaring it as onesignal = "4.8.4".

Only release builds seem to be affected. Debug builds or release builds with the isDebuggable property set to true in the app-level build.gradle.kts work fine with the latest version of the SDK.

Maybe more relevant for #1672, but adding a breakpoint at line 55 of HiltWorkerFactory seems to indicate that when Hilt attempts to instantiate com.onesignal.OSNotificationRestoreWorkManager$NotificationRestoreWorker or com.onesignal.OSFocusHandler$OnLostFocusWorker, the factory is null. When using the app's CoroutineWorkers the breakpoint is not hit.

I'm using work = "2.8.0" and hilt = "2.45"

My app class:

@ExperimentalCoroutinesApi
@HiltAndroidApp
class MyApplication : Application(), Configuration.Provider {

    // Allows injecting CoroutineWorkers
    @Inject
    lateinit var workerFactory: HiltWorkerFactory

    override fun getWorkManagerConfiguration() =
        Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()

    @Inject
    lateinit var sharedPreferences: SharedPreferences

    @Inject
    lateinit var oneSignal: MyAppOneSignal

    override fun onCreate() {
        super.onCreate()

        val defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()

        Thread.setDefaultUncaughtExceptionHandler(
            defaultUncaughtExceptionHandler?.let {
                CustomUncaughtExceptionHandler(it)
            }
        )

        oneSignal.init(context = this)

        if (BuildConfig.ENABLE_LOGGING) Timber.plant(ExtendedDebugTree())

        with(sharedPreferences) {
            resetTooltips()
            enableInAppUpdatePrompt()
        }
    }

}

I have this in my AndroidManifest.xml 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>

Example of how I declare and enqueue one of the CoroutineWorkers that fail (although I don't think this is relevant)

val myWorker = OneTimeWorkRequestBuilder<MyWorker>()
            .addTag(MY_WORKER_TAG + someData)
            .setInputData(workDataOf(SOME_DATA to someData))
            .setBackoffCriteria(BackoffPolicy.LINEAR, WORK_REQUEST_DEFAULT_BACKOFF_TIME, TimeUnit.MILLISECONDS)
            .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
            .build()

val uniqueWorkName = MY_WORKER_WORK_TAG + "_" + someData + "_" + someOtherData

workManager
            .beginUniqueWork(uniqueWorkName, ExistingWorkPolicy.APPEND_OR_REPLACE, myWorker)
            .then(myOtherWorker)
            .enqueue()

workManager is injected here:

@Module
@InstallIn(SingletonComponent::class)
class WorkModule {

    @Singleton
    @Provides
    fun provideWorkManager(@ApplicationContext context: Context): WorkManager =
        WorkManager.getInstance(context)
}

Steps to reproduce?

N/A

What did you expect to happen?

I expected OneSignal to not interfere with CoroutineWorkers outside of its library 😬

OneSignal Android SDK version

Release 4.8.5

Android version

13, 10

Specific Android models

* Samsung S9
* SDK 29

* Pixel 7 Pro
* SDK 33

Relevant log output

Could not instantiate com.app.MyWorker
java.lang.NoSuchMethodException: com.app.MyWorker.<init> [class android.content.Context, class androidx.work.WorkerParameters]
    at java.lang.Class.getConstructor0(Class.java:2332)
    at java.lang.Class.getDeclaredConstructor(Class.java:2170)
    at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:95)
    at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:243)
    at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:145)
    at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:919)
Could not create Worker com.app.MyWorker

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions