amplitude / Amplitude-Kotlin

Amplitude Kotlin SDK
MIT License
27 stars 10 forks source link

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

Closed samarthagarwal closed 6 months ago

samarthagarwal commented 6 months ago

Summary

We are building a keyboard for Android and we have integrated the Amplitude Kotlin SDK in the keyboard. The keyboard service initializes when the device is turned on and the user needs to enter the password (if they have a password set up). Since the keyboard service initialized and the device is not unlocked, we get the following crash.

Fatal Exception: java.lang.IllegalStateException: SharedPreferences in credential encrypted storage are not available until after user is unlocked
       at android.app.ContextImpl.getSharedPreferences(ContextImpl.java:589)
       at android.app.ContextImpl.getSharedPreferences(ContextImpl.java:574)
       at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:217)
       at com.amplitude.android.utilities.AndroidStorage.<init>(AndroidStorage.kt:35)
       at com.amplitude.android.utilities.AndroidStorageProvider.getStorage(AndroidStorageProvider.java:121)
       at com.amplitude.core.StorageProvider$DefaultImpls.getStorage$default(StorageProvider.java:37)
       at com.amplitude.core.Amplitude$build$built$1.invokeSuspend(Amplitude.kt:102)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
       at java.lang.Thread.run(Thread.java:1012)

Is there a way to change the default storage for Amplitude? If not, are there any other solutions? As a last resort, we will have delay the SDK initialization until the device is unlocked.

Mercy811 commented 6 months ago

Hi @samarthagarwal, thanks for choosing Amplitude. You can replace the default storage by setting config.storageProvider = YourCustomStorage() when init. For example

class CustomStorage: StorageProvider{
    override fun getStorage(amplitude: com.amplitude.core.Amplitude, prefix: String?): Storage {
        TODO("Not yet implemented")
    }

}

amplitude = Amplitude(
    Configuration(
        apiKey = AMPLITUDE_API_KEY,
        context = applicationContext,
        storageProvider = customStorage()
    )
)

Here is the docs.