WorkManager 在 Application#onCreate 中尝试将唯一周期性工作加入队列时崩溃

5

我希望使用Dagger 2与WorkManager一起注入worker的依赖。我按照这篇文章来实现设置。设置的一部分是按需初始化。为了实现它,我将以下行添加到我的清单文件中:

    <provider
        android:name="androidx.work.impl.WorkManagerInitializer"
        android:authorities="${applicationId}.workmanager-init"
        android:exported="false"
        tools:node="remove" />

我让我的应用程序类实现了Configuration.Provider接口,代码如下:

    @NonNull
    @Override
    public Configuration getWorkManagerConfiguration() {
        return new Configuration.Builder().setMinimumLoggingLevel(Log.DEBUG).setWorkerFactory(delegatingWorkerFactory).build();
    }

Dagger的设置按照预期工作。

然而,我遇到了以下问题:在中,我会排队唯一的定期任务,并且在应用程序的第一次安装中,此操作总是失败并显示以下错误:

java.lang.IllegalStateException: The file system on the device is in a bad state. WorkManager cannot access the app's internal data store.
    at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:115)
    at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
    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:764)
 Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database
    at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:211)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:195)
    at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:503)
    at android.database.sqlite.SQLiteConnectionPool.tryAcquireNonPrimaryConnectionLocked(SQLiteConnectionPool.java:987)
    at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:693)
    at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:378)
    at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
    at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:586)
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
    at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
    at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
    at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1408)
    at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1383)
    at androidx.sqlite.db.framework.FrameworkSQLiteDatabase.query(FrameworkSQLiteDatabase.java:161)
    at androidx.room.RoomDatabase.query(RoomDatabase.java:328)
    at androidx.room.util.DBUtil.query(DBUtil.java:83)
    at androidx.work.impl.model.PreferenceDao_Impl.getLongValue(PreferenceDao_Impl.java:70)
    at androidx.work.impl.utils.PreferenceUtils.getNeedsReschedule(PreferenceUtils.java:96)
    at androidx.work.impl.utils.ForceStopRunnable.shouldRescheduleWorkers(ForceStopRunnable.java:187)
    at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:88)
    at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91) 
    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:764) 

如果我将在Application#onCreate中排队的代码移到应用程序生命周期的后期(例如某个活动),则它就不会失败。
我没有发现任何关于从Application#onCreate排队工作的限制,因此我认为它必须正常工作。我正在使用WorkManager 2.3.4和Room 2.2.5。我尝试将Room降级到2.2.2以及将WorkManager降级到几个较旧的稳定版本,但这并没有帮助。问题在不同设备和模拟器上复现,并且在不同的Android版本上都有这个问题。
我如何解决这个问题并保持在Application#onCreate中排队工作?
编辑:以下是我的工作排队方法:
workManagerProvider.get().enqueueUniquePeriodicWork(
        "Unique name",
        ExistingPeriodicWorkPolicy.REPLACE,
        request
    )

其中workManagerProviderProvider<WorkManager>。由于存在循环依赖,我无法直接访问工作管理器,因此必须从Dagger获取提供程序,然后才能使用它。 这与主题无关。


从错误中可以理解到,这是因为数据库无法打开。我认为在将工作加入Application#onCreate之前,数据库没有被初始化。 - undefined
1
@Antonio没错,但这是由WorkManager管理的数据库。所以我不知道是什么阻止了WorkManager在第一次运行时进行独占初始化。 - undefined
你能添加展示如何将工作入队的代码吗? - undefined
在你的代码中使用了Dagger2和WorkManager,它们都有自己的初始化步骤。因此最好分享一下你尝试实现它的完整示例代码,否则可以尝试在这里不使用Dagger2来使用"enqueueUniquePeriodicWork",看看是否能正常工作。 - undefined
1个回答

0
问题是由另一段代码引起的,这段代码在首次启动时擦除了应用程序的内部数据。擦除操作与WorkManager的内部数据库创建几乎同时进行。因此,在初始化过程中,WorkManager试图访问已删除的数据库文件的SQLite连接,导致崩溃发生。

2
好的,但是你是怎么修复这个问题的? - undefined
@LuizAlegria 我编写的代码不会触碰WorkManager的数据库。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接