PIE Only: SharedPreferences IllegalStateException

I only found one or two puzzle pieces which may be helpful: the source code of ContextImpl has two IllegalStateExceptions, one of them from a method getSharedPreferences() in line 426-454.

"SharedPreferences in credential encrypted storage are not available until after user is unlocked"

This IllegalStateException is thrown from an if block which is executed only if the target SDK version is Oreo or higher

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");
     }
} 

Searching the web for isCredentialProtectedStorage() led me to FileBasedEncryption.

Since I don't know the details of your app's workflow I can only suggest to make sure that the app does not try to access a secured file while the device is locked.


You must be trying to access SharedPreferences after LOCKED_BOOT_COMPLETED and before BOOT_COMPLETED which isn't allowed since Nougat / API 24 unless you migrate your preferences to the Device Protected Storage.

2 options here:

  • Either remove the LOCKED_BOOT_COMPLETED action and the android:directBootAware flag from your Broadcast Receiver. This way your app will wait till BOOT_COMPLETED (when the user unlocks the device) before trying to access SharedPreferences.
  • Or if you do need to access SharedPreferences after LOCKED_BOOT_COMPLETED and before BOOT_COMPLETED, make sure your migrate your preferences to the Device Protected Storage and use Device Protected Storage Context when calling getSharedPreferences().

More details on the second option in the official docs: Support Direct Boot mode

Tags:

Android