Firebase 电话身份验证在活动恢复时显示异常:“短信代码已过期。请重新发送验证码以重试。”

Rid*_*dhi 6 android firebase firebase-authentication

我正在使用 firebase 电话身份验证来验证电话号码。但是,当我尝试切换任何其他应用程序或在进程进行的过程中(即在进程开始和结束之间)按下主页按钮时,会出现问题即使 OTP 正确且时间未过期,它也始终显示FirebaseAuthInvalidCredentialsException以下消息。

短信代码已过期。请重新发送验证码以重试。

以前,我发现当活动在过程中暂停并恢复时,身份验证过程(验证 OTP 或发送 OTP)停止并且不会恢复。因此,为此,我手动启动了该过程。现在,该过程开始但它总是返回上述异常。

通过使用resumeProcess()on Resume 中的方法。现在,receiveOTP()工作正常。但是OTP的验证仍然存在问题。(正如上面所解释的)。

我正在使用对话框进行电话身份验证。

我为电话身份验证和问题编写的代码如下。

手动恢复在暂停时停止的过程。我resumeProcess()onResume().

在片段的 onResume()

@Override
public void onResume() {
    super.onResume();
    if (phoneAuthDialog != null && phoneAuthDialog.isShowing()) {
        phoneAuthDialog.resumeProcess();
    }
}
Run Code Online (Sandbox Code Playgroud)

而且,在对话...

public void resumeProcess(){
    if(isReceivingOtpSms){
        receiveOtp(phoneNumber,null);
    }

    if(isVerifyingOtp){
        verifyOtp();
    }
}
Run Code Online (Sandbox Code Playgroud)

用于接收 OTP。

private void receiveOtp(String phoneNumber,PhoneAuthProvider.ForceResendingToken forceResendingToken) {
    if (connectionDetector != null && connectionDetector.isConnectingToInternet()) {

        setPhoneVerificationCallback();
        isReceivingOtpSms =true;
        showProgress();

        //for receiving otp for the first time
        if(forceResendingToken==null){
            PhoneAuthProvider.getInstance().verifyPhoneNumber(
                    phoneNumber,        // Phone number to verify
                    60,                 // Timeout duration
                    TimeUnit.SECONDS,   // Unit of timeout
                    activity,               // Activity (for callback binding)
                    mCallbacks);        // OnVerificationStateChangedCallbacks
        }

        //for resending otp
        else {
            PhoneAuthProvider.getInstance().verifyPhoneNumber(
                    phoneNumber,        // Phone number to verify
                    60,                 // Timeout duration
                    TimeUnit.SECONDS,   // Unit of timeout
                    activity,               // Activity (for callback binding)
                    mCallbacks,          // OnVerificationStateChangedCallbacks
                    forceResendingToken);
        }

    } else
        showToast(activity, Constants.MESSAGE_NO_CONNECTION);
}
Run Code Online (Sandbox Code Playgroud)

setPhoneVerificationCallback()方法用于处理验证回调。

private void setPhoneVerificationCallback() {
    mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
        @Override
        public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
            hideProgress();               //to hide progressbar.
            isReceivingOtpSms=false;
            //some ui process....
            verifyCredentials(phoneAuthCredential); 
        }

        @Override
        public void onCodeAutoRetrievalTimeOut(String s) {
            super.onCodeAutoRetrievalTimeOut(s);
        }

        @Override
        public void onVerificationFailed(FirebaseException e) {
            e.printStackTrace();
            hideProgress();
            isReceivingOtpSms=false;

            if (e instanceof FirebaseNetworkException) {
                showToast(activity, activity.getString(R.string.err_noconnection_message));
            } else if (e instanceof FirebaseAuthInvalidCredentialsException) {
                e.printStackTrace();
                showToast(activity, "Incorrect phone number format. Check your mobile number and country code twice.");
            } else {
                showToast(activity, e.getMessage());
            }
        }

        @Override
        public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
            super.onCodeSent(verificationId, forceResendingToken);
            hideProgress();
            isReceivingOtpSms=false;
            PhoneAuthDialogRefactored.this.verificationId = verificationId;
            PhoneAuthDialogRefactored.this.forceResendingToken = forceResendingToken;

            //some ui process ...

            showToast(activity, "code sent to your number");
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

verifyOTP()方法

