使用Firebase,如何捕获特定异常并优雅告诉用户?例如:
FirebaseAuthInvalidCredentialsException:电子邮件地址很糟糕 格式化。
我正在使用下面的代码使用电子邮件和密码注册用户,但我不是那么高级的java。
mAuth.createUserWithEmailAndPassword(email, pwd)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
//H.toast(c, task.getException().getMessage());
Log.e("Signup Error", "onCancelled", task.getException());
} else {
FirebaseUser user = mAuth.getCurrentUser();
String uid = user.getUid();
}
}
});
答案 0 :(得分:73)
您可以在try块中抛出task.getException
返回的Exception,并捕获您正在使用的方法可能抛出的每种类型的Exception。
以下是OnCompleteListener
方法的createUserWithEmailAndPassword
示例。
if(!task.isSuccessful()) {
try {
throw task.getException();
} catch(FirebaseAuthWeakPasswordException e) {
mTxtPassword.setError(getString(R.string.error_weak_password));
mTxtPassword.requestFocus();
} catch(FirebaseAuthInvalidCredentialsException e) {
mTxtEmail.setError(getString(R.string.error_invalid_email));
mTxtEmail.requestFocus();
} catch(FirebaseAuthUserCollisionException e) {
mTxtEmail.setError(getString(R.string.error_user_exists));
mTxtEmail.requestFocus();
} catch(Exception e) {
Log.e(TAG, e.getMessage());
}
}
答案 1 :(得分:27)
除了@ pdegand59回答,我在Firebase库中发现了一些错误代码并在Android上测试(返回的错误代码)。希望这会有所帮助,问候。
("ERROR_INVALID_CUSTOM_TOKEN", "The custom token format is incorrect. Please check the documentation."));
("ERROR_CUSTOM_TOKEN_MISMATCH", "The custom token corresponds to a different audience."));
("ERROR_INVALID_CREDENTIAL", "The supplied auth credential is malformed or has expired."));
("ERROR_INVALID_EMAIL", "The email address is badly formatted."));
("ERROR_WRONG_PASSWORD", "The password is invalid or the user does not have a password."));
("ERROR_USER_MISMATCH", "The supplied credentials do not correspond to the previously signed in user."));
("ERROR_REQUIRES_RECENT_LOGIN", "This operation is sensitive and requires recent authentication. Log in again before retrying this request."));
("ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL", "An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address."));
("ERROR_EMAIL_ALREADY_IN_USE", "The email address is already in use by another account."));
("ERROR_CREDENTIAL_ALREADY_IN_USE", "This credential is already associated with a different user account."));
("ERROR_USER_DISABLED", "The user account has been disabled by an administrator."));
("ERROR_USER_TOKEN_EXPIRED", "The user\'s credential is no longer valid. The user must sign in again."));
("ERROR_USER_NOT_FOUND", "There is no user record corresponding to this identifier. The user may have been deleted."));
("ERROR_INVALID_USER_TOKEN", "The user\'s credential is no longer valid. The user must sign in again."));
("ERROR_OPERATION_NOT_ALLOWED", "This operation is not allowed. You must enable this service in the console."));
("ERROR_WEAK_PASSWORD", "The given password is invalid."));
答案 2 :(得分:8)
如果这是格式错误的电子邮件的错误代码,您应该使用((FirebaseAuthException)task.getException()).getErrorCode()
来获取错误类型并正常失败。
很遗憾,我找不到Firebase使用的错误代码列表。 触发异常一次,请相应地记下错误代码和代码。
答案 3 :(得分:8)
与firebase身份验证相关的许多例外情况。 除了@kingspeech
您应该使用((FirebaseAuthException)task.getException()).getErrorCode()
来获取类型的错误,然后在switch
中执行此操作:
private void loginUser(String email, String password) {
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
startActivity(new Intent(MainActivity.this, Main2Activity.class));
} else {
String errorCode = ((FirebaseAuthException) task.getException()).getErrorCode();
switch (errorCode) {
case "ERROR_INVALID_CUSTOM_TOKEN":
Toast.makeText(MainActivity.this, "The custom token format is incorrect. Please check the documentation.", Toast.LENGTH_LONG).show();
break;
case "ERROR_CUSTOM_TOKEN_MISMATCH":
Toast.makeText(MainActivity.this, "The custom token corresponds to a different audience.", Toast.LENGTH_LONG).show();
break;
case "ERROR_INVALID_CREDENTIAL":
Toast.makeText(MainActivity.this, "The supplied auth credential is malformed or has expired.", Toast.LENGTH_LONG).show();
break;
case "ERROR_INVALID_EMAIL":
Toast.makeText(MainActivity.this, "The email address is badly formatted.", Toast.LENGTH_LONG).show();
etEmail.setError("The email address is badly formatted.");
etEmail.requestFocus();
break;
case "ERROR_WRONG_PASSWORD":
Toast.makeText(MainActivity.this, "The password is invalid or the user does not have a password.", Toast.LENGTH_LONG).show();
etPassword.setError("password is incorrect ");
etPassword.requestFocus();
etPassword.setText("");
break;
case "ERROR_USER_MISMATCH":
Toast.makeText(MainActivity.this, "The supplied credentials do not correspond to the previously signed in user.", Toast.LENGTH_LONG).show();
break;
case "ERROR_REQUIRES_RECENT_LOGIN":
Toast.makeText(MainActivity.this, "This operation is sensitive and requires recent authentication. Log in again before retrying this request.", Toast.LENGTH_LONG).show();
break;
case "ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL":
Toast.makeText(MainActivity.this, "An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.", Toast.LENGTH_LONG).show();
break;
case "ERROR_EMAIL_ALREADY_IN_USE":
Toast.makeText(MainActivity.this, "The email address is already in use by another account. ", Toast.LENGTH_LONG).show();
etEmail.setError("The email address is already in use by another account.");
etEmail.requestFocus();
break;
case "ERROR_CREDENTIAL_ALREADY_IN_USE":
Toast.makeText(MainActivity.this, "This credential is already associated with a different user account.", Toast.LENGTH_LONG).show();
break;
case "ERROR_USER_DISABLED":
Toast.makeText(MainActivity.this, "The user account has been disabled by an administrator.", Toast.LENGTH_LONG).show();
break;
case "ERROR_USER_TOKEN_EXPIRED":
Toast.makeText(MainActivity.this, "The user\\'s credential is no longer valid. The user must sign in again.", Toast.LENGTH_LONG).show();
break;
case "ERROR_USER_NOT_FOUND":
Toast.makeText(MainActivity.this, "There is no user record corresponding to this identifier. The user may have been deleted.", Toast.LENGTH_LONG).show();
break;
case "ERROR_INVALID_USER_TOKEN":
Toast.makeText(MainActivity.this, "The user\\'s credential is no longer valid. The user must sign in again.", Toast.LENGTH_LONG).show();
break;
case "ERROR_OPERATION_NOT_ALLOWED":
Toast.makeText(MainActivity.this, "This operation is not allowed. You must enable this service in the console.", Toast.LENGTH_LONG).show();
break;
case "ERROR_WEAK_PASSWORD":
Toast.makeText(MainActivity.this, "The given password is invalid.", Toast.LENGTH_LONG).show();
etPassword.setError("The password is invalid it must 6 characters at least");
etPassword.requestFocus();
break;
}
}
}
});
}
答案 4 :(得分:7)
如果您只是想向用户显示消息,则此方法有效。简单而优雅:
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithEmail:failed", task.getException());
Toast.makeText(LoginActivity.this, "User Authentication Failed: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
似乎.getMessage()方法已经为我们将异常转换为可用的格式,我们所要做的就是向用户显示某个地方。
(这是我的第一个评论,请提出建设性的批评)
答案 5 :(得分:2)
如果要将上游消息从用户发送到云,请实施firebase回调函数onMessageSent
和onSendError
以检查上游消息的状态。在错误情况下,onSendError
会返回带有错误代码的 SendException 。
例如,如果客户端在达到20条消息限制后尝试发送更多消息,则返回 SendException#ERROR_TOO_MANY_MESSAGES。
答案 6 :(得分:2)
您可以使用steve-guidetti或pdegand59方法。我使用了steve-guidetti的方法(缺少两个例外)
对于所有可能的例外情况,请参阅以下参考。
这里有详细记载。
https://firebase.google.com/docs/reference/js/firebase.auth.Auth
搜索“createUserWithEmailAndPassword”并找到
错误代码
AUTH /电子邮件已经在使用
Thrown if there already exists an account with the given email address.
AUTH /无效的电子邮件
Thrown if the email address is not valid.
AUTH /操作不被允许
Thrown if email/password accounts are not enabled. Enable email/password accounts in the Firebase Console, under the Auth tab.
AUTH /弱密码
Thrown if the password is not strong enough.
对于所有五个例外:点击此处
https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseAuthException
在这里您可以找到5种不同类型的AuthException。 4已知直接子类和1个间接子类
您可以使用steve-guidetti或pdegand59方法。
答案 7 :(得分:2)
我尝试了另一种解决方案,但并不喜欢它们。
这个怎么样:
if (!task.isSuccessful()) {
Exception exc = task.getException();
if (exc.getMessage().contains("The email address is badly formatted.")) {
etUser.setError(getString(R.string.error_wrong_email));
etUser.requestFocus();
}
else
if (exc.getMessage().contains("There is no user record corresponding to this identifier. The user may have been deleted.")) {
etUser.setError(getString(R.string.error_user_not_exist));
etUser.requestFocus();
}
else
if (exc.getMessage().contains("The password is invalid or the user does not have a password")) {
etPass.setError(getString(R.string.error_wrong_password));
etPass.requestFocus();
}
Log.w(TAG, "signInWithEmail:failed", task.getException());
Toast.makeText(AuthActivity.this, R.string.auth_failed,
Toast.LENGTH_SHORT).show();
}
答案 8 :(得分:1)
<强> LOGIN_EXCEPTIONS 强>
FirebaseAuthException
- 与Firebase身份验证相关的常规异常。请查看错误代码和消息以获取更多详细信息。
ERROR_USER_DISABLE
D如果用户已被禁用(例如,在Firebase控制台中)
ERROR_USER_NOT_FOUND
如果用户已被删除(例如,在Firebase控制台中,或在此应用的其他实例中)
ERROR_USER_TOKEN_EXPIRED
如果用户的令牌已在后端被撤销。如果用户的凭据在另一个设备中更改(例如,在密码更改事件中),则会自动发生此情况。
ERROR_INVALID_USER_TOKEN
如果用户的令牌格式错误。在正常情况下这不应该发生。
mAuth.signInWithEmailAndPassword(login, pass)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if(task.isSuccessful())
{
}else if (task.getException() instanceof FirebaseAuthInvalidUserException) {
}else if(((FirebaseAuthException) task.getException()).getErrorCode().equals("ERROR_USER_DISABLED"))
{
}else if(((FirebaseAuthException) task.getException()).getErrorCode().equals("ERROR_USER_NOT_FOUND "))
{
}else if(((FirebaseAuthException) task.getException()).getErrorCode().equals("ERROR_USER_TOKEN_EXPIRED "))
{
}else if(((FirebaseAuthException) task.getException()).getErrorCode().equals("ERROR_INVALID_USER_TOKEN "))
{
}
}
});
<强> REGISTER_EXCEPTIONS 强>
FirebaseAuthEmailException
表示尝试通过Firebase Auth发送电子邮件的结果的异常(例如密码重置电子邮件)
FirebaseAuthInvalidCredentialsException
- 当传递给方法的一个或多个凭据无法识别和/或验证该操作的用户主题时,抛出此异常。检查错误代码和消息以找出具体原因。
FirebaseAuthWeakPasswordException
- 使用弱密码(少于6个字符)创建新帐户或更新现有帐户密码时抛出。使用getReason()来获取一条消息,其中包含验证失败的原因,您可以向用户显示该消息。
答案 9 :(得分:1)
KOTLIN解决方案
fun signInWithEmail(email: String, passKey: String) {
FirebaseAuth.getInstance().signInWithEmailAndPassword(email, passKey).addOnSuccessListener {
it.user?.let {
authResultOperation.postValue(AuthResultOperation.OnSuccessSignIn)
}
}.addOnFailureListener {
val errorCode = (it as FirebaseAuthException).errorCode
val errorMessage = authErrors[errorCode] ?: R.string.error_login_default_error
Toast.makeText(context, context.getString(errorMessage),Toast.LENGTH_LONG).show()
}
}
说明:基本上,这只是一张将firebase错误代码与自定义字符串资源匹配的地图。
val authErrors = mapOf("ERROR_INVALID_CUSTOM_TOKEN" to R.string.error_login_custom_token,
"ERROR_CUSTOM_TOKEN_MISMATCH" to R.string.error_login_custom_token_mismatch,
"ERROR_INVALID_CREDENTIAL" to R.string.error_login_credential_malformed_or_expired,
"ERROR_INVALID_EMAIL" to R.string.error_login_invalid_email,
"ERROR_WRONG_PASSWORD" to R.string.error_login_wrong_password,
"ERROR_USER_MISMATCH" to R.string.error_login_user_mismatch,
"ERROR_REQUIRES_RECENT_LOGIN" to R.string.error_login_requires_recent_login,
"ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL" to R.string.error_login_accounts_exits_with_different_credential,
"ERROR_EMAIL_ALREADY_IN_USE" to R.string.error_login_email_already_in_use,
"ERROR_CREDENTIAL_ALREADY_IN_USE" to R.string.error_login_credential_already_in_use,
"ERROR_USER_DISABLED" to R.string.error_login_user_disabled,
"ERROR_USER_TOKEN_EXPIRED" to R.string.error_login_user_token_expired,
"ERROR_USER_NOT_FOUND" to R.string.error_login_user_not_found,
"ERROR_INVALID_USER_TOKEN" to R.string.error_login_invalid_user_token,
"ERROR_OPERATION_NOT_ALLOWED" to R.string.error_login_operation_not_allowed,
"ERROR_WEAK_PASSWORD" to R.string.error_login_password_is_weak)
字符串资源(根据您的要求随意更改)
<resources>
<string name="error_login_custom_token">The custom token format is incorrect. Please check the documentation.</string>
<string name="error_login_custom_token_mismatch">The custom token corresponds to a different audience.</string>
<string name="error_login_credential_malformed_or_expired">The supplied auth credential is malformed or has expired.</string>
<string name="error_login_invalid_email">The email address is badly formatted.</string>
<string name="error_login_wrong_password">The password is invalid or the user does not have a password.</string>
<string name="error_login_user_mismatch">The supplied credentials do not correspond to the previously signed in user.</string>
<string name="error_login_requires_recent_login">This operation is sensitive and requires recent authentication. Log in again before retrying this request.</string>
<string name="error_login_accounts_exits_with_different_credential">An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.</string>
<string name="error_login_email_already_in_use">The email address is already in use by another account.</string>
<string name="error_login_credential_already_in_use">This credential is already associated with a different user account.</string>
<string name="error_login_user_disabled">The user account has been disabled by an administrator.</string>
<string name="error_login_user_not_found">There is no user record corresponding to this identifier. The user may have been deleted.</string>
<string name="error_login_operation_not_allowed">This operation is not allowed. You must enable this service in the console.</string>
<string name="error_login_password_is_weak">The given password is invalid.</string>
<string name="error_login_user_token_expired">The user\'s credential is no longer valid. The user must sign in again</string>
<string name="error_login_invalid_user_token">The user\'s credential is no longer valid. The user must sign in again.</string>
</resources>
答案 10 :(得分:1)
我认为默认消息足够提供信息。因此,我使用它而不是任何自定义消息,对我来说效果很好。
if (!task.isSuccessful())
{
// there was an error
String yourString = task.getException().toString();
String target = "Exception:";
String error = yourString.substring(yourString.indexOf(target) + target.length() + 1, yourString.length());
Toast.makeText(LoginScreen.this, "Error: "+error, Toast.LENGTH_LONG).show();
}
p.s。这是我对堆栈溢出的第一个答案。让我知道是否有帮助。
答案 11 :(得分:0)
过去我们使用getErrorCode()来获取错误类型并正常失败。使用较新版本的api,不推荐使用getErrorCode()。我们应该使用response.getError()。getErrorCode()来代替
libmysql.dll
所以,例如。
com.firebase.ui.auth.IdpResponse
@Deprecated
public int getErrorCode()
Get the error code for a failed sign in
Deprecated use getError() instead
答案 12 :(得分:0)
尝试以下方法:
if (task.isSuccessful()) {
//Toast.makeText(getContext(),"Registration successful", Toast.LENGTH_SHORT).show();
try {
Toast.makeText(getContext(),"Registration successful", Toast.LENGTH_SHORT).show();
throw task.getException();
}
// if user enters wrong email.
catch (FirebaseAuthWeakPasswordException weakPassword) {
Log.d("Registration Error", "onComplete: weak_password");
// TODO: take your actions!
}
// if user enters wrong password.
catch (FirebaseAuthInvalidCredentialsException malformedEmail) {
Log.d("Registration Error", "onComplete: malformed_email");
// TODO: Take your action
}
catch (FirebaseAuthUserCollisionException existEmail) {
Log.d("Registration Error", "onComplete: exist_email");
// TODO: Take your action
}
catch (Exception e) {
Log.d("Registration Error", "onComplete: " + e.getMessage());
}
} else {
//Toast.makeText(getContext(), "ERROR, Please try again.", Toast.LENGTH_SHORT).show();
Toast.makeText(getContext(), task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
答案 13 :(得分:0)
这是我在Kotlin中使用的方法
fun handleErrorsFirebaseAuth(err:FirebaseAuthException): String {
when (err.errorCode) {
"ERROR_INVALID_EMAIL" -> return "Introduce un email válido"
"ERROR_EMAIL_ALREADY_IN_USE" -> return "Este email ya está en uso , usa otra cuenta o recupera la contraseña"
"ERROR_WEAK_PASSWORD" -> return "La contraseña tiene que ser de mínimo 6 carácteres"
"ERROR_WRONG_PASSWORD" -> return "La contraseña es incorrecta"
"ERROR_USER_DISABLED" -> return "Usuario deshabilitado, has infringido alguna norma"
"ERROR_USER_NOT_FOUND" -> return "No encontramos su cuenta. ¿El email es correcto? , contacte con nosotros mediante instagram @gobarberco"
else -> {
return "Se ha producido un error"
}
}
}
使用:
val messageError = handleErrorsFirebaseAuth(task.exception as FirebaseAuthException)
答案 14 :(得分:0)
要捕获firebase异常很简单,您应该在添加.addOnFailureListener
之后添加.addOnCompleteListener
:
private void login_user(String email, String password) {
mAuth.signInWithEmailAndPassword(email,password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
Intent intent = new Intent(getApplicationContext(),MainActivity.class);
startActivity(intent);
finish();
}if(!task.isSuccessful()){
// To know The Excepton
//Toast.makeText(LoginActivity.this, ""+task.getException(), Toast.LENGTH_LONG).show();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if( e instanceof FirebaseAuthInvalidUserException){
Toast.makeText(LoginActivity.this, "This User Not Found , Create A New Account", Toast.LENGTH_SHORT).show();
}
if( e instanceof FirebaseAuthInvalidCredentialsException){
Toast.makeText(LoginActivity.this, "The Password Is Invalid, Please Try Valid Password", Toast.LENGTH_SHORT).show();
}
if(e instanceof FirebaseNetworkException){
Toast.makeText(LoginActivity.this, "Please Check Your Connection", Toast.LENGTH_SHORT).show();
}
}
});
答案 15 :(得分:0)
try {
throw task.getException();
} catch(FirebaseAuthException e) {
switch (e.getErrorCode()){
case "ERROR_WEAK_PASSWORD":
Toast.makeText(this, "The given password is invalid.", Toast.LENGTH_SHORT).show();
break;
//and other
}
}
答案 16 :(得分:0)
有太多 Firebase 身份验证异常需要处理,我不确定处理所有这些异常是否是一件好事,因为要添加大量代码(正如您在其他答案中所见)。
我刚刚在 FirebaseTooManyRequestsException
返回 false 后得到一个 Task<AuthResult.isSuccessful()
:
firebaseAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener {
if (it.isSuccessful) {
[...]
} else {
[FirebaseTooManyRequestsException and others that can be returned here]
}
}
com.google.firebase.FirebaseTooManyRequestsException: We have blocked all requests from this device due to unusual activity. Try again later. [ Access to this account has been temporarily disabled due to many failed login attempts. You can immediately restore it by resetting your password or you can try again later. ]
因此,如果您想捕获所有这些或至少对您的逻辑更重要的那些,我希望在此列表中添加另一个 FirebaseAuth 例外对您有所帮助。
答案 17 :(得分:-1)
您可以使用此:
mAuth.getCurrentUser().linkWithCredential(authCredential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Log.d(TAG, "linkWithCredential:success");
} else {
Log.w(TAG, "linkWithCredential:failure", task.getException());
Toast.makeText(getApplicationContext(), "Authentication failed. " + task.getException().toString, Toast.LENGTH_SHORT).show();
}
// ...
}
});