我的应用程序广播接收器中收到 ANR。
来自谷歌控制台的日志 -
Broadcast of Intent { flg=0x14 cmp=in.medibuddy/.receivers.DailyInitHealthReceiver (has extras) }
最近我使用这个库 androidx.security:security-crypto:1.0.0 包含了 EncryptedSharedPreferences。 之后我在谷歌控制台中看到了多个与应用程序相关的ANR。 下面的日志我可以在谷歌控制台中找到。
#00 pc 000000000005589c /system/lib/libc.so (__ioctl+8)
#00 pc 0000000000022363 /system/lib/libc.so (ioctl+38)
#00 pc 000000000003d863 /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+206)
#00 pc 000000000003e339 /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+240)
#00 pc 000000000003729d /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36)
#00 pc 00000000000cacd3 /system/lib/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+82)
at android.os.BinderProxy.transactNative (Native method)
at android.os.BinderProxy.transact (Binder.java:1145)
at android.security.IKeystoreService$Stub$Proxy.exist (IKeystoreService.java:932)
at android.security.KeyStore.contains (KeyStore.java:366)
at android.security.keystore.AndroidKeyStoreSpi.engineContainsAlias (AndroidKeyStoreSpi.java:1037)
at java.security.KeyStore.containsAlias (KeyStore.java:1293)
at androidx.security.crypto.MasterKeys.keyExists (MasterKeys.java:137)
at androidx.security.crypto.MasterKeys.getOrCreate (MasterKeys.java:87)
at in.medibuddy.util.UserStore.getSecuredPref (UserStore.java:34)
at in.medibuddy.util.UserStore.getPref (UserStore.java:19)
at in.medibuddy.MediBuddyApplication.initializeFirebaseAnalytics (MediBuddyApplication.java:211)
at in.medibuddy.MediBuddyApplication.onCreate (MediBuddyApplication.java:201)
at android.app.Instrumentation.callApplicationOnCreate (Instrumentation.java:1158)
at android.app.ActivityThread.handleBindApplication (ActivityThread.java:6304)
at android.app.ActivityThread.access$1200 (ActivityThread.java:241)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1807)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:214)
at android.app.ActivityThread.main (ActivityThread.java:7156)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:975)
任何人都可以帮助我,为什么会发生这种情况?
这是因为 Android 密钥库实际上不能从主线程调用。
EncryptedSharedPreferences
使用密钥库进行加密。
那么为什么不是主线程呢?
在这个堆栈中,有一个
containsAlias
调用似乎需要一些时间。在幕后,这是执行磁盘 I/O 来搜索密钥。在较旧的(Android 12 之前的)设备上,如果设备上有很多密钥库密钥,我认为此操作可能有点麻烦。
对于 Android U,密钥库 API 现在已注释,以便如果应用程序从主线程调用密钥库 API,StrictMode 会发出警告。看起来这可能尚未公开记录,但这是可以修复的! :)
综上所述...应用程序通常不想使用
EncryptedSharedPreferences
无论如何。例如,由于 EncryptedSharedPreferences
使用密钥库加密,这意味着它们无法在出厂重置后保存或转移到其他设备(例如通过云备份)。当用户抱怨云恢复后他们丢失了设置时,这些事情有时会让开发人员感到惊讶。如果这是您在应用程序中想要的行为,那就去做吧!人们真正想要这种行为并不是非常典型。
还要考虑 Android 已经具有 文件加密。应用程序数据已使用每用户凭证进行加密。如果您的目的是数据永远不会以明文形式存在,那么为首选项添加额外的加密层不一定会改善情况。