Firebase NullPointException when logging in - java

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);

Related

android - email address is badly formatted firebase

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"

Keep User logged in Java Firebase

I am trying to keep the user logged into my chat app even after they close the app. So the only way they will be logged out of their account is if they click the log out button.
So far the user does stayed logged in but when I click the log out button, the app crashes. This is the error I get
Attempt to invoke virtual method 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' on a null object reference
at com.example.chatterbox.ChatsFragment.onCreateView(ChatsFragment.java:54)
the problem is that that error is from a different file. Can someone please help me ?
public class LoginActivity extends AppCompatActivity {
private FirebaseAuth mAuth;
private ProgressDialog loadingBar;
private Button LoginButton ;
private EditText UserEmail, UserPassword;
private TextView NeedNewAccountLink, ForgetPasswordLink;
private DatabaseReference UsersRef;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
RelativeLayout relativeLayout = findViewById(R.id.layout);
AnimationDrawable animationDrawable = (AnimationDrawable) relativeLayout.getBackground();
animationDrawable.setEnterFadeDuration(5000);
animationDrawable.setExitFadeDuration(5000);
animationDrawable.start();
mAuth = FirebaseAuth.getInstance();
UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");
InitializeFields();
if (UsersRef != null) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
NeedNewAccountLink.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SendUserToRegisterActivity();
}
});
LoginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AllowUserToLogin();
}
});
}
private void AllowUserToLogin () {
String email = UserEmail.getText().toString();
String password = UserPassword.getText().toString();
if (TextUtils.isEmpty(email)) {
Toast.makeText(this, "Please enter your email", Toast.LENGTH_SHORT).show();
}
if (TextUtils.isEmpty(password)) {
Toast.makeText(this, "Please enter your password", Toast.LENGTH_SHORT).show();
} else {
loadingBar.setTitle("Logging In");
loadingBar.setMessage("Please wait...");
loadingBar.setCanceledOnTouchOutside(true);
loadingBar.show();
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
String currentUserId = mAuth.getCurrentUser().getUid();
String deviceToken = FirebaseInstanceId.getInstance().getToken();
UsersRef.child(currentUserId).child("device_token")
.setValue(deviceToken)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
SendUserToMainActivity();
Toast.makeText(LoginActivity.this, "Logged in successfully", Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
}
});
} else {
String message = task.getException().toString();
Toast.makeText(LoginActivity.this, "Error:" + message, Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
}
});
}
}
private void InitializeFields () {
LoginButton = (Button) findViewById(R.id.login_button);
UserEmail = (EditText) findViewById(R.id.login_email);
UserPassword = (EditText) findViewById(R.id.login_password);
NeedNewAccountLink = (TextView) findViewById(R.id.need_new_account_link);
ForgetPasswordLink = (TextView) findViewById(R.id.forget_password_link);
loadingBar = new ProgressDialog(this);
}
private void SendUserToMainActivity () {
Intent mainIntent = new Intent(LoginActivity.this, MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(mainIntent);
finish();
}
private void SendUserToRegisterActivity () {
Intent registerIntent = new Intent(LoginActivity.this, RegisterActivity.class);
startActivity(registerIntent);
}
Error line :
currentUserID = mAuth.getCurrentUser().getUid();
This is how I check if the user is logged in. If they are I send them to the MainActivity. If they are not they stay on the LoginActivity
if (UsersRef != null) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
You call
mAuth = FirebaseAuth.getInstance();
UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");
and then
if (UsersRef != null) {
//do something
}
It's a bit odd because you need to know if there's currently a valid user logged in Firebase. This snippet maybe can be useful:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// User is signed in
} else {
// No user is signed in
}
But you're checking if the variable UsersRef (that is a DatabaseReference, i guess) is null or not... Indeed you just gived it a value!!!
Use addOnSuccessListener instead of addOnCompleteListener
auth.signInWithEmailAndPassword(mEmail, mPassword)
.addOnSuccessListener(LoginActivity.this, new OnSuccessListener<AuthResult>(){
#Override
public void onsuccess(#NonNull AuthResult authResult){
//your code goes here
}
});

Firebase createUserWithEmailAndPassword task.isSuccessful()

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();
}
}
});
}
}
}

Error: Caused by: java.lang.NullPointerException

I have an error which says:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.example.pc.proyectofinal.SignUp.onCreate(SignUp.java:46)
I tried two ways:
First with:
Intent SignUpINTENT = new Intent(SignUp.this, ResetPassword.class);
startActivity(SignUpINTENT);
And the second time with:
startActivity(new Intent(SignUp.this, ResetPassword.class));
Both give me the same error.
Here is the code:
public class SignUp extends AppCompatActivity {
private EditText inputEmail, inputPassword; //hit option + enter if you on mac , for windows hit ctrl + enter
private Button btnSignIn, btnSignUp, btnResetPassword;
private ProgressBar progressBar;
private FirebaseAuth auth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_signup);
//Get Firebase auth instance
auth = FirebaseAuth.getInstance();
btnSignIn = (Button) findViewById(R.id.sign_in_button);
btnSignUp = (Button) findViewById(R.id.sign_up_button);
inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.password);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
btnResetPassword = (Button) findViewById(R.id.btn_reset_password);
btnResetPassword.setOnClickListener(new View.OnClickListener() { //here is the problem with the regist
#Override
public void onClick(View v) {
Intent SignUpINTENT = new Intent(SignUp.this, ResetPassword.class);
startActivity(SignUpINTENT);
//startActivity(new Intent(SignUp.this, ResetPassword.class));
}
});
btnSignIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
btnSignUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String email = inputEmail.getText().toString().trim();
String password = inputPassword.getText().toString().trim();
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);
//create user
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(SignUp.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Toast.makeText(SignUp.this, "createUserWithEmail:onComplete:" + task.isSuccessful(), Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
// 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.
if (!task.isSuccessful()) {
Toast.makeText(SignUp.this, "Authentication failed." + task.getException(),
Toast.LENGTH_SHORT).show();
} else {
startActivity(new Intent(SignUp.this, Main.class));
finish();
}
}
});
}
});
}
#Override
protected void onResume() {
super.onResume();
progressBar.setVisibility(View.GONE);
}
}
You have this line in onCreate() commented:
setContentView(R.layout.activity_signup);
Why?
Without this line there is no layout inflated for the activity and all the views can't be found by findViewById and they are null.
So when you try
btnResetPassword.setOnClickListener()
you get
java.lang.NullPointerException

Firebase database entry is only created when breakpoint is set in Android Studio

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.

Categories

Resources