You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中CreatePublicKeyCredentialRequest抛出PhenotypeContext未设置错误的排查修复

Passkey注册报错:Must call PhenotypeContext.setContext() first 的原因与修复方案

错误原因

这个错误源于Android CredentialManager底层依赖的Google Play Services Phenotype库未提前初始化上下文。部分定制系统或特定版本的Google Play Services设备中,Phenotype库要求必须先调用PhenotypeContext.setContext()才能正常使用相关功能,而CredentialManager的默认初始化流程未覆盖该场景,导致触发未知异常。

修复步骤

  • 提前初始化Phenotype上下文:在应用启动阶段(比如自定义Application类的onCreate方法中),传入Application级别的上下文初始化PhenotypeContext,确保全局可用。
  • 使用Application Context而非Activity Context:创建CredentialManager和调用createCredential时,改用Application Context,避免Activity生命周期变化带来的上下文失效问题。
  • 更新Google Play Services:建议用户将设备上的Google Play Services更新至最新稳定版,部分旧版本存在该初始化逻辑的bug。

代码修改示例

1. 应用启动时初始化PhenotypeContext

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // 初始化Phenotype上下文,传入Application Context
        com.google.android.libraries.phenotype.PhenotypeContext.setContext(this)
    }
}

需在AndroidManifest.xml中指定该自定义Application类:

<application
    android:name=".MyApplication"
    <!-- 其他配置 -->
    >
</application>

2. 修改registerPasskey函数使用Application Context

suspend fun registerPasskey(jsonString: String, appContext: Context): CreatePublicKeyCredentialResponse {
    // 使用Application Context创建CredentialManager实例
    val credentialManager = CredentialManager.create(appContext)

    val json = JSONObject(jsonString)

    // 原有JSON解析逻辑保持不变
    val rpName = json.getJSONObject("rp").getString("name")
    val rpId = json.getJSONObject("rp").getString("id")

    val userVerification = json.getJSONObject("authenticatorSelection").getString("userVerification")
    val requireResidentKey = json.getJSONObject("authenticatorSelection").getBoolean("requireResidentKey")
    val residentKey = json.getJSONObject("authenticatorSelection").getString("residentKey")
    val authenticatorAttachment = json.getJSONObject("authenticatorSelection").getString("authenticatorAttachment")

    val userId = json.getJSONObject("user").getString("id")
    val userName = json.getJSONObject("user").getString("name")
    val userDisplayName = json.getJSONObject("user").getString("displayName")

    val pubKeyCredParams = json.getJSONArray("pubKeyCredParams")

    val attestation = json.getString("attestation")
    val timeout = json.getLong("timeout")
    val challenge = json.getString("challenge")

    val excludeCredentials = json.getJSONArray("excludeCredentials")

    val request = CreatePublicKeyCredentialRequest(
        requestJson = JSONObject().apply {
            put("rp", JSONObject().apply {
                put("name", rpName)
                put("id", rpId)
            })
            put("user", JSONObject().apply {
                put("id", userId)
                put("name", userName)
                put("displayName", userDisplayName)
            })
            put("challenge", challenge)
            put("pubKeyCredParams", pubKeyCredParams)
            put("timeout", timeout)
            put("excludeCredentials", excludeCredentials)
            put("authenticatorSelection", JSONObject().apply {
                put("authenticatorAttachment", authenticatorAttachment)
                put("requireResidentKey", requireResidentKey)
                put("residentKey", residentKey)
                put("userVerification", userVerification)
            })
            put("attestation", attestation)
        }.toString()
    )

    // 使用Application Context调用createCredential
    return credentialManager.createCredential(appContext, request) as CreatePublicKeyCredentialResponse
}

3. 添加Phenotype库依赖(若未添加)

在模块级build.gradle(或build.gradle.kts)中添加依赖:

dependencies {
    implementation "com.google.android.libraries.phenotype:phenotype:1.2.0"
}

可根据Google Maven仓库的最新版本调整版本号。

内容的提问来源于stack exchange,提问作者jamesmungai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 23:44:54