Firebase Checking if username exists - java

I am currently developing an android app that only requires the user to sign up once after pressing start. The next time the user opens the application, pressing start will redirect the user to the main game already.
I was able to do this using SharedPreferences. After signing up, I store a value called currentState and I use it to check if the user has already signed up. Here's the code:
final int currentState = sharedPreferences.getInt(USERSTATE_NUM_KEY,0);
if(currentState == 0 ) {
Intent i = new Intent(MainActivity.this, Main_Screen.class);
startActivity(i);
} else{
// Redirect user to tutorial page, then the map page.
}
Now I was asked to accomplish this again using Firebase since I've already stored the user data.
Here's my code so far just to try if it's going to the onDataChange but it doesn't and I'm not sure how to do it now. Here's my code so far:
final String currentUsername = sharedPreferences.getString(USERNAME_NUM_KEY, "");
final DatabaseReference userNameRef = rootReference.child("users");
startGame.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
userNameRef.orderByChild("username").equalTo(currentUsername)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
Log.v("TESTERR", "HELLO I EXIST LOL");
}
else{
Log.v("TESTERR", "NEW USER PAGE");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
Thank you!!!

This:
userNameRef.orderByChild("username").equalTo(currentUsername)
is a query it is like saying where username= currentUsername
The currentUsername is the logged in user, the datasnapshot is users.
So in your database you have:
users
userid
username: currentUsername
When you use if(dataSnapshot.exists()){ it checks the snapshot which is users and checks the where condition, if theys exists in the database then it will enter the if clause.
If the where condition does not exists in the database then it will enter the else.

Related

How to update child node (password) with the help of user entered phone number in firebase using android studio?

Here is the Firebase view. Password is updating under users, I want to update it under sidd5(userHelper class)->Password with the help of user-entered phone number.
Firebase Database img
Here is the code.
public void updatePassword(View view) {
//get data from fields
String userNewPassword = newPassword.getEditText().getText().toString().trim();
String phoneNumber = getIntent().getStringExtra("phone");
//update data in firebase
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("users");
reference.child(phoneNumber).getRef().getParent().child("password").setValue(userNewPassword);
startActivity(new Intent(getApplicationContext(), ForgetPassSuccess.class));
finish();
}
To find a user with a specific phone number in the Firebase Realtime Database, you need to use a Query object. Once you have found it, then you can simply update the "password" property using "setValue()" method. Assuming that "phone" property holds the exact value that exists under users/sidd5/password, which is "+9.......01", please try the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = rootRef.child("users");
Query queryByPhone = usersRef.orderByChild("phone").equalTo(phoneNumber);
queryByPhone.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot userSnapshot : task.getResult().getChildren()) {
userSnapshot.child("password").getRef().setValue(userNewPassword);
}
} else {
Log.d(TAG, task.getException().getMessage()); //Don't ignore potential errors!
}
}
});

Firebase addListenerForSingleValueEvent datasnapshot returning null

I try to make a login activity using Firebase realtime database.
My database is filled as shown bellow when signing up:
Upon sign-in I want to initialize a public static User so that I can retrieve it in my main activity and update UI accordingly but the dataSnapshop of the ValueEventListener returns null.
Here is the code of my addListenerForSingleValueEvent :
currentUserReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
currentUserUsername = dataSnapshot.child("/username").getValue(String.class);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
currentUserUsername = "ERROR";
}
});
// Get every information into a User class
MainActivity.CURRENT_USER_SESSION = new User(
currentUserUsername,
user.getEmail(),
user.getUid()
);
Anyone has an idea to help me. Or any workaround or advice to do it better?
Edit: below is the initialization of the currenUserReference
currentUserReference = database.getReference("users/" + user.getUid());
the database is initialized in onCreate like that:
database = FirebaseDatabase.getInstance();
the "user" from which I get the Uid is the FirebaseUser that is returned by firebaseAuth.getCurrentUser after checking if the signInWithEmailAndPassword.addOnCompleteListener was successful.
and after the addListenerForSingleValueEvent I added a Log.d that is writtent as follows:
Log.d(TAG, "Value of variable: " + currentUserUsername);
I expect the currentUserUsername to have the value of "username" in the databased assigned, but instead, I get:
LoginActivity: Value of variable: null
Edit2: While debugging, I realized that when the debugger reaches the .addListenerForSingleValueEvent and I press F8, it completely skips this method. So, as someone said in the comment, the datasnapshot is probably not null, it's never accessed. But I still don't get why.
dataSnapshot.getValue(String.class) doesn't return null, when you exit onDataChange
your currentUserUsername is reinitialised.
So to pass the value to the next activity you need to:
currentUserReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
currentUserUsername = dataSnapshot.getValue(String.class);
// Get every information into a User class
MainActivity.CURRENT_USER_SESSION = new User(
currentUserUsername,
user.getEmail(),
user.getUid()
);
Intent intent = new Intent(
LoginActivity.this, MainActivity.class);
startActivity(intent);
}

How can I prevent Firebase user from logging into wrong login Screen

