英文:
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.<init> [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 = ""
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 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<NotificationsWorker>(15, TimeUnit.MINUTES)
.addTag("daily_item")
.build()
WorkManager.getInstance(context)
.enqueueUniquePeriodicWork(
"myapp_notification_work",
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
-
Worker classes should be annotated by @HiltWorker.
-
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()
}
英文:
It looks like you didn't setup hilt-worker properly.
-
Worker classes should be annotated by <a href="https://developer.android.com/reference/androidx/hilt/work/HiltWorker">@HiltWorker</a>.
-
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论