Я получаю следующее исключение для двух моих CoroutineWorkers с дополнительными параметрами, введенными Hilt. Этого не происходит для воркеров без дополнительных параметров и происходит только тогда, когда я устанавливаю приложение через APK своей сборкой fastlane. Сборки Android Studio работают отлично. Но мой конвейер сборки использует те же настройки, что и сборки Android Studio. Под работой я подразумеваю, что рабочие ставятся в очередь и не выдают следующее исключение...
Could not instantiate com.example.android.ActivitySyncWorker
java.lang.NoSuchMethodException:
com.example.android.ActivitySyncWorker. [class android.content.Context, class androidx.work.WorkerParameters]
at java.lang.Class.getConstructor0(Class.java:3325)
at java.lang.Class.getDeclaredConstructor(Class.java:3063)
at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:94)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:243)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:144)
at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
Внутренняя переменная Hilt mWorkerFactories пуста. Моего работника тогда не найти. Но со сборками Android Studio это не пусто.
Прежде чем я продолжу. Что отличает этот вопрос от других подобных, так это то, что у меня многомодульный проект. Возможно, я что-то упускаю из-за этого.
Это Worker внутри модуля приложения: core-ble
@HiltWorker
class ActivitySyncWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted params: WorkerParameters,
val bleServiceModule: BleServiceModule,
private val connectionPool: BleConnectionPool,
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return coroutineScope {
try {
// ...
Result.success()
} catch (exception: Exception) {
SLog.e("[BLE_SYNC] worker error: $exception")
if (runAttemptCount < 2) {
Result.retry()
} else {
Result.failure()
}
}
}
}
companion object {
private const val ACTIVITY_SYNC_WORKER_TAG = "activity_sync"
fun enqueue(context: Context, workManager: WorkManager, workerParams: Data = Data.EMPTY) {
val workRequest = PeriodicWorkRequestBuilder(30, TimeUnit.MINUTES).apply {
addTag(ACTIVITY_SYNC_WORKER_TAG)
setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
setInputData(
Data.Builder()
.putAll(workerParams)
.build()
)
}.build()
workManager.enqueueUniquePeriodicWork(
/* uniqueWorkName = */ ACTIVITY_SYNC_WORKER_TAG,
/* existingPeriodicWorkPolicy = */ ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
/* periodicWork = */ workRequest
)
}
fun stop(context: Context) {
WorkManager.getInstance(context).cancelAllWorkByTag(ACTIVITY_SYNC_WORKER_TAG)
}
}
}
Этот рабочий всегда ставится в очередь, но не имеет дополнительных введенных параметров. Благодаря отражению его можно найти.
@HiltWorker
class RemoteConfigSyncWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted params: WorkerParameters,
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return coroutineScope {
try {
// ...
Result.success()
} catch (exception: Exception) {
if (runAttemptCount < 2) {
Result.retry()
} else {
Result.failure()
}
}
}
}
companion object {
private const val REMOTE_CONFIG_SYNC_WORKER_TAG = "remote_config_sync"
fun enqueue(workManager: WorkManager, workerParams: Data = Data.EMPTY) {
val workRequest = PeriodicWorkRequestBuilder(30, TimeUnit.MINUTES).apply {
addTag(REMOTE_CONFIG_SYNC_WORKER_TAG)
setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
setInputData(
Data.Builder()
.putAll(workerParams)
.build()
)
}.build()
workManager.enqueueUniquePeriodicWork(
/* uniqueWorkName = */ REMOTE_CONFIG_SYNC_WORKER_TAG,
/* existingPeriodicWorkPolicy = */ ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
/* periodicWork = */ workRequest
)
}
fun stop(context: Context) {
WorkManager.getInstance(context).cancelAllWorkByTag(REMOTE_CONFIG_SYNC_WORKER_TAG)
}
}
}
Как вы видите в моем манифесте, я удалил инициализатор по умолчанию и добавил свой собственный...
Это новый инициализатор...
@Module
@InstallIn(SingletonComponent::class)
object WorkManagerModule : Initializer {
private var isInitialized = false
@Provides
@Singleton
override fun create(@ApplicationContext context: Context): WorkManager {
if (!isInitialized) { // just in case this gets called twice
val entryPoint = EntryPointAccessors.fromApplication(
context,
HiltWorkerFactoryEntryPoint::class.java
)
val configuration = Configuration.Builder()
.setWorkerFactory(entryPoint.workerFactory())
.setMinimumLoggingLevel(Log.VERBOSE)
.build()
WorkManager.initialize(context, configuration)
isInitialized = true
}
return WorkManager.getInstance(context)
}
override fun dependencies(): MutableList {
return mutableListOf()
}
@EntryPoint
@InstallIn(SingletonComponent::class)
interface HiltWorkerFactoryEntryPoint {
fun workerFactory(): HiltWorkerFactory
}
}
Я делаю это в onCreate моего MultiDexApplication, который находится в :app
AppInitializer.getInstance(this).initializeComponent(WorkManagerModule::class.java)
Мой импорт... (как в :core-ble, так и в :app.
implementation(libs.hilt)
implementation(libs.hilt.work)
implementation(libs.hilt.plugin)
kapt(libs.hilt.compiler)
kapt(libs.hilt.androidx.compiler)
implementation(libs.work.runtime.ktx)
implementation(libs.startup)
hilt = "2.44.2"
hiltAndroidX = "1.1.0"
hiltCompose = "1.0.0"
hiltWork = "1.0.0"
work = "2.9.0"
hiltKapt = "2.35"
hilt-plugin = { group = "com.google.dagger", name = "hilt-android-gradle-plugin", version.ref = "hilt" }
hilt-kapt = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hiltKapt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
hilt-androidx-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltAndroidX" }
hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltWork" }
startup = { group = "androidx.startup", name = "startup-runtime", version.ref = "startup" }
hilt = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
work-runtime = { group = "androidx.work", name = "work-runtime", version.ref = "work" }
work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work" }
Я также пробовал добавить эти правила ProGuard, но почему они должны работать со сборками Android Studio, а не со сборками APK.
-keepclassmembers class * extends androidx.work.Worker {
public (android.content.Context,androidx.work.WorkerParameters);
}
-keepclassmembers class * extends androidx.work.CoroutineWorker {
public (android.content.Context,androidx.work.WorkerParameters);
}
Это мой модуль рукоятки для одного из параметров WorkManagers. То же самое и с параметрами внутри ProvideBleServiceModule
@Module
@InstallIn(SingletonComponent::class)
object BleServiceModuleModule {
@Singleton
@Provides
fun provideBleServiceModule(
@ApplicationContext context: Context,
sharedPrefHelper: CommonsSharedPrefHelper,
bluetoothAdapterStateModule: BluetoothAdapterStateModule,
userDbService: UserDbService,
bleEvents: BleEvents,
): BleServiceModule = BleServiceModule(
context,
sharedPrefHelper,
bluetoothAdapterStateModule,
userDbService,
bleEvents,
)
}
Подробнее здесь: https://stackoverflow.com/questions/778 ... parameters
NoSuchMethodException, создаваемое HiltWorker с дополнительными параметрами ⇐ Android
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
FatalException, создаваемое библиотекой protobuf при создании экземпляра сообщения
Anonymous » » в форуме C++ - 0 Ответы
- 20 Просмотры
-
Последнее сообщение Anonymous
-