【发布时间】:2019-07-14 22:56:29
【问题描述】:
我正在使用 Firebase 电话身份验证来验证电话号码。但是,当我尝试切换任何其他应用程序或只是按下主页按钮时会出现问题,该过程正在进行中,即在该过程开始和结束之间。即使OTP 正确且时间未过期,它始终显示 FirebaseAuthInvalidCredentialsException 和以下消息。
短信代码已过期。请重新发送验证码重试。
以前,我发现当活动暂停并在进程中间恢复时,身份验证过程(验证 OTP 或发送 OTP )停止并且不会恢复。因此,为此,我手动启动了该过程。现在,该过程开始了,但它总是返回上述异常。
通过在简历中使用resumeProcess() 方法。现在,receiveOTP() 工作正常。但是OTP的验证仍然存在问题。 (如上文所述)。
我正在使用对话框进行电话身份验证。
我为电话验证和问题编写的代码如下。
手动恢复进程,该进程在暂停时停止。我在onResume() 中使用resumeProcess() 方法。
在片段的onResume()
@Override
public void onResume() {
super.onResume();
if (phoneAuthDialog != null && phoneAuthDialog.isShowing()) {
phoneAuthDialog.resumeProcess();
}
}
而且,在对话框中...
public void resumeProcess(){
if(isReceivingOtpSms){
receiveOtp(phoneNumber,null);
}
if(isVerifyingOtp){
verifyOtp();
}
}
用于接收 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);
}
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");
}
};
}
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));
}
}
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));
}
}
}
});
}
}
请帮助我解决这个问题,如果我的问题不清楚,请随时提出。主要问题是
即使 OTP 正确且时间未过期。它仍然显示代码已过期。并且仅在我们暂停并恢复活动时才会发生。在一个过程的中间。 (我的意思是在一个过程的中间,验证过程已经开始,但在它完成验证过程(成功或失败)之前,我按下切换到另一个应用程序并返回应用程序)
【问题讨论】:
-
如果您继续进行相同的活动并输入代码会怎样?
-
@RahulKhurana 它运行良好。在这种情况下。只有当我们最小化应用程序或按下主页按钮或类似情况时才会出现问题。
-
只需检查 mCallbacks 以查看它是否为空。如果它不为空,则不要重置它
-
@RahulKhurana 没用。
-
你能把你的完整代码贴在这里吗?
标签: android firebase firebase-authentication