Context: In my Firebase Database I have a Parent called "Clients" that stores data in "Vendor" or "Eater" depending on which the client registered as.
Issue: Registered "Vendor" can login as "Eater" and "Eater" can login as "Vendor". With Current code, app still allows "Vendor" to login the "Eater" screen and vice versa.
What I need to do: Only allow "Vendor" to login the Vendor screen and "Eater" in the Eater screen.
Errors: I get this crash when either an Eater or Vendor Logins to the Eater screen on the
#Overridepublic void onDataChange
"java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Object.equals(java.lang.Object)' on a null object reference at com.example.zzyzj.eloteroman.login.EatCornLoginActivity$4.onDataChange"
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
circProgressBar.setVisibility(View.VISIBLE);
final String emailUser = emailEditText.getText().toString();
final String passwordUser = passwordEditText.getText().toString();
firebaseAuth.signInWithEmailAndPassword(emailUser, passwordUser).addOnCompleteListener(EatCornLoginActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (!task.isSuccessful()){
circProgressBar.setVisibility(View.INVISIBLE);
} else {
checkIfUserIsEaterOrVendor();
}
}
});
}
});
}
public void checkIfUserIsEaterOrVendor(){
FirebaseDatabase.getInstance().getReference().
child("Clients").
child(FirebaseAuth.getInstance().getCurrentUser().getUid()).
child("Eater").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue().equals("Eater")) {
//Code if the user is Eater
circProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(EatCornLoginActivity.this, R.string.login_success_toast, Toast.LENGTH_SHORT).show();
startActivity(new Intent(EatCornLoginActivity.this, MapsActivity.class));
} else {
//Code if the user is Vendor trying to login as Eater
circProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(EatCornLoginActivity.this, R.string.login_failed_toast, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getBaseContext(), databaseError.getMessage(),
Toast.LENGTH_SHORT).show();
}
});
}
You can use SharedPreferences.So you can store a userid with value of what type of user is register and check login if userid is match as your value so,it can login if you want.
SharedPreferences sharedPref = getApplicationContext().getSharedPreferences("com.example.pc.it7project.data", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(firebaseAuth.getCurrentUser().getUid(), "Vendor");
editor.apply();
And you get value of shared preference using this code
SharedPreferences sharedPref = getApplicationContext().getSharedPreferences("com.example.pc.it7project.data", Context.MODE_PRIVATE);
String sc = sharedPref.getString(FirebaseAuth.getInstance().getUid(), "");
And check
if(sc.equals("Vendor"))
{
//Put Your Code Here
}
I hope this can help you!
Thank You.
For registration:
You should ask user first, either user want to register as vendor or eater. Once
user registered itself then save its type into firebase database.
e-g bleow:
registered_user:
+user_key:(FirebaseAuth.getInstance().getCurrentUser().getUid());
+user_type:vendor/eater (under user_key node)
For login:
You must have two button to differentiate login e-g login as vendor or
login as eater. e-g If user click on login as vendor then pass its
type through intent to login activiy.
Intent intent = new Intent(StartScreen.this,LoginActivity.class);
intent.putExtra("user_type","vendor");
startActivity(intent);
Once authenticated the user then check its type
if (!task.isSuccessful() && client_db ){
circProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(EatCornLoginActivity.this, R.string.login_failed_toast, Toast.LENGTH_SHORT).show();
} else {
circProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(EatCornLoginActivity.this, R.string.login_success_toast, Toast.LENGTH_SHORT).show();
// If Login/Registration Successful send user to MapsActivity
checkUserValidation
}
getIntent().getStringExtra("user_type"), will give the type which you
passed from StratScreen.this so If you its user_type exists then you
will pass to next activity otherwise show an error toast
public void checkUserValidation(){
FirebaseDatabase.getInstance().getReference().child("registered_user").
child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child(getIntent().getStringExtra("user_type")).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() != null) {
startActivity(new Intent(EatCornLoginActivity.this, MapsActivity.class));
}else{
Log.e("notify","Error in login");
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
PS:
If you want to user SharePreferences then It's easy to do but one
problem may arise If user clear cache or uninstall then reinstall the
application the application would not be able to find the
Sharepreferences file. Sharepreferences stores data in local file.
I think a good way of solving this problem would be adding a new field in your Firebase database for every user indicating if it is a Vendor or Eater. This field can be populated when creating an account. Next, when someone wants to login you should first check if it is a Vendor trying to login on Vendor screen or Eater screen and vice versa. That way you will know for sure the type of the user. Can you do this with your implementation or I am missing something?
Example function:
public void checkUserType(){
FirebaseDatabase.getInstance().getReference().
child("Users").
child(FirebaseAuth.getInstance().getCurrentUser().getUid()).
child("user_type").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue().equals("Vendor")) {
//Code if the user is Vendor depending on the screen
} else {
//Code if the user is Eater depending on the screen
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
log.e(databaseError);
}
});
}
You should first login and get the user id and then use that to query the eater reference then if that user exist go to the eater screen else go to the vendor screen
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
circProgressBar.setVisibility(View.VISIBLE);
final String emailUser = emailEditText.getText().toString();
final String passwordUser = passwordEditText.getText().toString();
firebaseAuth.signInWithEmailAndPassword(emailUser, passwordUser)
.addOnCompleteListener(EatCornLoginActivity.this, new
OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Log.d(TAG, "createUserWithEmail:success");
FirebaseUser user = mAuth.getCurrentUser();
DatabaseReference client_db =
FirebaseDatabase.getInstance().getReference().child("Clients")
.child("Eater")
.child(user.getUid());
client_db.addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (snapshot.exists()) {
// go to eater activity
}else{
//go to vendor activity
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Toast.makeText(getContext(), firebaseError.getMessage(),
Toast.LENGTH_SHORT).show();
}
});
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "createUserWithEmail:failure",
task.getException());
Toast.makeText(EmailPasswordActivity.this, "Authentication
failed.", Toast.LENGTH_SHORT).show();
}
// ...
}
});

