Firebase手机号验证崩溃:无法创建PhoneAuthCredential报错
解决Firebase手机号验证时的IllegalArgumentException崩溃问题
我之前在做Firebase Phone Auth的时候也碰到过一模一样的崩溃,这个错误其实就是在创建PhoneAuthCredential时参数没传对导致的,给你梳理下问题原因和解决办法:
问题根源
报错提示的Cannot create PhoneAuthCredential without either verificationProof, sessionInfo, or temporary proof,翻译过来就是:创建PhoneAuthCredential必须提供验证凭证、会话信息或者临时证明。说白了就是你调用PhoneAuthProvider.getCredential()的时候,缺少了必填的核心参数——要么是「验证ID + 用户输入的验证码」,要么是自动验证返回的完整凭证。
具体解决步骤
1. 先确认你的验证码流程是否正确
Firebase的手机号验证分为两种场景,对应不同的凭证创建方式:
- 自动验证场景:当设备能自动读取短信验证码时,Firebase会在
onVerificationCompleted回调里直接返回一个完整的PhoneAuthCredential,你直接用这个凭证去登录就行,不需要自己再调用getCredential()。 - 手动输入验证码场景:需要先在
onCodeSent回调里拿到verificationId(验证ID),等用户输入验证码后,把verificationId和用户输入的验证码一起传给getCredential()。
2. 检查代码里的常见错误点
- 有没有在还没拿到verificationId的时候就去调用
getCredential()?比如在verifyPhoneNumber刚调用完就执行创建凭证的代码,这时候onCodeSent还没触发,verificationId是空的,肯定会报错。 - 有没有把verificationId或者验证码的变量写错?比如变量名拼写错误,导致传入了空值。
- 有没有在屏幕旋转等配置更改后丢失了verificationId?这时候需要把verificationId存在
SavedInstanceState里,避免重建Activity后变量清空。
正确代码示例
发送验证码的核心代码
// 初始化手机号验证 PhoneAuthProvider.getInstance().verifyPhoneNumber( "+1234567890", // 要验证的手机号,记得加国家区号 60, // 验证码有效期(秒) TimeUnit.SECONDS, this, // 当前Activity上下文 new PhoneAuthProvider.OnVerificationStateChangedCallbacks() { // 自动验证成功(设备自动读取短信) @Override public void onVerificationCompleted(PhoneAuthCredential credential) { // 直接用这个凭证登录 signInWithPhoneAuthCredential(credential); } // 验证失败 @Override public void onVerificationFailed(FirebaseException e) { Toast.makeText(MainActivity.this, "验证失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); } // 验证码发送成功,拿到verificationId @Override public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken token) { // 保存verificationId,等用户输入验证码后使用 mVerificationId = verificationId; mResendToken = token; Toast.makeText(MainActivity.this, "验证码已发送", Toast.LENGTH_SHORT).show(); } });
手动输入验证码后的验证代码
// 用户点击验证按钮时调用 public void onVerifyCodeClick(View view) { String userInputCode = etVerificationCode.getText().toString().trim(); if (TextUtils.isEmpty(userInputCode)) { Toast.makeText(this, "请输入验证码", Toast.LENGTH_SHORT).show(); return; } if (TextUtils.isEmpty(mVerificationId)) { Toast.makeText(this, "请先获取验证码", Toast.LENGTH_SHORT).show(); return; } // 创建凭证 PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, userInputCode); // 登录 signInWithPhoneAuthCredential(credential); } // 登录方法 private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) { FirebaseAuth.getInstance().signInWithCredential(credential) .addOnCompleteListener(this, task -> { if (task.isSuccessful()) { // 登录成功,处理逻辑 FirebaseUser user = task.getResult().getUser(); Toast.makeText(MainActivity.this, "登录成功:" + user.getPhoneNumber(), Toast.LENGTH_SHORT).show(); } else { // 登录失败,处理错误 if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) { Toast.makeText(MainActivity.this, "验证码错误", Toast.LENGTH_SHORT).show(); } } }); }
保存verificationId避免配置更改丢失
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // 保存verificationId outState.putString("VERIFICATION_ID", mVerificationId); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); // 恢复verificationId mVerificationId = savedInstanceState.getString("VERIFICATION_ID"); }
按照这个流程调整你的代码,应该就能解决这个崩溃问题啦!
内容的提问来源于stack exchange,提问作者Yara El Ashram
相关产品推荐
相关产品推荐

