Well, I get the user inside the Firebase database but it doesn’t seem to be opening up the login activity after clicking register. It endlessly shows the progress bar…
Heres the entire RegisterActivity.java code block
package com.example.goalhero;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.app.DatePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Patterns;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.auth.FirebaseAuthUserCollisionException;
import com.google.firebase.auth.FirebaseAuthWeakPasswordException;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.UserProfileChangeRequest;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegisterActivity extends AppCompatActivity {
EditText etRegFullname, etRegEmail, etRegDob, etRegMobile, etRegPwd, etRegConfirmPwd;
ProgressBar progressBar;
RadioGroup rgRegGender;
RadioButton rbRegGenderSelected;
DatePickerDialog picker;
private static final String TAG = "RegisterActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
setSupportActionBar(findViewById(R.id.toolbar));
Toast.makeText(RegisterActivity.this, "You may register now.", Toast.LENGTH_LONG).show();
progressBar = findViewById(R.id.progress_bar);
etRegPwd = findViewById(R.id.et_register_password);
etRegConfirmPwd = findViewById(R.id.et_confirm_password);
etRegFullname = findViewById(R.id.et_register_fullname);
etRegEmail = findViewById(R.id.et_register_email);
etRegDob = findViewById(R.id.et_register_dob);
etRegMobile = findViewById(R.id.et_register_mobile);
rgRegGender = findViewById(R.id.radio_group_register_gender);
rgRegGender.clearCheck();
// Setting up the date picker
etRegDob.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final Calendar cal = Calendar.getInstance();
int day = cal.get(Calendar.DAY_OF_MONTH);
int month = cal.get(Calendar.MONTH);
int year = cal.get(Calendar.YEAR);
// Date picker dialog
picker = new DatePickerDialog(RegisterActivity.this, new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker datePicker, int year, int month, int day) {
etRegDob.setText(day + "/" + (month + 1) + "/" + year);
Log.d(TAG, "Date of Birth selected: " + etRegDob.getText().toString());
}
}, year, month, day);
picker.show();
}
});
Button registerBtn = findViewById(R.id.registerBtn);
registerBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int selectedGenderId = rgRegGender.getCheckedRadioButtonId();
rbRegGenderSelected = findViewById(selectedGenderId);
// Obtain the entered data
String txtFullname = etRegFullname.getText().toString();
String txtEmail = etRegEmail.getText().toString();
String txtDob = etRegDob.getText().toString();
String txtMobile = etRegMobile.getText().toString();
String txtPwd = etRegPwd.getText().toString();
String txtConfirmPwd = etRegConfirmPwd.getText().toString();
String txtGender;
Log.d(TAG, "Register button clicked with details - Fullname: " + txtFullname + ", Email: " + txtEmail + ", DOB: " + txtDob + ", Mobile: " + txtMobile + ", Password: " + txtPwd + ", Confirm Password: " + txtConfirmPwd);
// Validate the mobile number using matcher and pattern (regular express)
String mobileRegex = "^(\+\d{1,2}\s?)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$";
Matcher mobileMatcher;
Pattern mobilePattern = Pattern.compile(mobileRegex);
mobileMatcher = mobilePattern.matcher(txtMobile);
if (TextUtils.isEmpty(txtFullname)) {
showError(etRegFullname, "Please enter your full name.", "Full name is required.");
} else if (TextUtils.isEmpty(txtEmail)) {
showError(etRegEmail, "Please enter a valid email.", "Email is required.");
} else if (!Patterns.EMAIL_ADDRESS.matcher(txtEmail).matches()) {
showError(etRegEmail, "Please re-enter your email.", "Valid email address required.");
} else if (TextUtils.isEmpty(txtDob)) {
showError(etRegDob, "Please enter your DOB.", "DOB required.");
} else if (rgRegGender.getCheckedRadioButtonId() == -1) {
showError(rbRegGenderSelected, "Please select your gender.", "Gender selection required.");
} else if (TextUtils.isEmpty(txtMobile)) {
showError(etRegMobile, "Please enter your 10-digit mobile number.", "Phone number isn't valid.");
} else if (txtMobile.length() != 10) {
showError(etRegMobile, "Phone number must be 10-digits", "Phone number isn't 10-digits.");
} else if (!mobileMatcher.find()) {
showError(etRegMobile, "This is not a valid phone number.", null);
} else if (TextUtils.isEmpty(txtPwd)) {
showError(etRegPwd, "You must enter a password.", "No password entered.");
} else if (txtPwd.length() < 6) {
showError(etRegPwd, "Password too short.", "Password too short.");
} else if (TextUtils.isEmpty(txtConfirmPwd)) {
showError(etRegConfirmPwd, "Please confirm your password.", "Password confirmation is required.");
} else if (!txtPwd.equals(txtConfirmPwd)) {
showError(etRegConfirmPwd, "Passwords must match.", "Passwords don't match.");
etRegConfirmPwd.clearComposingText();
etRegPwd.clearComposingText();
} else {
txtGender = rbRegGenderSelected.getText().toString();
progressBar.setVisibility(View.VISIBLE);
registerUser(txtFullname, txtEmail, txtDob, txtGender, txtMobile, txtPwd);
}
}
});
}
private void showError(View view, String toastMessage, String errorMessage) {
Toast.makeText(RegisterActivity.this, toastMessage, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Error: " + toastMessage + " - " + errorMessage);
if (view instanceof EditText) {
((EditText) view).setError(errorMessage);
view.requestFocus();
} else if (view instanceof RadioButton) {
((RadioButton) view).setError(errorMessage);
view.requestFocus();
}
}
private void registerUser(String txtFullname, String txtEmail, String txtDob, String txtGender, String txtMobile, String txtPwd) {
FirebaseAuth auth = FirebaseAuth.getInstance();
auth.createUserWithEmailAndPassword(txtEmail, txtPwd)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
FirebaseUser firebaseUser = task.getResult().getUser();
Log.d(TAG, "User registered successfully with UID: " + firebaseUser.getUid());
updateUserProfile(firebaseUser, txtFullname);
writeUserDataToDatabase(firebaseUser, new ReadWriteUserDetails(txtDob, txtGender, txtMobile));
} else {
handleRegistrationError(task.getException());
}
progressBar.setVisibility(View.GONE);
}
});
}
private void updateUserProfile(FirebaseUser user, String displayName) {
user.updateProfile(new UserProfileChangeRequest.Builder()
.setDisplayName(displayName)
.build())
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User profile updated.");
} else {
Log.e(TAG, "Failed to update user profile.");
Toast.makeText(RegisterActivity.this, "Failed to update user profile.", Toast.LENGTH_SHORT).show();
}
}
});
}
private void writeUserDataToDatabase(FirebaseUser user, ReadWriteUserDetails userData) {
DatabaseReference referenceProfile = FirebaseDatabase.getInstance().getReference("Registered Users");
referenceProfile.child(user.getUid()).setValue(userData)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User data written to database.");
sendVerificationEmail(user);
} else {
Log.e(TAG, "Failed to save user data.");
Toast.makeText(RegisterActivity.this, "Failed to save user data.", Toast.LENGTH_SHORT).show();
}
}
});
}
private void sendVerificationEmail(FirebaseUser user) {
user.sendEmailVerification()
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Verification email sent.");
Toast.makeText(RegisterActivity.this, "User registered successfully. Please verify your email.", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
} else {
Log.e(TAG, "Failed to send verification email.");
Toast.makeText(RegisterActivity.this, "Failed to send verification email.", Toast.LENGTH_SHORT).show();
}
}
});
}
private void handleRegistrationError(Exception e) {
String message;
if (e instanceof FirebaseAuthWeakPasswordException) {
message = "Password must contain 6 or more characters. Letters, numbers, and special character required";
} else if (e instanceof FirebaseAuthInvalidCredentialsException) {
message = "Your email is invalid or already in use.";
} else if (e instanceof FirebaseAuthUserCollisionException) {
message = "User is already registered.";
} else {
message = e.getMessage();
}
Log.e(TAG, "Registration error: " + message, e);
Toast.makeText(RegisterActivity.this, message, Toast.LENGTH_SHORT).show();
}
}
This is the output of the code
RegisterActivity com.example.goalhero D Date of Birth selected: 6/6/2024
RegisterActivity com.example.goalhero D Register button clicked with details – Fullname: K, Email: [email protected], DOB: 6/6/2024, Mobile: 2042322553, Password: *******, Confirm Password: *******
RegisterActivity com.example.goalhero D User registered successfully with UID: T49FfhdctwOcevRDuA94K0IDw8t2
RegisterActivity com.example.goalhero D User profile updated.
2
Answers
I just moved this
Into the registerUser method... Got rid of the email verification all together.
Firstly I would highly suggest separate each functionality to a separate function, for example you would do something like:
This will improve code organization, reusability and maintainability.
Also I would suggest moving sending the verification email after successful user registration to ensure the user object is valid.
You can see a complete example reflecting my points in Here