使用Firebase实现用户名替代邮箱注册时出现‘邮箱格式不正确’错误的解决方案咨询
Hey there! I see exactly what's going on here, and I can help you fix this so you can let users sign up/login with just a username instead of an email.
What's Causing the Error?
First off, the error The email address is badly formatted is happening because you're passing the username into the createUserWithEmailAndPassword() method where it expects a valid email address. Firebase's built-in email/password auth checks that the first parameter is a properly formatted email, and your username doesn't fit that standard—hence the error.
How to Implement Username-Based Auth
Since Firebase's default flow requires an email, we need a workaround. Here's a simple, practical approach that uses a "virtual" email tied to the username, along with Firebase Firestore to map usernames to user accounts:
Step 1: Modify Your Registration Code
Instead of asking for an email, we'll generate a valid virtual email from the username (e.g., username@yourapp.com), create the Firebase user with that email, and store the username in Firestore for later lookup.
reg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String username = userName.getText().toString().trim(); String pass = password.getText().toString().trim(); String cpass = confirmPass.getText().toString().trim(); // Validate input fields if (TextUtils.isEmpty(username)) { userName.setError("Username is required"); return; } if (TextUtils.isEmpty(pass)) { password.setError("Password is required"); return; } if (pass.length() < 6) { password.setError("Password length should be greater than 6"); return; } if (!TextUtils.equals(pass, cpass)) { confirmPass.setError("Passwords do not match"); return; } progBar.setVisibility(View.VISIBLE); // Generate a valid virtual email from the username String virtualEmail = username + "@yourappdomain.com"; // Create Firebase user with virtual email and password fauth.createUserWithEmailAndPassword(virtualEmail, pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { // Get the new user's UID String userId = fauth.getCurrentUser().getUid(); // Store username and virtual email in Firestore FirebaseFirestore db = FirebaseFirestore.getInstance(); HashMap<String, Object> userData = new HashMap<>(); userData.put("username", username); userData.put("email", virtualEmail); db.collection("users") .document(userId) .set(userData) .addOnSuccessListener(aVoid -> { Toast.makeText(Signup.this, "Registration Successful", Toast.LENGTH_SHORT).show(); startActivity(new Intent(getApplicationContext(), MainActivity.class)); progBar.setVisibility(View.GONE); }) .addOnFailureListener(e -> { Toast.makeText(Signup.this, "Error saving user details: " + e.getMessage(), Toast.LENGTH_SHORT).show(); progBar.setVisibility(View.GONE); }); } else { Toast.makeText(Signup.this, "Error !" + task.getException().getMessage(), Toast.LENGTH_SHORT).show(); progBar.setVisibility(View.GONE); } } }); } });
Step 2: Add Username-Based Login
For login, we'll first query Firestore to find the virtual email linked to the entered username, then use that email and password to authenticate with Firebase:
// Example login button click listener loginBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String username = userNameLogin.getText().toString().trim(); String pass = passwordLogin.getText().toString().trim(); if (TextUtils.isEmpty(username) || TextUtils.isEmpty(pass)) { Toast.makeText(Login.this, "Please fill all fields", Toast.LENGTH_SHORT).show(); return; } progBar.setVisibility(View.VISIBLE); // Query Firestore to find the user by username FirebaseFirestore db = FirebaseFirestore.getInstance(); db.collection("users") .whereEqualTo("username", username) .get() .addOnCompleteListener(task -> { if (task.isSuccessful() && !task.getResult().isEmpty()) { // Get the matching user's email DocumentSnapshot userDoc = task.getResult().getDocuments().get(0); String userEmail = userDoc.getString("email"); // Authenticate with Firebase using the virtual email and password fauth.signInWithEmailAndPassword(userEmail, pass) .addOnCompleteListener(authTask -> { if (authTask.isSuccessful()) { Toast.makeText(Login.this, "Login Successful", Toast.LENGTH_SHORT).show(); startActivity(new Intent(getApplicationContext(), MainActivity.class)); } else { Toast.makeText(Login.this, "Invalid username or password", Toast.LENGTH_SHORT).show(); } progBar.setVisibility(View.GONE); }); } else { Toast.makeText(Login.this, "Username not found", Toast.LENGTH_SHORT).show(); progBar.setVisibility(View.GONE); } }); } });
Important Notes
- Enforce Unique Usernames: Before creating a user, add a check to Firestore to ensure the username isn't already taken (use a query for the username and verify no results exist).
- Virtual Email Domain: Replace
yourappdomain.comwith a domain you control (or any dummy domain likeusername.local—it just needs to be a valid email format). - Alternative: Custom Authentication: For more control, you could use Firebase's Custom Authentication (generate custom tokens on a backend), but the above method is simpler for most use cases.
内容的提问来源于stack exchange,提问作者Hamza Butt

