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

如何在手机登录Fragment中用Integrity Api替代废弃的SafetyNet Api

用Google Play Integrity API替换废弃SafetyNet API实现手机号登录

问题背景

上传应用到Google Play时收到警告,提示手机号登录Fragment依赖已废弃的SafetyNet API,已经通过Gradle排除该依赖:

configurations.all {
    exclude group: 'com.google.android.gms', module: 'play-services-safetynet'
}

需要替换原有基于SafetyNet的Firebase手机号验证逻辑为Integrity API。

解决方案

1. 添加Play Integrity API依赖

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

// Groovy
implementation 'com.google.android.gms:play-services-integrity:1.2.0'

// Kotlin DSL
implementation("com.google.android.gms:play-services-integrity:1.2.0")

2. 生成Integrity Token并传入Firebase Auth

Firebase Phone Auth现在需要搭配Integrity Token完成验证,核心是在请求发送验证码前获取Token,再传入验证配置。

2.1 在ViewModel中实现Token获取逻辑

修改PhoneLoginViewModel,添加获取Integrity Token的方法:

import com.google.android.gms.tasks.Tasks
import com.google.android.play.core.integrity.IntegrityManagerFactory
import com.google.android.play.core.integrity.IntegrityTokenRequest

class PhoneLoginViewModel : ViewModel() {
    // 原有代码保持不变...

    fun fetchIntegrityToken(): String? {
        return try {
            val integrityManager = IntegrityManagerFactory.create(getApplication())
            // 生成随机Nonce,建议每次请求都用不同值,防止重放攻击
            val randomNonce = java.util.UUID.randomUUID().toString()
            val request = IntegrityTokenRequest.builder()
                .setNonce(randomNonce)
                .build()
            val tokenResponse = Tasks.await(integrityManager.requestIntegrityToken(request))
            tokenResponse.token()
        } catch (e: Exception) {
            // 捕获异常:比如网络错误、Play服务版本过低、设备无Google服务等
            e.printStackTrace()
            null
        }
    }
}

注意:Nonce必须是随机生成的唯一字符串,不要固定值,避免安全风险。

2.2 修改Fragment中的验证码发送逻辑

在sendCode和sendCodeAgain方法中,先获取Integrity Token,再传入PhoneAuthOptions:

private fun sendCode() {
    val phoneNumber = binding.phoneNumber.value
    val numberWithCode = requireContext().addCountryCode(phoneNumber)
    model.onSendCode(numberWithCode) {
        val integrityToken = model.fetchIntegrityToken()
        val optionsBuilder = PhoneAuthOptions.newBuilder(Firebase.auth)
            .setPhoneNumber(numberWithCode)
            .setTimeout(60L, TimeUnit.SECONDS)
            .setActivity(requireActivity())
            .setCallbacks(callbacks)

        // 成功获取Token则传入
        integrityToken?.let {
            optionsBuilder.setGooglePlayServicesToken(it)
        }

        PhoneAuthProvider.verifyPhoneNumber(optionsBuilder.build())
    }
}

private fun sendCodeAgain() {
    model.onSendCodeAgain {
        val integrityToken = model.fetchIntegrityToken()
        val optionsBuilder = PhoneAuthOptions.newBuilder(Firebase.auth)
            .setPhoneNumber(model.phoneNumber.value!!)
            .setTimeout(60L, TimeUnit.SECONDS)
            .setActivity(requireActivity())
            .setCallbacks(callbacks)

        // 成功获取Token则传入
        integrityToken?.let {
            optionsBuilder.setGooglePlayServicesToken(it)
        }

        PhoneAuthProvider.verifyPhoneNumber(optionsBuilder.build())
    }
}

3. 处理Token获取失败的情况

如果获取Integrity Token失败,建议:

  • 弹出提示告知用户检查Google Play服务状态、网络连接
  • 若设备无Google Play服务,可考虑提供其他登录方式(比如邮箱登录)
  • 不要跳过验证直接发送验证码,避免账号安全风险

4. 验证修改效果

编译应用后测试手机号登录流程,确保验证码能正常发送和验证;重新上传应用到Google Play,确认不再收到SafetyNet相关警告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 07:01:08