I'm creating an Android application and am implementing the login / register functionality.
I'm at the stage where the register activity is successfully creating user entries in my Firebase application, however, I can't seem to track if the task was successful.
private void startRegister() {
String email = mEmailField.getText().toString();
String password = mPasswordField.getText().toString();
String confirmPassword = mConfirmPassword.getText().toString();
// Check that fields are not empty
if (TextUtils.isEmpty(email) || TextUtils.isEmpty(password) || TextUtils.isEmpty(confirmPassword)) {
Toast.makeText(Register.this, "Email, password or confirm password field cannot be empty.", Toast.LENGTH_LONG).show();
} else if (!password.equals(confirmPassword)) {
Toast.makeText(Register.this, "Password and confirm password should match", Toast.LENGTH_LONG).show();
} else {
mAuth.createUserWithEmailAndPassword(email, password).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
Toast.makeText(Register.this, "Success", Toast.LENGTH_LONG).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(Register.this, "Failure", Toast.LENGTH_LONG).show();
}
});
}
}
Both the if !task.isSuccessful() or else blocks ever get reached but the user is created in Firebase. Any ideas why I can't track the success/if it failed?
IN COMPARISON:
This is working in my login class.
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
Toast.makeText(Login.this, "Credentials error, user may not exist.", Toast.LENGTH_LONG).show();
}
}
});
Hard to say what's going with the current way of implementation.
Try adding a onSuccess directly
mAuth.createUserWithEmailAndPassword(email, pass).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
//done
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
//display toast if registering failed
ToastRect.failed(RegisterActivity.this, getString(R.string.app_activities_error_text)
}
});
public class Register extends AppCompatActivity {
private EditText mEmailField;
private EditText mPasswordField;
private EditText mConfirmPassword;
private Button mRegisterButton;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirebaseApp.initializeApp(this);
setContentView(R.layout.activity_register);
mEmailField = findViewById(R.id.registerEmailField);
mPasswordField = findViewById(R.id.registerPasswordField);
mConfirmPassword = findViewById(R.id.registerConfirmPassword);
mRegisterButton = findViewById(R.id.registerButton);
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() != null) {
startActivity(new Intent(Register.this, UploadActivity.class));
}
}
};
// https://stackoverflow.com/questions/10936042/how-to-open-layout-on-button-click-android
Button register = (Button) findViewById(R.id.navigate_to_login);
register.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(view.getContext(), Login.class);
startActivityForResult(myIntent, 0);
}
});
mRegisterButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startRegister();
}
});
}
#Override
protected void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
private void startRegister() {
String email = mEmailField.getText().toString();
String password = mPasswordField.getText().toString();
String confirmPassword = mConfirmPassword.getText().toString();
// Check that fields are not empty
if (TextUtils.isEmpty(email) || TextUtils.isEmpty(password) || TextUtils.isEmpty(confirmPassword)) {
Toast.makeText(Register.this, "Email, password or confirm password field cannot be empty.", Toast.LENGTH_LONG).show();
} else if (!password.equals(confirmPassword)) {
Toast.makeText(Register.this, "Password and confirm password should match", Toast.LENGTH_LONG).show();
} else {
mAuth.createUserWithEmailAndPassword(email, password).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
Toast.makeText(Register.this, "Success", Toast.LENGTH_LONG).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(Register.this, "Failure", Toast.LENGTH_LONG).show();
}
});
}
}
}
To confirm the FirebaseAuth.AuthStateListener() was kicking in. This was a bad copy and paste job from the my Login class. This was stopping me handle the successful user creation.
The fix then looked like:
public class Register extends AppCompatActivity {
private EditText mEmailField;
private EditText mPasswordField;
private EditText mConfirmPassword;
private Button mRegisterButton;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirebaseApp.initializeApp(this);
setContentView(R.layout.activity_register);
mEmailField = findViewById(R.id.registerEmailField);
mPasswordField = findViewById(R.id.registerPasswordField);
mConfirmPassword = findViewById(R.id.registerConfirmPassword);
mRegisterButton = findViewById(R.id.registerButton);
mAuth = FirebaseAuth.getInstance();
// https://stackoverflow.com/questions/10936042/how-to-open-layout-on-button-click-android
Button register = (Button) findViewById(R.id.navigate_to_login);
register.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(view.getContext(), Login.class);
startActivityForResult(myIntent, 0);
}
});
mRegisterButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startRegister();
}
});
}
#Override
protected void onStart() {
super.onStart();
}
private void startRegister() {
String email = mEmailField.getText().toString();
String password = mPasswordField.getText().toString();
String confirmPassword = mConfirmPassword.getText().toString();
// Check that fields are not empty
if (TextUtils.isEmpty(email) || TextUtils.isEmpty(password) || TextUtils.isEmpty(confirmPassword)) {
Toast.makeText(Register.this, "Email, password or confirm password field cannot be empty.", Toast.LENGTH_LONG).show();
} else if (!password.equals(confirmPassword)) {
Toast.makeText(Register.this, "Password and confirm password should match", Toast.LENGTH_LONG).show();
} else {
mAuth.createUserWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Toast.makeText(Register.this, "Password and confirm password should match", Toast.LENGTH_LONG).show();
}
}
});
}
}
}
Related
hello I'm making a login in my project and when I try to input the data it says email address is badly formatted
Codes
public class MainActivity extends AppCompatActivity {
private EditText email;
private EditText Password;
private ImageButton BackMenu;
private TextView SignIn;
private Button login;
ProgressBar progressBar;
private FirebaseAuth auth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progressBar);
progressBar.setVisibility(View.GONE);
email = (EditText)findViewById(R.id.log_email);
Password = (EditText)findViewById(R.id.password);
BackMenu = (ImageButton)findViewById(R.id.returnMenu);
SignIn = (TextView) findViewById(R.id.reg_SignIn);
login = (Button)findViewById(R.id.btn_Login);
auth = FirebaseAuth.getInstance();
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loginUser();
}
});
SignIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
registrationForm();
progressBar.setVisibility(View.VISIBLE);
}
});
BackMenu.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openShopMenu();
progressBar.setVisibility(View.VISIBLE);
}
});
}
private void loginUser() {
String userEmail = email.getText().toString().trim();
String userPass = Password.getText().toString().trim();
progressBar.setVisibility(View.VISIBLE);
if (TextUtils.isEmpty(userEmail)){
Toast.makeText(this, "Email is empty", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
return;
}
if (TextUtils.isEmpty(userPass)){
Toast.makeText(this, "Password is empty", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
return;
}
if (userPass.length() < 5){
Toast.makeText(this, "Password must be 5 characters or more", Toast.LENGTH_SHORT).show();
}
auth.signInWithEmailAndPassword(userPass,userEmail)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
Toast.makeText(MainActivity.this, "Login is Successful", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
else {
Toast.makeText(MainActivity.this, "Error"+task.getException(), Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
}
});
}
public void openShopMenu() {
Intent intent = new Intent(MainActivity.this, ShopMenu.class);
startActivity(intent);
progressBar.setVisibility(View.GONE);
}
public void registrationForm(){
Intent intent = new Intent(MainActivity.this,Registration.class);
startActivity(intent);
progressBar.setVisibility(View.GONE);
}
}
Problem
the input is:
Email : gon#gmail.com
Password : 12345678
The user fails to login and the message below pops out
The email address is badly formatted
and I don't think there's a problem in my .xml file
android:inputType="textEmailAddress"
I'm trying to authenticate user with phone number using the firebase Authentication method. But it is showing me error after some time by running the code. And I think the sendVerificationCodeToUser() function is not working properly.
package com.example.foodapp;
import ...
public class PhoneVerification<phoneAuthProvider> extends AppCompatActivity {
String verificationCodeBySystem;
Button btn_verify;
EditText phoneenteredbyuser;
ProgressBar progressbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone_verification);
btn_verify = findViewById(R.id.btn_verify);
phoneenteredbyuser = findViewById(R.id.txt_otp);
progressbar = findViewById(R.id.progressbar);
progressbar.setVisibility(View.GONE);
String phoneNo = getIntent().getStringExtra("phone");
sendVerificationCodeToUser(phoneNo);
btn_verify.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String code= phoneenteredbyuser.toString();
if(code.isEmpty() || code.length()< 6){
phoneenteredbyuser.setError("Wrong OTP...");
phoneenteredbyuser.requestFocus();
return;
}
progressbar.setVisibility(View.VISIBLE);
verifyCode(code);
}
});
}
private void sendVerificationCodeToUser(String phoneNo) {
FirebaseAuth mAuth= FirebaseAuth.getInstance();
PhoneAuthOptions options =
PhoneAuthOptions.newBuilder(mAuth)
.setPhoneNumber("+92" + phoneNo) // Phone number to verify
.setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
.setActivity(this) // Activity (for callback binding)
.setCallbacks(mCallbacks) // OnVerificationStateChangedCallbacks
.build();
PhoneAuthProvider.verifyPhoneNumber(options);
}
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
#Override //Entering OTP by manual way
public void onCodeSent(#NonNull String s, #NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
verificationCodeBySystem = s;
}
#Override // Automatically Verifying the OTP by system.
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
String code = phoneAuthCredential.getSmsCode();
if (code != null) {
progressbar.setVisibility(View.VISIBLE);
verifyCode(code);
}
}
#Override //In case of error this code will run.
public void onVerificationFailed(FirebaseException e) {
Toast.makeText(PhoneVerification.this, "Error Occured", Toast.LENGTH_SHORT).show();
}
};
private void verifyCode(String codeByUser) {
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationCodeBySystem, codeByUser);
signInUserByCredentials(credential);
}
private void signInUserByCredentials(PhoneAuthCredential credential) {
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
firebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(PhoneVerification.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Toast.makeText(PhoneVerification.this, "Your Account has been created successfully!", Toast.LENGTH_SHORT).show();
//Perform Your required action here to either let the user sign In or do something required
Intent intent = new Intent(getApplicationContext(), User_Home.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
} else {
Toast.makeText(PhoneVerification.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
}
i'm using firebase to login to my app there are two users customer and driver .i log in as driver/captain after app restart without asking for sign in as customer or driver it moves to customer side.just because of user.getInstance()
how to differenciate how was signed in first
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customer_login);
nAuth= FirebaseAuth.getInstance();
firebaseAuthListener= new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user =FirebaseAuth.getInstance().getCurrentUser();
if(user!=null){
Intent intent= new Intent(CustomerLoginActivity.this, CustomerMapActivity.class);
startActivity(intent);
}
}
};
nEmail= findViewById(R.id.email);
nPassword= findViewById(R.id.password);
nLogIn= findViewById(R.id.login);
new_user= findViewById(R.id.new_user);
new_user.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(user_Type=="Customer") {
final String email = nEmail.getText().toString();
final String password = nPassword.getText().toString();
nAuth.createUserWithEmailAndPassword(email, password).addOnCompleteListener(CustomerLoginActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
Toast.makeText(CustomerLoginActivity.this, "Sign Up Error", Toast.LENGTH_SHORT).show();
} else {
String user_id = nAuth.getCurrentUser().getUid();
DatabaseReference current_user_db = FirebaseDatabase.getInstance().getReference().child("Users").child("Customers").child(user_id);
current_user_db.setValue(true);
}
}
});
}else if(user_Type=="Captain"){
final String email = nEmail.getText().toString();
final String password = nPassword.getText().toString();
nAuth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(CustomerLoginActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(!task.isSuccessful()){
Toast.makeText(CustomerLoginActivity.this , "Sign Up Error", Toast.LENGTH_SHORT).show();
}else{
String user_id= nAuth.getCurrentUser().getUid();
DatabaseReference current_user_db = FirebaseDatabase.getInstance().getReference().child("Users").child("Drivers").child(user_id);
current_user_db.setValue(true);
}
}
});
}else {
Toast.makeText(CustomerLoginActivity.this , "Select Any User Type", Toast.LENGTH_SHORT).show();
}
}
});
nLogIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (user_Type=="Customer") {
final String email = nEmail.getText().toString();
final String password = nPassword.getText().toString();
nAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(CustomerLoginActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
Toast.makeText(CustomerLoginActivity.this, "Sign Up Error", Toast.LENGTH_SHORT).show();
}
}
});
}
else if(user_Type=="Captain"){
final String email = nEmail.getText().toString();
final String password = nPassword.getText().toString();
nAuth.signInWithEmailAndPassword(email,password).addOnCompleteListener(CustomerLoginActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(!task.isSuccessful()){
Toast.makeText(CustomerLoginActivity.this , "Sign Up Error", Toast.LENGTH_SHORT).show();
}
}
});
}else {
Toast.makeText(CustomerLoginActivity.this , "Select Any User Type", Toast.LENGTH_SHORT).show();
}
}
});
actually using that email registered as captain but it login as customer too
If you are only restarting the application, then you can do the following:
DatabaseReference customer = FirebaseDatabase.getInstance().getReference().child("customer");
DatabaseReference driver = FirebaseDatabase.getInstance().getReference().child("driver");
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if(user!=null){
customer.child(user.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists() && user != null) {
Intent i = new Intent(Activity.this, CustomerActivity.class);
startActivity(i);
finish();
} else {
driver.child(user.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists() && user != null) {
Intent i = new Intent(Activity.this, DriverActivity.class);
startActivity(i);
finish();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
Here, you retrieve the FirebaseUser then you check if the userId is under either the customer node or the driver node, and then you navigate to the specific activity.
For the above to work, you need to have the following database:
customer
userId
name : customer_1
driver
userId
name : driver_1
Hello im trying to create a firebase logging in auth with 2 different users, the admin, and user. but like when i was trying to log in, The application would crash. Heres the error i think
my database
and here is my code on the login
public class LoginActivity extends AppCompatActivity {
private EditText inputEmail, inputPassword;
private FirebaseAuth auth;
private ProgressBar progressBar;
private Button btnSignup, btnLogin, btnReset;
private DatabaseReference mFirebaseDatabase;
private FirebaseDatabase mFirebaseInstance;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setIcon(R.mipmap.ic_launcher);
auth = FirebaseAuth.getInstance();
setContentView(R.layout.activity_login);
inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.password);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
btnSignup = (Button) findViewById(R.id.btn_signup);
btnLogin = (Button) findViewById(R.id.btn_login);
btnReset = (Button) findViewById(R.id.btn_reset_password);
//db
mFirebaseInstance = FirebaseDatabase.getInstance();
//Get Firebase auth instance
auth = FirebaseAuth.getInstance();
btnSignup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(LoginActivity.this, signup.class));
}
});
btnReset.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(LoginActivity.this, ResetPasswordActivity.class));
}
});
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String email = inputEmail.getText().toString();
final String password = inputPassword.getText().toString();
if (TextUtils.isEmpty(email)) {
Toast.makeText(getApplicationContext(), "Enter email address!", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(password)) {
Toast.makeText(getApplicationContext(), "Enter password!", Toast.LENGTH_SHORT).show();
return;
}
progressBar.setVisibility(View.VISIBLE);
//authenticate user
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(LoginActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
progressBar.setVisibility(View.GONE);
if (!task.isSuccessful()) {
// there was an error
if (password.length() < 6) {
inputPassword.setError(getString(R.string.minimum_password));
} else {
Toast.makeText(LoginActivity.this, getString(R.string.auth_failed), Toast.LENGTH_LONG).show();
}
} else {
onAuthSuccess(task.getResult().getUser());
}
}
private void onAuthSuccess(FirebaseUser user) {
if (user !=null){
mFirebaseDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child(user.getUid()).child("type");
mFirebaseDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
if(Integer.parseInt(value) == 1) {
startActivity(new Intent(LoginActivity.this, UserActivity.class));
Toast.makeText(LoginActivity.this, "Welcome User", Toast.LENGTH_SHORT).show();
finish();
}else {
startActivity(new Intent(LoginActivity.this, AdminActivity.class));
Toast.makeText(LoginActivity.this, "Welcome", Toast.LENGTH_SHORT).show();
finish();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
});
}
});
}
I feel like the problem lies on the ondata change one but I don't know what to do to fix this, so im asking for your help :O
Try this:
mFirebaseDatabase = FirebaseDatabase.getInstance().getReference().child("Accounts").child("Users").child(user.getUid());
mFirebaseDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.child("type").getValue(String.class);
if(Integer.parseInt(value) == 1) {
startActivity(new Intent(LoginActivity.this, UserActivity.class));
Toast.makeText(LoginActivity.this, "Welcome User", Toast.LENGTH_SHORT).show();
finish();
}else {
startActivity(new Intent(LoginActivity.this, AdminActivity.class));
Toast.makeText(LoginActivity.this, "Welcome", Toast.LENGTH_SHORT).show();
finish();
}
}
try the above, have the reference at the userid then inside onDataChange retrieve the type. you need to reference in order and specify the child name like this:
String value = dataSnapshot.child("type").getValue(String.class);
I have the following SignUp Activity that does not work properly: after the user receives the verification email and tries to sign in, the app crashes with a NullPointerException, as a new user entry in Firebase Realtime Database is not created. I noticed, though, during debugging, that if I set a breakpoint at where generateUser() is defined, a new database entry is created (the app crashes the same way, though).
What could be the solution here?
Any help would be highly appreciated.
Update: The emphasis here is not on NullPointerException, I can handle that. The question is why generateUser() is not being called.
public class SignUpActivity extends AppCompatActivity {
private EditText inputUsername, inputEmail, inputPassword;
private Button btnSignIn, btnSignUp;
private ProgressBar progressBar;
private FirebaseAuth auth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
auth = FirebaseAuth.getInstance();
FirebaseUser user = auth.getCurrentUser();
if (user != null) {
if (user.isEmailVerified()) {
startActivity(new Intent(SignUpActivity.this, MainActivity.class));
finish();
}
}
setContentView(R.layout.activity_sign_up);
btnSignIn = findViewById(R.id.sign_in_button);
btnSignUp = findViewById(R.id.sign_up_button);
inputUsername = findViewById(R.id.username);
inputEmail = findViewById(R.id.email);
inputPassword = findViewById(R.id.password);
progressBar = findViewById(R.id.progressBar);
btnSignIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(SignUpActivity.this, SignInActivity.class));
}
});
btnSignUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String username = inputUsername.getText().toString().trim();
final String email = inputEmail.getText().toString().trim();
final String password = inputPassword.getText().toString().trim();
if (TextUtils.isEmpty(username)) {
Toast.makeText(getApplicationContext(), "Enter username!", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(email)) {
Toast.makeText(getApplicationContext(), "Enter email address!", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(password)) {
Toast.makeText(getApplicationContext(), "Enter password!", Toast.LENGTH_SHORT).show();
return;
}
if (password.length() < 6) {
Toast.makeText(getApplicationContext(), "Password too short, enter minimum 6 characters!", Toast.LENGTH_SHORT).show();
return;
}
progressBar.setVisibility(View.VISIBLE);
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(SignUpActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
progressBar.setVisibility(View.GONE);
if (!task.isSuccessful()) {
Toast.makeText(SignUpActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show();
} else {
new GenerateUserAsyncTask().execute(username, email, password, 0);
}
}
});
}
class GenerateUserAsyncTask extends AsyncTask<Object, Void, Void> {
#Override
protected Void doInBackground(Object... params) {
String username = (String) params[0];
String email = (String) params[1];
String password = (String) params[2];
int score = (int) params[3];
generateUser(username, email, password, score);
return null;
}
#Override
protected void onPostExecute(Void result) {
sendVerificationEmail();
}}
});
}
public void sendVerificationEmail() {
FirebaseUser user = auth.getCurrentUser();
if (user != null) {
user.sendEmailVerification()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(SignUpActivity.this, "Signup successful, verification email sent", Toast.LENGTH_SHORT).show();
auth.signOut();
startActivity(new Intent(SignUpActivity.this, SignInActivity.class));
finish();
} else {
Toast.makeText(SignUpActivity.this, "Failed to send email!", Toast.LENGTH_SHORT).show();
}
progressBar.setVisibility(View.GONE);
}
});
}
}
public void generateUser(String username, String email, String password, int score) {
FirebaseDatabase database = Utils.getDatabase();
DatabaseReference users = database.getReference("users");
User user = new User(username, email, password, score);
users.child(auth.getUid()).setValue(user);
}
}
I have found the solution. The problem is caused by the Realtime Database security rules: they only allow users to write to the database if they are authenticated. In my code, though, where generateUser() is called, users are not fully authenticated yet. So I need to generate new entries in the database after the user has clicked on the link in the verification email.