仅PIE:SharedPreferences IllegalStateException

时间:2018-12-17 21:11:08

标签: 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)

这是初始化代码:

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
        }
    }

3 个答案:

答案 0 :(得分:3)

我只发现了一个或两个拼图碎片,这可能会有所帮助:source code of ContextImpl有两个IllegalStateException,其中一个来自426-454行中的方法getSharedPreferences()

  

“直到用户解锁后,凭据加密存储中的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");
     }
} 

在网络上搜索isCredentialProtectedStorage()导致我进入FileBasedEncryption

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

答案 1 :(得分:1)

您必须尝试在SharedPreferences之后和LOCKED_BOOT_COMPLETED之前访问BOOT_COMPLETED,这是自牛轧糖/ API 24以来不允许的,除非您将首选项迁移到设备保护的存储。

这里有2个选项:

  • 从广播接收器中删除LOCKED_BOOT_COMPLETED操作和android:directBootAware标志。这样,您的应用将等到BOOT_COMPLETED(当用户解锁设备时),然后再尝试访问SharedPreferences
  • 或者,如果您确实需要在SharedPreferences之后和LOCKED_BOOT_COMPLETED之前访问BOOT_COMPLETED,请确保将偏好设置迁移到设备保护存储,并在调用{{ 1}}。

有关官方文档中第二个选项的更多详细信息:Support Direct Boot mode

答案 2 :(得分:0)

尝试将 App Center 初始化从 Application 类移动到 MainActivity。这会帮助你。我们必须在应用准备好(BootCompleted)后才调用 Sharepreference。