仅PIE:SharedPreferences IllegalStateException

Pse*_*328 6 android

尝试初始化共享首选项单例类时,我们收到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)

Mak*_*nov 7

您必须尝试在 Nougat / API 24 之后访问SharedPreferencesLOCKED_BOOT_COMPLETED除非BOOT_COMPLETED您将首选项迁移到设备保护存储。

这里有 2 个选项:

  • 从广播接收器中删除LOCKED_BOOT_COMPLETED操作和标志。android:directBootAware这样,您的应用程序将等到BOOT_COMPLETED(当用户解锁设备时)再尝试访问SharedPreferences
  • 或者,如果您确实需要SharedPreferences在之后LOCKED_BOOT_COMPLETED和之前进行访问BOOT_COMPLETED,请确保将您的首选项迁移到设备保护存储并在调用时使用设备保护存储上下文getSharedPreferences()

有关官方文档中第二个选项的更多详细信息:支持直接启动模式


0X0*_*gar 5

我只找到了一两个可能有用的拼图:ContextImpl源代码有两个IllegalStateExceptions,其中一个来自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

由于我不知道您的应用程序工作流程的详细信息,因此我只能建议确保应用程序不会在设备锁定时尝试访问受保护的文件。