Kotlin: 无法实例化 CoroutineWorker(java.lang.NoSuchMethodException)

huangapple go评论62阅读模式
英文:

Kotlin: Could not instantiate CouroutineWorker (java.lang.NoSuchMethodException)

问题

I can provide translations for the code portions you've provided:

NotificationsWorker:

class NotificationsWorker(
    context: Context,
    workerParameters: WorkerParameters,
    private val repository: MyRepository
): CoroutineWorker(context, workerParameters) {

    override suspend fun doWork(): Result {

        val intent = Intent(applicationContext, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        }

        val pendingIntent: PendingIntent = PendingIntent.getActivity(
            applicationContext, 0, intent, PendingIntent.FLAG_IMMUTABLE
        )

        val today = LocalDate.now()
        var dailyItem = ""
        repository.getDailyItem(today).collect {
            dailyItem = it.title
        }

        val builder = NotificationCompat.Builder(applicationContext, "myChannelId")
            .setSmallIcon(R.drawable.icon)
            .setContentTitle(dailyItem)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setContentIntent(pendingIntent)

        with(NotificationManagerCompat.from(applicationContext)) {
            if (ActivityCompat.checkSelfPermission(
                    applicationContext,
                    Manifest.permission.POST_NOTIFICATIONS
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    ActivityCompat.requestPermissions(
                        MainActivity(),
                        arrayOf(Manifest.permission.POST_NOTIFICATIONS),
                        1
                    )
                }
            }

            notify(1, builder.build())
        }

        return Result.success()
    }

}

NotificationsScheduler:

class NotificationsScheduler @Inject constructor(@ApplicationContext private val context: Context) {

    fun scheduleNotification(hourOfDay: Int, minute: Int) {
        val now = Calendar.getInstance()
        val target = Calendar.getInstance().apply {
            set(Calendar.HOUR_OF_DAY, hourOfDay)
            set(Calendar.MINUTE, minute)
        }

        val timeDiff = target.timeInMillis - now.timeInMillis

        val notificationRequest = PeriodicWorkRequestBuilder<NotificationsWorker>(15, TimeUnit.MINUTES)
            .addTag("daily_item")
            .build()

        WorkManager.getInstance(context)
            .enqueueUniquePeriodicWork(
                "myapp_notification_work",
                ExistingPeriodicWorkPolicy.UPDATE,
                notificationRequest
            )

    }
}

Please note that I've translated the code comments and strings as well. If you have any specific questions or need further assistance with this code, please feel free to ask.

英文:

I'm trying to add periodic (daily) notifications to my app with a different title pulled from a Room DB based on the current date. I'm using Dagger-Hilt and Jetpack compose.

This is the error that appears in Logcat when the time comes for the Worker to do its work:

Could not instantiate com.example.myapp.ui.notifications.NotificationsWorker
java.lang.NoSuchMethodException: com.example.myapp.ui.notifications.NotificationsWorker.&lt;init&gt; [class android.content.Context, class androidx.work.WorkerParameters]
	at java.lang.Class.getConstructor0(Class.java:2363)
	at java.lang.Class.getDeclaredConstructor(Class.java:2201)
	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:1137)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
	at java.lang.Thread.run(Thread.java:1012)
Could not create Worker com.example.myapp.ui.notifications.NotificationsWorker

Here's the rest of the setup:

NotificationsWorker

class NotificationsWorker(
    context: Context,
    workerParameters: WorkerParameters,
    private val repository: MyRepository
): CoroutineWorker(context, workerParameters) {

    override suspend fun doWork(): Result {

        val intent = Intent(applicationContext, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        }

        val pendingIntent: PendingIntent = PendingIntent.getActivity(
            applicationContext, 0, intent, PendingIntent.FLAG_IMMUTABLE
        )

        val today = LocalDate.now()
        var dailyItem = &quot;&quot;
        repository.getDailyItem(today).collect {
            dailyItem = it.title
        }

        val builder = NotificationCompat.Builder(applicationContext, &quot;myChannelId&quot;)
            .setSmallIcon(R.drawable.icon)
            .setContentTitle(dailyItem)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setContentIntent(pendingIntent)

        with(NotificationManagerCompat.from(applicationContext)) {
            if (ActivityCompat.checkSelfPermission(
                    applicationContext,
                    Manifest.permission.POST_NOTIFICATIONS
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.TIRAMISU) {
                    ActivityCompat.requestPermissions(
                        MainActivity(),
                        arrayOf(Manifest.permission.POST_NOTIFICATIONS),
                        1
                    )
                }
            }

            notify(1, builder.build())
        }

        return Result.success()
    }

}

NotificationsScheduler called from a ViewModel

class NotificationsScheduler @Inject constructor(@ApplicationContext private val context: Context) {

    fun scheduleNotification(hourOfDay: Int, minute: Int) {
        val now = Calendar.getInstance()
        val target = Calendar.getInstance().apply {
            set(Calendar.HOUR_OF_DAY, hourOfDay)
            set(Calendar.MINUTE, minute)
        }

        val timeDiff = target.timeInMillis - now.timeInMillis

        val notificationRequest = PeriodicWorkRequestBuilder&lt;NotificationsWorker&gt;(15, TimeUnit.MINUTES)
            .addTag(&quot;daily_item&quot;)
            .build()

        WorkManager.getInstance(context)
            .enqueueUniquePeriodicWork(
                &quot;myapp_notification_work&quot;,
                ExistingPeriodicWorkPolicy.UPDATE,
                notificationRequest
            )

    }
}

I can confirm that requesting POST_NOTIFICATIONS permission works fine. The app targets API 33.

Could you help me figure out what's wrong with the NotificationsWorker, please?

答案1

得分: 1

  1. Worker classes should be annotated by @HiltWorker.

  2. Hilt-WorkerFactory should be injected manually on WorkManager creation.

    2-1. WorkManager version 2.6.0-alpha01 or higher.
    configure your own WorkManager initializer while disabling default WorkManager initializer to inject HiltWorkerFactory to the WorkerManager.
    2-2. WorkManager lower version, construct the WorkManger provider like below

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

  @Inject lateinit var workerFactory: HiltWorkerFactory

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

hilt-worker

英文:

It looks like you didn't setup hilt-worker properly.

  1. Worker classes should be annotated by <a href="https://developer.android.com/reference/androidx/hilt/work/HiltWorker">@HiltWorker</a>.

  2. Hilt-WorkerFactory should be injected manually on WorkManager creation.

    2-1. WorkManager version 2.6.0-alpha01 or higher.
    configure your own WorkManager initializer while disabling default WorkManager initializer to inject HiltWorkerFactory to the WorkerManger.
    2-2. WorkManager lower version, construct the WorkManger provider like below

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

  @Inject lateinit var workerFactory: HiltWorkerFactory

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

<a href="https://developer.android.com/training/dependency-injection/hilt-jetpack?hl=en#workmanager">hilt-worker</a>

huangapple
  • 本文由 发表于 2023年5月22日 15:58:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76304094.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定