Как создать обработчик внутри потока, который не вызвал Looper.prepare() в мобильном приложении xamarin
У меня есть мобильное приложение с аутентификацией по отпечатку пальца, которое использует фреймворк xamarin. До сих пор все работало хорошо на всех устройствах, кроме Samsung Note 8. При попытке отладки этого устройства я получаю исключение Java.Lang.RuntimeException: не могу создать обработчик внутри потока, который не вызвал Looper.prepare(). Я понятия не имею, что это значит и как это исправить, потому что он хорошо работает с другими устройствами. Это дает исключение для строки keyGen.Init(keyGenSpec)
static readonly string KEY_NAME = "YYYYYYY";
static readonly string KEYSTORE_NAME = "AndroidKeyStore";
static readonly string KEY_ALGORITHM = KeyProperties.KeyAlgorithmAes;
static readonly string BLOCK_MODE = KeyProperties.BlockModeCbc;
static readonly string ENCRYPTION_PADDING = KeyProperties.EncryptionPaddingPkcs7;
static readonly string TRANSFORMATION = KEY_ALGORITHM + "/" +
BLOCK_MODE + "/" +
ENCRYPTION_PADDING;
readonly KeyStore _keystore;
public CryptoObjectHelper()
{
_keystore = KeyStore.GetInstance(KEYSTORE_NAME);
_keystore.Load(null);
}
public FingerprintManagerCompat.CryptoObject BuildCryptoObject()
{
Cipher cipher = CreateCipher();
return new FingerprintManagerCompat.CryptoObject(cipher);
}
Cipher CreateCipher(bool retry = true)
{
IKey key = GetKey();
Cipher cipher = Cipher.GetInstance(TRANSFORMATION);
try
{
cipher.Init(CipherMode.EncryptMode, key);
}
catch (KeyPermanentlyInvalidatedException e)
{
_keystore.DeleteEntry(KEY_NAME);
if (retry)
{
CreateCipher(false);
}
else
{
throw new Exception("Could not create the cipher for fingerprint authentication.", e);
}
}
return cipher;
}
IKey GetKey()
{
if (!_keystore.IsKeyEntry(KEY_NAME))
{
CreateKey();
}
IKey secretKey = _keystore.GetKey(KEY_NAME, null);
return secretKey;
}
void CreateKey()
{
KeyGenerator keyGen = KeyGenerator.GetInstance(KeyProperties.KeyAlgorithmAes, KEYSTORE_NAME);
KeyGenParameterSpec keyGenSpec =
new KeyGenParameterSpec.Builder(KEY_NAME, KeyStorePurpose.Encrypt | KeyStorePurpose.Decrypt)
.SetBlockModes(BLOCK_MODE)
.SetEncryptionPaddings(ENCRYPTION_PADDING)
.SetUserAuthenticationRequired(true)
.Build();
keyGen.Init(keyGenSpec);
keyGen.GenerateKey();
}
2 ответа
Не видя больше кода, трудно сказать, что происходит. Похоже, ваш код выполняется в фоновом потоке. Вы можете попробовать добавить android.os.Looper.Prepare()
как первая строка внутри CreateKey()
, Надеюсь, что это работает.
Я понятия не имею, что это значит и как это исправить, потому что он хорошо работает с другими устройствами. Это дает исключение для строки keyGen.Init(keyGenSpec)
Это похожая проблема здесь. И, как предложено, вы можете перехватить исключение и инициализировать ключ в потоке пользовательского интерфейса в соответствии с failedOnNote8
:
failedOnNote8=false;
try{
keyGen.Init(keyGenSpec);
}catch (Exception e) {
if(e.getMessage() != null && e.getMessage().equals("Can't create handler inside thread that has not called Looper.prepare()")) {
failedOnNote8 = true;
}
}
if(failedOnNote8)
{
//try to init the key on UI Thread.
}