如何在手机登录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
相关产品推荐
相关产品推荐