Why firebase return true even with empty input

Basically the program should checks for the existance of the data in the Firebase database based on the input and display the pop up accordingly, but if I left the input as empty, somehow it still considered the data does exists by prompting the 'Request' pop-out window.
#Override
public void onClick(View v) {
final String input = mInput.getText().toString();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference idRef = rootRef.child("Patient");
idRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.child(input).getValue() != null) {
startActivity(new Intent(addNew.this, Request.class));
} else{
startActivity(new Intent(addNew.this, Fail.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
I would like to know how to solve it so that the empty Input considered as inexistence data, thanks for the help
To solve this, just verify the lenght of the input String before you create the "Request pop-out window".
if(input.length() != 0) {
//"Request pop-out window"
}
You're checking if the value != null but the thing is if the value is null, firebase does not create the that child node or deletes it.
You can instead check dataSnapshot.hasChild("input") .

creating a new user entry in firebase database, everytime a user signs up in Android

I'm currently working on a quiz app, where a user signs up with email and pw via firebase.
After the signup he shall pass a nickname which will be used in for a highscore.
So basically I want the app to add a these kind of user information, everytime a user signs up as shown in the attached picture.
In order to achieve this I used this code:
public class createNickname extends AppCompatActivity {
private static final String TAG = "createNickname";
private FirebaseDatabase mFirebaseDatabase;
private FirebaseAuth.AuthStateListener mAuthListener;
private EditText NicknameInput;
private Button NicknameReg;
private String Nickname, UserId;
private FirebaseAuth mAuth;
private String EmailEntry;
private DatabaseReference myref = mFirebaseDatabase.getInstance().getReference();
#Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_nickname);
NicknameInput = (EditText)findViewById(R.id.etNickname);
NicknameReg = (Button)findViewById(R.id.btsetNickname);
mAuth = FirebaseAuth.getInstance();
myref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange( DataSnapshot dataSnapshot ) {
String value = dataSnapshot.getValue(String.class);
Log.d(TAG, "value is: " + value);
}
#Override
public void onCancelled( DatabaseError databaseError ) {
Log.w(TAG, "Failed to read value.", databaseError.toException());
}
});
NicknameReg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick( View view ) {
Log.d(TAG, "onClick: Attempting to add object to database.");
String newNick = NicknameInput.getText().toString();
if (!newNick.equals("")) {
FirebaseUser user = mAuth.getCurrentUser();
UserId = user.getUid();
EmailEntry = user.getEmail();
myref.child("userlist").push().setValue(UserId);
myref.child("userlist").child(UserId).push().setValue(EmailEntry);
myref.child("userlist").child(UserId).push().setValue(0);
startActivity(new Intent(getApplicationContext(), LoginActivity.class));
}
}
});
}
#Override
public void onStart() {
super.onStart();
// Check if user is signed in (non-null) and update UI accordingly.
FirebaseUser currentUser = mAuth.getCurrentUser();
}
}
So the question is now, what did I do wrong?
A user is created in the authentication window in firebase, but the database is just not updated.
Did I target the database correctly? How do u decided which database you want to target?
These are my firebase security rules:
{
"rules": {
".read": false,
".write": false
}
}
Regarding the database nothing is happening if i get it right.
I get no error message what so ever.
First I would advice to add a completion callback to your code so you know when and if your writes to Firebase have failed/succeeded.
In your case you would get a permission denied error because your security rules are set to false -> nobody has permission to read/write to your database. Instead you could give each user permission to write to their own data like this:
{
"rules": {
"userlist": {
"$user_id": {
// grants write access to the owner of this user account
// whose uid must exactly match the key ($user_id)
".write": "$user_id === auth.uid"
}
}
}
}
(See the documentation for more information)
For the above to work you will also have to change your code you are using to write to the database. Currently you are using push(). This generates a random id and you don't need (want) that here. Instead you can use setValue():
myref.child("userlist").push().setValue(UserId);
myref.child("userlist").child(UserId).child("email").setValue(EmailEntry);
myref.child("userlist").child(UserId).child("highscore").setValue(0);
You can also look at my answer here for a bit more information about this subject.

Categories