react-native-keychain: Android UI freezing on launch
Hi
I’m experiencing problems with react-native-keychain on Android which unfortunately forces me to disable the library for Android (on iOS it works flawlessly). Sometimes the UI freezes for several seconds shortly after launching the app. This happens when simply importing the library without even using it, as in the following code:
// App.js
import React, {Component} from 'react';
import {TextInput,} from 'react-native';
import 'react-native-keychain';
export default class KeychainExample extends Component {
render() {
return (
<TextInput
style={{flex: 1}}
/>
);
}
}
As you can see in the screen recording below, the UI freezes and ignores any input for several seconds shortly after reloading the app.

Logcat shows a couple of errors, but I don’t know if they are related:
2020-03-15 18:15:01.464 19347-19347/com.keychainexample E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
2020-03-15 18:15:01.464 19347-19347/com.keychainexample E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
2020-03-15 18:15:02.585 19347-19397/com.keychainexample D/OpenGLRenderer: endAllActiveAnimators on 0x7e77934600 (AlertController$RecycleListView) with handle 0x7e885a9f60
2020-03-15 18:15:02.603 19347-20435/com.keychainexample D/DecorView: onWindowFocusChangedFromViewRoot hasFocus: true, DecorView@7311aa4[MainActivity]
2020-03-15 18:15:02.757 19347-19347/com.keychainexample D/ReactNative: ReactInstanceManager.onJSBundleLoadedFromServer()
2020-03-15 18:15:02.758 19347-19347/com.keychainexample D/ReactNative: ReactInstanceManager.recreateReactContextInBackground()
2020-03-15 18:15:02.758 19347-19347/com.keychainexample D/ReactNative: ReactInstanceManager.runCreateReactContextOnNewThread()
2020-03-15 18:15:02.758 19347-19347/com.keychainexample D/ReactNative: ReactInstanceManager.tearDownReactContext()
2020-03-15 18:15:02.761 19347-19347/com.keychainexample D/ReactNative: CatalystInstanceImpl.destroy() start
2020-03-15 18:15:02.762 19347-19347/com.keychainexample W/unknown:ReactNative: Packager connection already open, nooping.
2020-03-15 18:15:02.766 19347-32636/com.keychainexample D/ReactNative: ReactInstanceManager.createReactContext()
2020-03-15 18:15:02.766 19347-32574/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTEventEmitter.receiveEvent([3,"topBlur",{"target":3}])
2020-03-15 18:15:02.766 19347-32574/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTEventEmitter.receiveEvent([3,"topEndEditing",{"text":"","target":3}])
2020-03-15 18:15:02.771 19347-32637/com.keychainexample V/RNKeychainManager: warming up started at 229678618570351
2020-03-15 18:15:02.771 19347-32636/com.keychainexample D/ReactNative: Initializing React Xplat Bridge.
2020-03-15 18:15:02.772 19347-32636/com.keychainexample D/ReactNative: Initializing React Xplat Bridge before initializeBridge
--------- beginning of system
2020-03-15 18:15:02.773 19347-32637/com.keychainexample D/RNKeychainManager: Probe cipher storage: CipherStorageFacebookConceal
2020-03-15 18:15:02.773 19347-32637/com.keychainexample D/RNKeychainManager: Probe cipher storage: CipherStorageKeystoreAesCbc
2020-03-15 18:15:02.775 19347-32636/com.keychainexample D/ReactNative: Initializing React Xplat Bridge after initializeBridge
2020-03-15 18:15:02.776 19347-32636/com.keychainexample D/ReactNative: CatalystInstanceImpl.runJSBundle()
2020-03-15 18:15:02.776 19347-32639/com.keychainexample D/ReactNative: ReactInstanceManager.setupReactContext()
2020-03-15 18:15:02.776 19347-32639/com.keychainexample D/ReactNative: CatalystInstanceImpl.initialize()
2020-03-15 18:15:02.778 19347-32639/com.keychainexample D/ReactNative: ReactInstanceManager.attachRootViewToInstance()
2020-03-15 18:15:02.788 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.art.ARTGroupViewManager
2020-03-15 18:15:02.788 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.art.ARTGroupShadowNode
2020-03-15 18:15:02.789 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.art.ARTShapeViewManager
2020-03-15 18:15:02.789 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.art.ARTShapeShadowNode
2020-03-15 18:15:02.790 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.art.ARTTextViewManager
2020-03-15 18:15:02.790 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.art.ARTTextShadowNode
2020-03-15 18:15:02.791 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.checkbox.ReactCheckBoxManager
2020-03-15 18:15:02.792 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.uimanager.LayoutShadowNode
2020-03-15 18:15:02.793 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.picker.ReactDialogPickerManager
2020-03-15 18:15:02.795 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.drawer.ReactDrawerLayoutManager
2020-03-15 18:15:02.795 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.picker.ReactDropdownPickerManager
2020-03-15 18:15:02.796 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.scroll.ReactHorizontalScrollViewManager
2020-03-15 18:15:02.797 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.scroll.ReactHorizontalScrollContainerViewManager
2020-03-15 18:15:02.797 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.progressbar.ReactProgressBarViewManager
2020-03-15 18:15:02.799 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.progressbar.ProgressBarShadowNode
2020-03-15 18:15:02.799 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.scroll.ReactScrollViewManager
2020-03-15 18:15:02.801 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.slider.ReactSliderManager
2020-03-15 18:15:02.801 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.slider.ReactSliderManager$ReactSliderShadowNode
2020-03-15 18:15:02.802 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.switchview.ReactSwitchManager
2020-03-15 18:15:02.803 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.switchview.ReactSwitchManager$ReactSwitchShadowNode
2020-03-15 18:15:02.803 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.swiperefresh.SwipeRefreshLayoutManager
2020-03-15 18:15:02.804 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.art.ARTSurfaceViewManager
2020-03-15 18:15:02.804 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.art.ARTSurfaceViewShadowNode
2020-03-15 18:15:02.804 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.text.frescosupport.FrescoBasedReactTextInlineImageViewManager
2020-03-15 18:15:02.805 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.text.frescosupport.FrescoBasedReactTextInlineImageShadowNode
2020-03-15 18:15:02.805 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.image.ReactImageManager
2020-03-15 18:15:02.806 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.modal.ReactModalHostManager
2020-03-15 18:15:02.807 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.modal.ModalHostShadowNode
2020-03-15 18:15:02.807 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.text.ReactRawTextManager
2020-03-15 18:15:02.807 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.text.ReactRawTextShadowNode
2020-03-15 18:15:02.808 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.textinput.ReactTextInputManager
2020-03-15 18:15:02.810 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.textinput.ReactTextInputShadowNode
2020-03-15 18:15:02.812 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.text.ReactTextViewManager
2020-03-15 18:15:02.813 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.text.ReactTextShadowNode
2020-03-15 18:15:02.813 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.view.ReactViewManager
2020-03-15 18:15:02.813 19347-19452/com.keychainexample D/ReactNative: CatalystInstanceImpl.destroy() end
2020-03-15 18:15:02.815 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.viewpager.ReactViewPagerManager
2020-03-15 18:15:02.815 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.text.ReactVirtualTextViewManager
2020-03-15 18:15:02.815 19347-32639/com.keychainexample W/unknown:ViewManagerPropertyUpdater: Could not find generated setter for class com.facebook.react.views.text.ReactVirtualTextShadowNode
2020-03-15 18:15:02.841 19347-19347/com.keychainexample W/unknown:ReactNative: Packager connection already open, nooping.
2020-03-15 18:15:02.889 19347-32637/com.keychainexample D/RNKeychainManager: Probe cipher storage: CipherStorageKeystoreRsaEcb
2020-03-15 18:15:03.148 19347-32638/com.keychainexample I/ReactNativeJS: Running "KeychainExample" with {"rootTag":311}
2020-03-15 18:15:03.247 19347-19672/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.247 19347-19449/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.248 19347-19864/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.248 19347-19828/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.249 19347-20528/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.249 19347-20458/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.249 19347-20415/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.249 19347-19958/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.250 19347-20621/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.250 19347-20591/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.250 19347-20561/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.251 19347-27463/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.252 19347-20687/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.253 19347-27632/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.253 19347-27591/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.254 19347-27549/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.254 19347-27510/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.254 19347-27864/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.254 19347-27667/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.255 19347-27646/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.255 19347-28207/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.255 19347-28057/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.256 19347-27935/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.256 19347-27900/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.256 19347-28771/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.257 19347-28615/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.257 19347-28571/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.257 19347-28799/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.257 19347-28872/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.258 19347-28966/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.258 19347-32597/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-start\",\"body\":{\"isInitialUpdate\":true}}","type":"text","id":1}])
2020-03-15 18:15:03.259 19347-19672/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.259 19347-19449/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.259 19347-19864/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.259 19347-19864/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.260 19347-19828/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.260 19347-19828/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.261 19347-20458/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.261 19347-20458/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.261 19347-20528/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.261 19347-20528/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.261 19347-19958/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.261 19347-19958/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.262 19347-20621/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.262 19347-20621/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.262 19347-20415/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.262 19347-20415/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.262 19347-20591/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.262 19347-20591/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.263 19347-20561/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.263 19347-20561/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.263 19347-27463/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.263 19347-27463/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.263 19347-20687/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.263 19347-20687/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.264 19347-27632/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.264 19347-27632/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.264 19347-27591/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.264 19347-27591/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.264 19347-27549/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.265 19347-27549/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.265 19347-27510/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.265 19347-27510/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.265 19347-27864/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.265 19347-27864/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.265 19347-27667/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.266 19347-27667/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.266 19347-27646/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.266 19347-27646/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.266 19347-28207/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.266 19347-28207/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.266 19347-28057/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.267 19347-28057/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.267 19347-27935/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.267 19347-27935/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.267 19347-27900/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.267 19347-27900/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.267 19347-28771/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.268 19347-28771/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.268 19347-28615/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.268 19347-28615/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.269 19347-28571/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.269 19347-28571/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.269 19347-28799/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.269 19347-28799/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.270 19347-28872/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.270 19347-28872/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.271 19347-28966/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.271 19347-28966/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.271 19347-32597/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update\",\"body\":{\"revisionId\":\"e18a6388909dd3d1\",\"isInitialUpdate\":true,\"added\":[],\"modified\":[],\"deleted\":[]}}","type":"text","id":1}])
2020-03-15 18:15:03.271 19347-32597/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.271 19347-19672/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.272 19347-19449/com.keychainexample W/unknown:ReactNative: Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(["websocketMessage",{"data":"{\"type\":\"update-done\"}","type":"text","id":1}])
2020-03-15 18:15:03.677 19347-19347/com.keychainexample E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
2020-03-15 18:15:03.682 19347-19347/com.keychainexample I/chatty: uid=10440(com.keychainexample) identical 2 lines
2020-03-15 18:15:03.682 19347-19347/com.keychainexample E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
2020-03-15 18:15:16.947 19347-32637/com.keychainexample D/RNKeychainManager: Selected storage: CipherStorageKeystoreRsaEcb
2020-03-15 18:15:16.966 19347-32637/com.keychainexample W/CipherStorageBase: StrongBox security storage is not available.
android.security.keystore.StrongBoxUnavailableException: Failed to generate key pair
at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.generateKeystoreKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:511)
at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.generateKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:470)
at java.security.KeyPairGenerator$Delegate.generateKeyPair(KeyPairGenerator.java:727)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreRsaEcb.generateKey(CipherStorageKeystoreRsaEcb.java:256)
at com.oblador.keychain.cipherStorage.CipherStorageBase.tryGenerateStrongBoxSecurityKey(CipherStorageBase.java:444)
at com.oblador.keychain.cipherStorage.CipherStorageBase.generateKeyAndStoreUnderAlias(CipherStorageBase.java:391)
at com.oblador.keychain.KeychainModule.internalWarmingBestCipher(KeychainModule.java:167)
at com.oblador.keychain.KeychainModule.lambda$NuQDyTTfZc67dTNiVeEDbYNRCJw(Unknown Source:0)
at com.oblador.keychain.-$$Lambda$KeychainModule$NuQDyTTfZc67dTNiVeEDbYNRCJw.run(Unknown Source:2)
at java.lang.Thread.run(Thread.java:764)
Caused by: android.security.KeyStoreException: No StrongBox available
at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.generateKeystoreKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:511)
at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.generateKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:470)
at java.security.KeyPairGenerator$Delegate.generateKeyPair(KeyPairGenerator.java:727)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreRsaEcb.generateKey(CipherStorageKeystoreRsaEcb.java:256)
at com.oblador.keychain.cipherStorage.CipherStorageBase.tryGenerateStrongBoxSecurityKey(CipherStorageBase.java:444)
at com.oblador.keychain.cipherStorage.CipherStorageBase.generateKeyAndStoreUnderAlias(CipherStorageBase.java:391)
at com.oblador.keychain.KeychainModule.internalWarmingBestCipher(KeychainModule.java:167)
at com.oblador.keychain.KeychainModule.lambda$NuQDyTTfZc67dTNiVeEDbYNRCJw(Unknown Source:0)
at com.oblador.keychain.-$$Lambda$KeychainModule$NuQDyTTfZc67dTNiVeEDbYNRCJw.run(Unknown Source:2)
at java.lang.Thread.run(Thread.java:764)
2020-03-15 18:15:17.065 19347-19347/com.keychainexample W/InputMethodManager: IME died: com.touchtype.swiftkey/com.touchtype.KeyboardService
android.os.DeadObjectException
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:1179)
at com.android.internal.view.IInputMethodSession$Stub$Proxy.updateSelection(IInputMethodSession.java:224)
at android.view.inputmethod.InputMethodManager.updateSelection(InputMethodManager.java:1672)
at android.widget.Editor.sendUpdateSelection(Editor.java:1749)
at android.widget.Editor.finishBatchEdit(Editor.java:1589)
at android.widget.Editor.endBatchEdit(Editor.java:1563)
at android.widget.TextView.endBatchEdit(TextView.java:8068)
at com.android.internal.widget.EditableInputConnection.endBatchEdit(EditableInputConnection.java:78)
at com.android.internal.widget.EditableInputConnection.closeConnection(EditableInputConnection.java:91)
at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:541)
at com.android.internal.view.IInputConnectionWrapper.dispatchMessage(IInputConnectionWrapper.java:225)
at com.android.internal.view.IInputConnectionWrapper.closeConnection(IInputConnectionWrapper.java:211)
at android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper.deactivate(InputMethodManager.java:600)
at android.view.inputmethod.InputMethodManager.startInputInner(InputMethodManager.java:1334)
at android.view.inputmethod.InputMethodManager$H.handleMessage(InputMethodManager.java:538)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6898)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2020-03-15 18:15:17.104 19347-19347/com.keychainexample E/unknown:ReactNative: Got DOWN touch before receiving UP or CANCEL from last gesture
2020-03-15 18:15:20.067 19347-32637/com.keychainexample V/RNKeychainManager: warming up takes: 17296 ms
Tested on OnePlus 5T (A5010) running OxygenOS 9.0.10.
react-native info:
System:
OS: macOS 10.15.3
CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Memory: 3.50 GB / 32.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 10.16.0 - /usr/local/bin/node
Yarn: 1.19.2 - ~/.yarn/bin/yarn
npm: 6.13.4 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
Android SDK:
API Levels: 19, 23, 24, 25, 26, 27, 28, 29
Build Tools: 23.0.1, 23.0.3, 25.0.1, 25.0.2, 25.0.3, 26.0.0, 26.0.1, 26.0.3, 27.0.3, 28.0.0, 28.0.0, 28.0.2, 28.0.3, 29.0.2
System Images: android-19 | Google APIs ARM EABI v7a, android-19 | Google APIs Intel x86 Atom, android-25 | Google APIs Intel x86 Atom, android-27 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
IDEs:
Android Studio: 3.6 AI-192.7142.36.36.6241897
Xcode: 11.3.1/11C504 - /usr/bin/xcodebuild
npmPackages:
react: 16.9.0 => 16.9.0
react-native: 0.61.2 => 0.61.2
npmGlobalPackages:
react-native-cli: 2.0.1
react-native-create-library: 3.1.2
react-native-nemid: 1.13.0
Let me know if you need any more information!
@OleksandrKucherenko I know you have put a lot of effort into this version of the library, especially the Android part. Maybe you have encountered similar issues?
Best regards Jens
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 13
- Comments: 63 (22 by maintainers)
@john-y-pazekha Sorry for the late response - I just became a dad, so I’ve been afk for three weeks 😄
Here are the results:
@oblador Are there any plans for an official fix for this on the native side of this lib?
Still on 6.1.1 here and was also experiencing UI freeze on devices. It was locking the whole phone up. I found the culprit. It was related to the RSA cipher. It was taking a long time to load on devices especially ones with biometrics. As I was not using biometrics part of the keychain package and supporting API 23+, I decided to patch the build. The patch commented out the facebook (yuck) and RSA option. I now only work with the AES cipher and it super fast again. (Phew. I was blaming the size of the android bundle and thought Android was slow at parsing the bundle on load).
NB: This was a solution for my app as I’m only concerned about AES cipher. It will not work for everyone The patch package. https://www.npmjs.com/package/patch-package
The patch code:
The technical part: pre-warming the RSA cipher (calculating that vast 2048 bit prime number) plus when the exception handler took an eternity to roll up the stack and then the next step was to re-run the pre-warming with the biometrics enabled.
@SudoPlz Yes. Patch the package as suggested above to remove the initial freeze, or force the use of AES by using the STORAGE_TYPE option. The problem is that the AES option is incompatible with the user interaction requirement (biometric or password).
Under the hood
To improve on my previous comment, here is what actually happens. A secure hardware generates the keys: either a secret symmetric key (AES) or a private-public key pair (RSA) in our case. That AES key or RSA public key is used to encrypt your item value and store the encrypted result on a public file. The security lies in the fact that the secure hardware makes sure that only your app can retrieve the key. You can also specify options so that the secure hardware reveals the key only after the user has authenticated with biometrics or password.
The problem on Android is that if you specify that option for an AES key, to be able to encrypt your entry value with the newly created key, you would have to authenticate. So the user experience would be weird: the user types his password, then has to use his fingerprint or device password right after so the app can save the password… That is the reason why, I suppose, the authors of the library decided that in order to enable this option, the best way was to generate an RSA key pair. Indeed, the public key of the RSA key pair is always available… since it is public.
Then came the drawback that generating an RSA key pair is a random process, so it sometimes takes a long time. I suppose the authors of the library thought the problem was the time it took to load the library, and decided to add a warming up mechanism, which is of course not a solution and makes the problem even worse.
There are several alternatives here: 1/ keeping the current RSA implementation and accepting the key generation time randomness (maybe adding a message for the user) 2/ using an AES key without the biometric/password requirement at the hardware level while still requiring it programmatically (perfect UX, but lower theoretical security though still very good) 3/ using an AES key with the biometric/password requirement at the hardware level (highest security) with a UX compromise (requiring authentication right after key generation)
In any case, the warming up mechanism should be removed.
I have implemented 2/ on my project with a simplified api. I can send you the code if you wish.
With RN 0.64 and keychain 7.0.0 The warning in log is still there for android
Hello, I have taken a great inspiration from this module to write my own (because I like to understand stuff). Thank you by the way for your work !
I didn’t investigate this issue in particular, but I was surprised when I saw the warming up mechanism in the code. This mechanism generates a “warmingUp” key which has no other purpose.
I don’t know if you are aware, but if the chosen algorithm is RSA, it will take a lot of time to generate a key pair. Just try to generate an RSA key pair in your terminal with ssh-keygen, you’ll see that takes a noticeable time. Generating an RSA key pair is a random process. The algorithm tests a lot of random numbers until it finds a prime one that’s big enough and then derives the private and the public key from it. So the generation can be quick or really long. It both depends on the speed of your processor and on luck.
I believe this slowness issue will be solved once you remove your warmup mechanism as @cladjules commented. And from my understanding of the library, it has no other side effect.
You could also use the AES algorithm instead of the RSA one. It’s as secure for this use case. (But generating a key in the Keystore with the option “setUserAuthenticationRequired(true)” and immediately use it to encrypt the user password will fail if the user does not authenticate in between. I guess that’s precisely why the RSA algorithm was used in the first place).
I hope this helps.
I don’t know if I did anything wrong with my tests, but selecting AES with my current config which now looks like this:
seems to have worked without any hustle. Saving the credentials went down from 1 second to 0.1 second and I can use biometrics just fine.
@SudoPlz I think you should read the native code. I promise it will help you.
It’s the whole logic. But
.setUserAuthenticationRequired(true)is the line that creates the secure-hardware requirement to use biometrics or device password. It won’t be enough to change juste this line though.@SudoPlz yes
=== EDIT
…assuming you use the lib as is. If you rewrite the lib from scratch, AES can work.
=== EDIT 2 Wrong! as shown in below comment
@SudoPlz
About FB vs RSA vs AES
You can find a lot more details on the web about these two algorithms.
The lib chooses the algorithm for you depending on your parameters if you don’t specify it.
About your use case
Your NO_BIOMETRICS_CONFIG should not specify the storage type to let the lib decide for you. I can’t remember exactly how the code decides, but I think it won’t use RSA unless you specify the biometric requirement. (But I’m not sure)
In the case of your RAW_CREDS_CONFIG, my solution 2/ is fine. Biometrics is not really a security improvement anyways, so let’s consider it simply as a a means to improve the UX. Here is the code I use in my project: https://github.com/giregk/react-native-simple-keychain. The api is a bit different though. Do read the native code, it will help you.
Experiencing the same issue on our app as well. Managed to work around the issue by disabling autolinking and adding the non warmed up module to my app.
Would be nice if the library would support loading it without necessarily performing the warmup on start, and then allow developers to explicitly control when to perform the warmup with some
warmup()function.For anyone wanting to do a similar workaround, these are roughly the changes I did.
react-native.config.js: Disable autolinkingsettings.gradle: Add the projectapp/build.gradle: Add the dependencyColdKeychaingPackage.java: Separate non-warmupping packageMainApplication.java: Add the cold keychain packageCongrats 🥳
for background thread it can be ok to be a little slower, but not 28 seconds… this is tooo long
Since a concern was expressed about safety of this APK, I would like to assure you gentlemen that this APK is not malicious. It requests no permissions so it cannot harm your system.
Alternatively, you can clone the source from this repo and run it in Android Studio.
@jenskuhrjorgensen @Nullabl3 @cladjules @maherzaidoune @pwneth Please use either way to produce the log. Without this information we won’t be able to reproduce the issue.
Well yes, as i’m using RSA ,i didn’t need to add Facebook || AES. The last screenshot (just edited my answer), i just needed to create an instance of Cipher , that reduce the warming up time from 20s to 2s (Huawei y7 pro)
yep… but that a complete module warmup… it triggers maximum things that’s are in the module to force java load classes and initialize them. I think you can investigate deeper with android studio profiler and see which method takes the most of the time.
low level crypto/keystores api itself is very slow… I have no idea why it so