如何在 xamarin 移动应用程序中未调用 Looper.prepare() 的线程内创建处理程序

How to create handler inside thread that has not called Looper.prepare() in xamarin mobile app

我有一个具有指纹认证的移动应用程序,它使用 xamarin 框架。到目前为止,一切都适用于除三星 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();


    }

如果不查看更多代码,很难判断发生了什么。看来您的代码是在后台线程上执行的。您可以尝试添加 android.os.Looper.Prepare() 作为 CreateKey() 中的第一行。希望有用。

I have no idea what does it mean and how to fix it because it works well with other devices. It gives exception on row keyGen.Init(keyGenSpec)

这是一个类似的问题here。按照建议,您可以捕获异常并根据 failedOnNote8:

在 UI 线程上初始化密钥
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.
}