在 background.systemjob.SystemJobService.onCreate 中调用 WorkManagerImpl.getInstance 导致 java.lang.IllegalStateException
Call WorkManagerImpl.getInstance in background.systemjob.SystemJobService.onCreate caused java.lang.IllegalStateException
我们正在使用以下 WorkManager 库
def work_version = "2.1.0-beta01"
implementation "androidx.work:work-runtime:$work_version"
我们的 Application
class 正在修改如下,以便与 WorkManager
一起使用
public class WeNoteApplication extends MultiDexApplication implements DefaultLifecycleObserver, Configuration.Provider {
private static WeNoteApplication me;
@Override
public void onCreate() {
super.onCreate();
me = this;
...
}
public static WeNoteApplication instance() {
return me;
}
@NonNull
@Override
public Configuration getWorkManagerConfiguration() {
return new Configuration.Builder()
.build();
}
}
我们不在AndroidManifest.xml
中添加任何WorkManager
相关代码。我们完全依赖 Default initialization
这就是我们构建的方式WorkManager
public static WorkManager getWorkManager() {
WeNoteApplication weNoteApplication = WeNoteApplication.instance();
return WorkManager.getInstance(weNoteApplication);
}
上述函数在 4 个不同的地方被调用
Activity
Fragment
BroadcastReceiver
IntentService
我们仍然在生产环境中收到以下崩溃日志。它发生在 Android 7.1、Android 8.1、Android 9(到目前为止)
java.lang.RuntimeException:
at android.app.ActivityThread.handleCreateService (ActivityThread.java:3265)
at android.app.ActivityThread.-wrap5 (ActivityThread.java)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1598)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:241)
at android.app.ActivityThread.main (ActivityThread.java:6274)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:776)
Caused by: java.lang.IllegalStateException:
at androidx.work.impl.WorkManagerImpl.getInstance (WorkManagerImpl.java:142)
at androidx.work.impl.background.systemjob.SystemJobService.onCreate (SystemJobService.java:53)
at android.app.ActivityThread.handleCreateService (ActivityThread.java:3255)
at android.app.ActivityThread.-wrap5 (ActivityThread.java)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1598)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:241)
at android.app.ActivityThread.main (ActivityThread.java:6274)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:776)
正如您在崩溃中看到的那样,崩溃起源于 WorkManager
内部,而不是我们的应用程序。
WorkManagerImpl
/**
* Retrieves the singleton instance of {@link WorkManagerImpl}.
*
* @param context A context for on-demand initialization.
* @return The singleton instance of {@link WorkManagerImpl}
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static @NonNull WorkManagerImpl getInstance(@NonNull Context context) {
synchronized (sLock) {
WorkManagerImpl instance = getInstance();
if (instance == null) {
Context appContext = context.getApplicationContext();
if (appContext instanceof Configuration.Provider) {
initialize(
appContext,
((Configuration.Provider) appContext).getWorkManagerConfiguration());
instance = getInstance(appContext);
} else {
throw new IllegalStateException("WorkManager is not initialized properly. You "
+ "have explicitly disabled WorkManagerInitializer in your manifest, "
+ "have not manually called WorkManager#initialize at this point, and "
+ "your Application does not implement Configuration.Provider.");
}
有2种可能IllegalStateException
appContext
为空。 (怎么可能为空?)
appContext
没有实现 Configuration.Provider
(但我们已经在 WeNoteApplication
中实现了 Configuration.Provider
?)
为了弄清楚上下文是如何从 SystemJobService
传递到 WorkManagerImpl
,我们看一下代码
androidx.work.impl.background.systemjob.SystemJobService.onCreate
- https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/work/workmanager/src/main/java/androidx/work/impl/background/systemjob/SystemJobService.java#53
系统作业服务
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@RequiresApi(WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL)
public class SystemJobService extends JobService implements ExecutionListener {
private static final String TAG = Logger.tagWithPrefix("SystemJobService");
private WorkManagerImpl mWorkManagerImpl;
private final Map<String, JobParameters> mJobParameters = new HashMap<>();
@Override
public void onCreate() {
super.onCreate();
mWorkManagerImpl = WorkManagerImpl.getInstance(getApplicationContext());
乍一看还不错。但是,为什么我已经在我的Application
中实现了Configuration.Provider
,但为什么WorkManagerImpl
不能获得Configuration.Provider
呢?是因为我用的是MultiDexApplication
吗?
发现
在SystemJobService中,由于auto-backup原因,它可以期望null,并且能够从WorkManagerImpl.getInstance容忍null。
@Override
public void onCreate() {
super.onCreate();
mWorkManagerImpl = WorkManagerImpl.getInstance(getApplicationContext());
if (mWorkManagerImpl == null) {
// This can occur if...
// 1. The app is performing an auto-backup. Prior to O, JobScheduler could erroneously
// try to send commands to JobService in this state (b/32180780). Since neither
// Application#onCreate nor ContentProviders have run, WorkManager won't be
// initialized. In this case, we should ignore all JobScheduler commands and tell it
// to retry.
但是,当前的 WorkManagerImpl.getInstance(Context context)
实现是,它永远不会 return null 而是抛出 IllegalStateException
.
这2个SystemJobService.onCreate
逻辑和WorkManagerImpl.getInstance
逻辑不冲突吗?
问题跟踪器
这是一个错误。本周晚些时候将在 WorkManager 2.1.0-rc01
中提供修复。
我们正在使用以下 WorkManager 库
def work_version = "2.1.0-beta01"
implementation "androidx.work:work-runtime:$work_version"
我们的 Application
class 正在修改如下,以便与 WorkManager
public class WeNoteApplication extends MultiDexApplication implements DefaultLifecycleObserver, Configuration.Provider {
private static WeNoteApplication me;
@Override
public void onCreate() {
super.onCreate();
me = this;
...
}
public static WeNoteApplication instance() {
return me;
}
@NonNull
@Override
public Configuration getWorkManagerConfiguration() {
return new Configuration.Builder()
.build();
}
}
我们不在AndroidManifest.xml
中添加任何WorkManager
相关代码。我们完全依赖 Default initialization
这就是我们构建的方式WorkManager
public static WorkManager getWorkManager() {
WeNoteApplication weNoteApplication = WeNoteApplication.instance();
return WorkManager.getInstance(weNoteApplication);
}
上述函数在 4 个不同的地方被调用
Activity
Fragment
BroadcastReceiver
IntentService
我们仍然在生产环境中收到以下崩溃日志。它发生在 Android 7.1、Android 8.1、Android 9(到目前为止)
java.lang.RuntimeException:
at android.app.ActivityThread.handleCreateService (ActivityThread.java:3265)
at android.app.ActivityThread.-wrap5 (ActivityThread.java)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1598)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:241)
at android.app.ActivityThread.main (ActivityThread.java:6274)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:776)
Caused by: java.lang.IllegalStateException:
at androidx.work.impl.WorkManagerImpl.getInstance (WorkManagerImpl.java:142)
at androidx.work.impl.background.systemjob.SystemJobService.onCreate (SystemJobService.java:53)
at android.app.ActivityThread.handleCreateService (ActivityThread.java:3255)
at android.app.ActivityThread.-wrap5 (ActivityThread.java)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1598)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:241)
at android.app.ActivityThread.main (ActivityThread.java:6274)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:776)
正如您在崩溃中看到的那样,崩溃起源于 WorkManager
内部,而不是我们的应用程序。
WorkManagerImpl
/**
* Retrieves the singleton instance of {@link WorkManagerImpl}.
*
* @param context A context for on-demand initialization.
* @return The singleton instance of {@link WorkManagerImpl}
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static @NonNull WorkManagerImpl getInstance(@NonNull Context context) {
synchronized (sLock) {
WorkManagerImpl instance = getInstance();
if (instance == null) {
Context appContext = context.getApplicationContext();
if (appContext instanceof Configuration.Provider) {
initialize(
appContext,
((Configuration.Provider) appContext).getWorkManagerConfiguration());
instance = getInstance(appContext);
} else {
throw new IllegalStateException("WorkManager is not initialized properly. You "
+ "have explicitly disabled WorkManagerInitializer in your manifest, "
+ "have not manually called WorkManager#initialize at this point, and "
+ "your Application does not implement Configuration.Provider.");
}
有2种可能IllegalStateException
appContext
为空。 (怎么可能为空?)appContext
没有实现Configuration.Provider
(但我们已经在WeNoteApplication
中实现了Configuration.Provider
?)
为了弄清楚上下文是如何从 SystemJobService
传递到 WorkManagerImpl
,我们看一下代码
androidx.work.impl.background.systemjob.SystemJobService.onCreate
- https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/work/workmanager/src/main/java/androidx/work/impl/background/systemjob/SystemJobService.java#53
系统作业服务
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@RequiresApi(WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL)
public class SystemJobService extends JobService implements ExecutionListener {
private static final String TAG = Logger.tagWithPrefix("SystemJobService");
private WorkManagerImpl mWorkManagerImpl;
private final Map<String, JobParameters> mJobParameters = new HashMap<>();
@Override
public void onCreate() {
super.onCreate();
mWorkManagerImpl = WorkManagerImpl.getInstance(getApplicationContext());
乍一看还不错。但是,为什么我已经在我的Application
中实现了Configuration.Provider
,但为什么WorkManagerImpl
不能获得Configuration.Provider
呢?是因为我用的是MultiDexApplication
吗?
发现
在SystemJobService中,由于auto-backup原因,它可以期望null,并且能够从WorkManagerImpl.getInstance容忍null。
@Override
public void onCreate() {
super.onCreate();
mWorkManagerImpl = WorkManagerImpl.getInstance(getApplicationContext());
if (mWorkManagerImpl == null) {
// This can occur if...
// 1. The app is performing an auto-backup. Prior to O, JobScheduler could erroneously
// try to send commands to JobService in this state (b/32180780). Since neither
// Application#onCreate nor ContentProviders have run, WorkManager won't be
// initialized. In this case, we should ignore all JobScheduler commands and tell it
// to retry.
但是,当前的 WorkManagerImpl.getInstance(Context context)
实现是,它永远不会 return null 而是抛出 IllegalStateException
.
这2个SystemJobService.onCreate
逻辑和WorkManagerImpl.getInstance
逻辑不冲突吗?
问题跟踪器
这是一个错误。本周晚些时候将在 WorkManager 2.1.0-rc01
中提供修复。