尝试初始化共享首选项单例类时,我们收到IllegalStageException,但我不知道是什么原因引起的。
有人可以告诉我这可能是什么原因吗?
注意:这仅在Pie上发生
这是来自Google Play控制台的报告(崩溃未在Crashlytics中显示):
java.lang.RuntimeException:
at android.app.ActivityThread.handleBindApplication (ActivityThread.java:5876)
at android.app.ActivityThread.access$1100 (ActivityThread.java:199)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1650)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:193)
at android.app.ActivityThread.main (ActivityThread.java:6669)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:858)
Caused by: java.lang.IllegalStateException:
at android.app.ContextImpl.getSharedPreferences (ContextImpl.java:419)
at android.app.ContextImpl.getSharedPreferences (ContextImpl.java:404)
at android.content.ContextWrapper.getSharedPreferences (ContextWrapper.java:174)
at com.nbc.news.utils.SharedPreferences.<init> (SharedPreferences.java:27)
at com.nbc.news.utils.SharedPreferences.init (SharedPreferences.java:44)
at com.nbc.news.NbcNews.onCreate (NbcNews.java:122)
at android.app.Instrumentation.callApplicationOnCreate (Instrumentation.java:1154)
at android.app.ActivityThread.handleBindApplication (ActivityThread.java:5871)
Run Code Online (Sandbox Code Playgroud)
这是初始化代码:
private android.content.SharedPreferences sharedPreferences;
private static SharedPreferences instance;
private SharedPreferences(Context context) {
Context appContext = context.getApplicationContext();
sharedPreferences = appContext.getSharedPreferences(context.getString(R.string.database_name), Context.MODE_PRIVATE); // <- this is line #27
}
public android.content.SharedPreferences getPreference(){
return sharedPreferences;
}
public static SharedPreferences getInstance() {
if (instance == null) {
throw new RuntimeException("SharedPreferences must be initialized with context prior to use");
}
return instance;
}
public static void init(Context context) {
if (instance == null) {
instance = new SharedPreferences(context); // <- this is line #44
}
}
Run Code Online (Sandbox Code Playgroud)
您必须尝试在 Nougat / API 24 之后访问SharedPreferences
,LOCKED_BOOT_COMPLETED
除非BOOT_COMPLETED
您将首选项迁移到设备保护存储。
这里有 2 个选项:
LOCKED_BOOT_COMPLETED
操作和标志。android:directBootAware
这样,您的应用程序将等到BOOT_COMPLETED
(当用户解锁设备时)再尝试访问SharedPreferences
。SharedPreferences
在之后LOCKED_BOOT_COMPLETED
和之前进行访问BOOT_COMPLETED
,请确保将您的首选项迁移到设备保护存储并在调用时使用设备保护存储上下文getSharedPreferences()
。有关官方文档中第二个选项的更多详细信息:支持直接启动模式
我只找到了一两个可能有用的拼图:ContextImpl的源代码有两个IllegalStateException
s,其中一个来自getSharedPreferences()
第 426-454 行的方法。
“凭证加密存储中的 SharedPreferences 在用户解锁之前不可用”
这IllegalStateException
是从if
仅当目标 SDK 版本为 Oreo 或更高版本时才执行的块中抛出的
if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O) {
if (isCredentialProtectedStorage()
&&
!getSystemService(UserManager.class).isUserUnlockingOrUnlocked(UserHandle.myUserId())) {
throw new IllegalStateException("SharedPreferences in credential encrypted "
+ "storage are not available until after user is unlocked");
}
}
Run Code Online (Sandbox Code Playgroud)
在网上搜索isCredentialProtectedStorage()
让我找到FileBasedEncryption。
由于我不知道您的应用程序工作流程的详细信息,因此我只能建议确保应用程序不会在设备锁定时尝试访问受保护的文件。