kotlin 使用BiometricPrompt的设备凭据(PIN)会破坏呼叫活动

j2cgzkjk  于 2023-04-07  发布在  Kotlin
关注(0)|答案(1)|浏览(134)

我们目前在一些Android设备上面临着奇怪的BiometricPrompt行为。这个问题与品牌/制造商无关,因为它可以在一些三星设备上工作,但在其他设备上则不行。

问题

为了批准用户对其帐户进行的某些交易,我们要求她使用设备凭据或生物特征来验证自己。在后台,我们使用BiometricPrompt。我们面临的问题是,在调用BiometricPrompt.authenticate()方法后,立即显示设备凭据屏幕(特别是仅PIN),我们的底层活动被破坏(中间只有几毫秒),我们输入PIN码,点击继续,设备凭据屏幕消失,我们看到设备本身的主屏幕.该问题只发生在用户已将PIN设置为设备凭据.模式和生物识别工作正常.此外,PIN在其他一些Android设备上工作.

代码

下面是我们调用的代码:

suspend fun authenticate(
    activity: FragmentActivity
): AuthenticationResult = suspendCoroutine { continuation ->
    @Suppress("DEPRECATION") // We are aware of this. If possible we use the "Modern" approach.
    val promptInfo = BiometricPrompt.PromptInfo.Builder()
        .setTitle(activity.getString(R.string.biometric_prompt_title))
        .setDeviceCredentialAllowed(true)
        .build()
    activity.createBiometricPrompt(continuation).authenticate(promptInfo)
}

我们的authenticate()方法在主线程上使用Dispatchers.Main调用。
下面是createBiometricPrompt()方法的代码:

fun FragmentActivity.createBiometricPrompt(continuation: Continuation<AuthenticationResult>): BiometricPrompt {
    return BiometricPrompt(
        this,
        object : BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                continuation.resume(AuthenticationResult.Error(errorCode, errString))
            }

            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                continuation.resume(AuthenticationResult.Succeeded(result))
            }

            override fun onAuthenticationFailed() {
                Timber.i("onAuthenticationFailed")
            }
        }
    )
}

由于我们正在向注册为第二个因素的设备发送推送,因此我们创建了一个PendingIntent来呈现交易活动。我们使用以下代码创建活动:

fun createPendingIntent(context: Context, transaction: Transaction): PendingIntent =
    Intent(context, TransactionActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NO_HISTORY or
                Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
        putExtra(INTENT_EXTRA_TRANSACTION_APPROVAL, transaction)
    }.let { intent ->
        val flags = PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        PendingIntent.getActivity(context, 1484, intent, flags)
    }

我们在登录过程中使用相同的代码。我们的代码在所有设备上都没有任何问题。因此,我猜我们可能在创建Intent/PendingIntent时做错了什么?🤷
你们谁知道是什么导致了我们的问题?

已尝试解决方案

  • 添加日志到我们的活动。可以确认我们的活动的onDestroy被调用
  • 已从Intent中删除所有flags
p5cysglq

p5cysglq1#

我刚刚找到了解决问题的方法。关于Start an Activity from a Notification的文档,他们建议使用TaskStackBuilder来构建PendingIntent。使用TaskStackBuilder,当PIN屏幕显示时,我们的活动不会被杀死。

相关问题