Catch missing classes in WorkerFactory (#3744)

When NotificationWorker was moved from ...components.notifications to
...worker.

Installing Tusky with this change doesn't remove any future periodic
jobs queued under the old class name. So when Class.forName() is
called the old class name is not found, and the exception is thrown.

Handle this the same way androidx.work.WorkerFactory does -- catch
the exception, log it, and return null.

Fixes #3740
This commit is contained in:
Nik Clayton 2023-06-12 22:04:58 +02:00 committed by GitHub
parent 5327c9f572
commit eedf6abf91
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -18,11 +18,13 @@
package com.keylesspalace.tusky.worker
import android.content.Context
import android.util.Log
import androidx.work.ListenableWorker
import androidx.work.WorkerFactory
import androidx.work.WorkerParameters
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
/**
* Workers implement this and are added to the map in [com.keylesspalace.tusky.di.WorkerModule]
@ -37,20 +39,33 @@ interface ChildWorkerFactory {
* Creates workers, delegating to each worker's [ChildWorkerFactory.createWorker] to do the
* creation.
*
* @see [com.keylesspalace.tusky.components.notifications.NotificationWorker]
* @see [com.keylesspalace.tusky.worker.NotificationWorker]
*/
@Singleton
class WorkerFactory @Inject constructor(
val workerFactories: Map<Class<out ListenableWorker>, @JvmSuppressWildcards Provider<ChildWorkerFactory>>
private val workerFactories: Map<Class<out ListenableWorker>, @JvmSuppressWildcards Provider<ChildWorkerFactory>>
) : WorkerFactory() {
override fun createWorker(
appContext: Context,
workerClassName: String,
workerParameters: WorkerParameters
): ListenableWorker? {
val key = Class.forName(workerClassName)
val key = try {
Class.forName(workerClassName)
} catch (e: ClassNotFoundException) {
// Class might be missing if it was renamed / moved to a different package, as
// periodic work requests from before the rename might still exist. Catch and
// return null, which should stop future requests.
Log.d(TAG, "Invalid class: $workerClassName", e)
null
}
workerFactories[key]?.let {
return it.get().createWorker(appContext, workerParameters)
}
return null
}
companion object {
private const val TAG = "WorkerFactory"
}
}