private void verifyOtp() {
    String otp = etOtp.getText().toString().trim();
    if (otp.length() == 6) {

        if (connectionDetector != null && connectionDetector.isConnectingToInternet()) {
            if (verificationId != null) {
                Log.e("Verification ID : ", verificationId);
                PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, otp.trim());
                verifyCredentials(credential);
            } else {
                showToast(activity, "Please wait for a while! the code is not sent yet.");
            }
        } else {
            showToast(activity, activity.getString(R.string.err_noconnection_message));
        }
    } else {
        errOtp.setVisibility(View.VISIBLE);
        errOtp.setText(activity.getString(R.string.err_required));
    }
}
Run Code Online (Sandbox Code Playgroud)

verifyCredentials方法验证 OTP 是否正确。

private void verifyCredentials(PhoneAuthCredential credential) {
    isVerifyingOtp=true;
    showProgress();

    if (activity != null) {
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(activity, task -> {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        hideProgress();
                        isVerifyingOtp=false;
                        //some ui process...

                    } else {
                        // Sign in failed, display a message and update the UI
                        hideProgress();
                        isVerifyingOtp=false;
                        Log.w("Phone authentication", "signInWithCredential:failure", task.getException());
                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            // The verification code entered was invalid

                            Exception exception=task.getException();
                            if(exception.getMessage().equals("The sms code has expired. Please re-send the verification code to try again.")){
                                showToast(activity,exception.getMessage());
                                errOtp.setVisibility(View.VISIBLE);
                                errOtp.setText(activity.getString(R.string.err_expired_code));
                            }
                            else {
                                errOtp.setVisibility(View.VISIBLE);
                                errOtp.setText(activity.getString(R.string.err_wrong_otp));
                            }
                        }
                    }
                });
    }
}
Run Code Online (Sandbox Code Playgroud)

请帮助我解决这个问题,如果我的问题不清楚,请随时提问。主要问题是

当即使 OTP 正确且时间未过期。它仍然显示代码已过期。只有在我们暂停并恢复活动时才会发生这种情况。在一个过程中。(我的意思是在一个过程的中间,验证过程已经开始,但在它完成验证过程(成功或失败)之前,我按下切换到另一个应用程序并返回到应用程序)

小智 1

@Riddhi我认为问题在于您在验证时发送的verificationId。代码看起来不错。我之前发送验证ID时遇到了同样的问题。

public class OtpVerificationActivity extends AppCompatActivity implements View.OnClickListener {

    EditText mobileNumber,otpText;
    Button sendOtp,verifyOtp;
    FirebaseAuth mAuth;
    String codeSent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_otp_verification);

        mobileNumber = findViewById(R.id.mobileNumber);
        otpText = findViewById(R.id.otpText);
        sendOtp = findViewById(R.id.sendOtp);
        verifyOtp = findViewById(R.id.verifyOtp);

        sendOtp.setOnClickListener(this);
        verifyOtp.setOnClickListener(this);

        mAuth = FirebaseAuth.getInstance();

    }

    @Override
    public void onClick(View v) {

        switch (v.getId()){

            case R.id.sendOtp:

                sendVerificationCode();
                break;

            case R.id.verifyOtp:

                verifyCodeSent();
                break;
        }

    }

    private void verifyCodeSent() {

        String code = otpText.getText().toString();
        PhoneAuthCredential credential = PhoneAuthProvider.getCredential(codeSent,code);
        signInWithPhoneAuthCredential(credential);
    }

    private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            Log.d("verifyCode", "signInWithCredential:success");

                            Toast.makeText(OtpVerificationActivity.this, "Successful", Toast.LENGTH_SHORT).show();
                            //FirebaseUser user = task.getResult().getUser();
                            // ...
                        } else {
                            // Sign in failed, display a message and update the UI
                            Log.w("verifyCode", "signInWithCredential:failure", task.getException());
                            if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                                // The verification code entered was invalid
                                Toast.makeText(OtpVerificationActivity.this, ""+task.getException().getMessage(), Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                });
    }

    private void sendVerificationCode() {

        String phoneNumber = mobileNumber.getText().toString();

        if (phoneNumber.isEmpty()){
            mobileNumber.setError("mobile number cannot be empty");
            mobileNumber.requestFocus();
        }

        if (phoneNumber.length() < 10){
            mobileNumber.setError("Please enter a valid phone");
            mobileNumber.requestFocus();
        }

        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                "+91" + phoneNumber,        // Phone number to verify (I hardcoded it only for Indian Mobile numbers).
                60,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                this,               // Activity (for callback binding)
                mCallbacks);
    }

    PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
        @Override
        public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {

        }

        @Override
        public void onVerificationFailed(FirebaseException e) {

        }

        @Override
        public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
            super.onCodeSent(s, forceResendingToken);

            codeSent = s;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

我希望这个对你有用。您检查完此代码后可以回复我吗?