移除SafetyNet后Flutter firebase_auth手机号验证崩溃问题求助
我的Flutter应用使用firebase_auth(v4.2.1)插件实现手机号验证,原本运行正常。但收到Google Play的「迁移Google SafetyNet Attestation API」警告,经查该插件依赖SafetyNet。参考方案在Android配置中排除SafetyNet依赖:
dependencies { implementation platform('com.google.firebase:firebase-bom:30.3.2') implementation 'com.google.firebase:firebase-auth' } configurations.all { exclude group: 'com.google.android.gms', module: 'play-services-safetynet' }
移除后,调用手机号验证时应用崩溃,报错如下:
E/AndroidRuntime(15766): java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/safetynet/SafetyNet; E/AndroidRuntime(15766): at com.google.firebase.auth.internal.zzf.zza(com.google.firebase:firebase-auth@@21.1.0:2) E/AndroidRuntime(15766): at com.google.firebase.auth.FirebaseAuth.zzI(com.google.firebase:firebase-auth@@21.1.0:26) E/AndroidRuntime(15766): at com.google.firebase.auth.PhoneAuthProvider.verifyPhoneNumber(com.google.firebase:firebase-auth@@21.1.0:2) E/AndroidRuntime(15766): at io.flutter.plugins.firebase.auth.PhoneNumberVerificationStreamHandler.onListen(PhoneNumberVerificationStreamHandler.java:180) E/AndroidRuntime(15766): at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onListen(EventChannel.java:218) E/AndroidRuntime(15766): at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onMessage(EventChannel.java:197) E/AndroidRuntime(15766): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295) E/AndroidRuntime(15766): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319) E/AndroidRuntime(15766): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(D8$$SyntheticClass) E/AndroidRuntime(15766): at android.os.Handler.handleCallback(Handler.java:751) E/AndroidRuntime(15766): at android.os.Handler.dispatchMessage(Handler.java:95) E/AndroidRuntime(15766): at android.os.Looper.loop(Looper.java:154) E/AndroidRuntime(15766): at android.app.ActivityThread.main(ActivityThread.java:6077) E/AndroidRuntime(15766): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(15766): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) E/AndroidRuntime(15766): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) E/AndroidRuntime(15766): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.safetynet.SafetyNet" on path: DexPathList[[zip file "/data/app/.../base.apk"],nativeLibraryDirectories=[/data/app/.../lib/x86, /data/app/.../base.apk!/lib/x86, /system/lib, /vendor/lib]] E/AndroidRuntime(15766): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) E/AndroidRuntime(15766): at java.lang.ClassLoader.loadClass(ClassLoader.java:380) E/AndroidRuntime(15766): at java.lang.ClassLoader.loadClass(ClassLoader.java:312) E/AndroidRuntime(15766): ... 16 more
疑问:该SafetyNet解决方案是否正确?若正确,如何修复崩溃问题?或SafetyNet问题的最优解决方案是什么?
1. 直接排除SafetyNet的方案不可行
你用的排除依赖方法之所以崩溃,是因为firebase-auth:21.1.0版本(对应BOM 30.3.2)仍直接依赖SafetyNet,代码里硬调用了SafetyNet类,直接排除必然触发ClassNotFound错误。这个方案本身就是错误的,不能这么操作。
2. 最优解决路径:迁移到Play Integrity API
Google已废弃SafetyNet Attestation API,官方推荐迁移到Play Integrity API,这是合规且能彻底解决Play商店警告的方案,具体步骤如下:
步骤1:升级firebase_auth和Firebase BOM版本
firebase_auth v4.2.1对应的Android Auth版本太老,还在依赖SafetyNet。需要升级到支持Play Integrity的版本:
- 将firebase_auth升级到v4.12.0+(或更高稳定版)
- 同步升级Firebase BOM到32.0.0+(对应支持Play Integrity的Auth版本)
修改Flutter项目的pubspec.yaml:
dependencies: firebase_auth: ^4.12.0 # 其他Firebase依赖建议同步升级以保持版本兼容
步骤2:配置Android端依赖
升级后,firebase_auth会自动切换到Play Integrity,无需手动排除SafetyNet。修改android/app/build.gradle:
dependencies { implementation platform('com.google.firebase:firebase-bom:32.0.0') implementation 'com.google.firebase:firebase-auth' # 可选:如果BOM未自动引入,手动添加Play Integrity依赖 implementation 'com.google.android.play:integrity:1.2.0' }
注意:删除之前添加的排除SafetyNet的配置,新版本Auth已不再依赖SafetyNet。
步骤3:在Firebase控制台启用Play Integrity API
- 打开Firebase控制台并进入你的项目
- 左侧菜单选择「Build」→「Play Integrity」
- 点击「启用API」,按照指引完成配置(需关联Google Play开发者账号)
步骤4:验证流程无需代码改动
升级firebase_auth后,原有PhoneAuthProvider.verifyPhoneNumber的调用逻辑完全不用修改,插件内部已切换到Play Integrity验证,对Flutter层完全透明。
3. 临时过渡方案(不推荐)
如果暂时无法升级依赖,可临时采用以下方式避免Play商店警告,但这只是权宜之计,最终仍需升级:
- 保留SafetyNet依赖,不要排除
- 在Firebase控制台启用Play Integrity API,同时保留SafetyNet配置
内容的提问来源于stack exchange,提问作者user2609021

