firebase realtime database push infinite loop error - java

I'm using firebase authentication with email and password.
So I want to save user data in realtime database .
But when i push the data to database, infinite loop was executing.
I don't know why..
I want to save data like this form and continue saving.
But when I starting, infinite loop is starting
private void createUser(String email, String password,String name, String phone, String
nickname) {
firebaseAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) { //Join Success
Toast.makeText(JoinActivity.this, "Join Success", Toast.LENGTH_SHORT).show();
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(firebaseAuth.getCurrentUser()!=null) {
String email=editTextEmail.getText().toString().trim();
FirebaseUser user=firebaseAuth.getCurrentUser();
String uid=user.getUid();
if(dataSnapshot.child("USER").child("user_info").child(uid).exists()){
Toast.makeText(JoinActivity.this,"already exist",Toast.LENGTH_SHORT).show();
}else{
User user_info = new User(uid, editTextId.getText().toString(), editTextEmail.getText().toString(), editTextPassword.getText().toString(),
editTextname.getText().toString(), editTextNickname.getText().toString(), editTextPhone.getText().toString());
//delete all data
mDatabase.setValue(null);
String key = mDatabase.child("USER").push().getKey();
// mDatabase.child("USER").child("user_info").child(key).setValue(user_info);
Toast.makeText(JoinActivity.this, "save the data", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Intent intent = new Intent(JoinActivity.this, MainActivity.class);
startActivity(intent);
} else { //already exists
Toast.makeText(JoinActivity.this, "already exists", Toast.LENGTH_SHORT).show();
return;
}
}
});
}
}

Instead of :
mDatabase.addValueEventListener(new ValueEventListener() {
Use the following:
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
This way you will retrieve data only once.

Related

cannot be cast to com.google.firebase.database.DatabaseReference

Hi I'm creating a simple login system. I have 2 users of my application
user
admin
I'm trying that if the user login app intends to user activity and if the admin login app intents to admin activity.
For this, I am passing a String "admin" when the new admin register and "user" went the new user register, And in Login Activity, I match these String but this error occurs.
mAuth.signInWithEmailAndPassword(dbemail, dbpassword)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
FirebaseUser users = FirebaseAuth.getInstance().getCurrentUser();
if (users != null){
DatabaseReference databaseReference = (DatabaseReference) FirebaseDatabase.getInstance().getReference().child("users")
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.child("as").equals("Admin")){
startActivity(new Intent(LoginActivity.this,MainActivity.class));
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
else {
Toast.makeText(LoginActivity.this, "Failed to login! Please check your credentials", Toast.LENGTH_LONG).show();
}
}
else {
Toast.makeText(LoginActivity.this, "This account don't exist! Create Account", Toast.LENGTH_LONG).show();
}
}
});
addValueEventListener method returns ValueEventListener type, not DatabaseReference so it cannot be cast.
If you don't need DatabaseReference object, it should be enough:
FirebaseDatabase.getInstance().getReference().child("users")
.addValueEventListener(...);

How to check if the particular username exists in the firebase? (Java Android)

I have tried all of the StackOverflow methods but all the methods are checking if it's null or not.
I wanted to check the particular strings under the "Users" node. example: (aaaaa) (bbbbb) or the child value in it (username : "aaaaa")
if users enter username as "asaaa" or "bbbbb" in registration will be a prompt error. (i want to check all of the values in all of the nodes of firebase)
I have searched all over the stack overflow but most of the solutions need to know the node names in order to run. I want to retrieve all of the names of the nodes under "Users" back to check.
if a user uses "aaaaa" as a username during registration will be setError in the TextInputLayout.
public class RegisterActivity extends AppCompatActivity {
EditText username, fullname, email, password;
Button register;
TextView txt_login;
public String strUsername;
FirebaseAuth auth;
DatabaseReference reference;
ProgressDialog pd;
private static final String TAG = "RegisterActivity";
private static String users_from_database;
private ArrayList<String> username_list = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
username = findViewById(R.id.username);
fullname = findViewById(R.id.fullname);
email = findViewById(R.id.email);
password = findViewById(R.id.password);
register = findViewById(R.id.btn_Register);
txt_login = findViewById(R.id.txt_login);
auth = FirebaseAuth.getInstance();
checkForUsername();
txt_login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(RegisterActivity.this,HomeActivity.class));
}
});
register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pd = new ProgressDialog(RegisterActivity.this);
pd.setMessage("Please wait...");
pd.show();
String str_username = username.getText().toString();
String str_fullname = fullname.getText().toString();
String str_email = email.getText().toString();
String str_password = password.getText().toString();
strUsername = username.getText().toString().trim();
if (!username_list.contains(strUsername)) {
// do your job here , suppose send verification code to phone number
if(TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_fullname) || TextUtils.isEmpty(str_email) ||
TextUtils.isEmpty(str_password)){
Toast.makeText(RegisterActivity.this,"All fields are required!",Toast.LENGTH_SHORT).show();
pd.dismiss();
} else if (str_password.length() < 6) {
Toast.makeText(RegisterActivity.this,"Password must be over 6 characters.",Toast.LENGTH_SHORT).show();
pd.dismiss();
} else {
register(str_username,str_fullname,str_email,str_password);
}
} else {
username.setError("Username Exist");
}
}
});
}
private void checkForUsername(){
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users/");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds : snapshot.getChildren()) {
users_from_database = (String) ds.child("username").getValue();
username_list.add(users_from_database);
StringBuilder stringBuilder = new StringBuilder();
for (String s : username_list) {
stringBuilder.append(s + "\n");
}
Log.d("ZI", stringBuilder.toString());
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d("ZI", "Failed");
}
});
}
private void register(final String username, final String fullname, String email, String password){
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(RegisterActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
FirebaseUser firebaseUser = auth.getCurrentUser();
String userID = firebaseUser.getUid();
firebaseUser.sendEmailVerification().addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(RegisterActivity.this,"Verification Email Has Been Sent.", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: Email not sent" + e.getMessage());
}
});
reference = FirebaseDatabase.getInstance().getReference().child("Users").child(username);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("username",username.toLowerCase());
hashMap.put("fullname",fullname);
hashMap.put("email",email);
hashMap.put("password",password);
hashMap.put("imageurl","");
reference.setValue(hashMap).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
pd.dismiss();
Intent intent = new Intent(RegisterActivity.this,EmailActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
});
} else {
pd.dismiss();
Toast.makeText(RegisterActivity.this,"Register Failed",Toast.LENGTH_SHORT).show();
}
}
});
}
}
pic 2
You can create a public path usernames where you just store the usernames that are already used and are publicly visible. When registering a new user you can check there is a username already exists. Also don't try to get all of then to check if a single one exists. Just call the path usernames/{username} and if that is null there username doens't exist. Reading all of them would blow up your Firebase bill.
I have searched all over the stack overflow but most of the solutions need to know the node names in order to run.
Even in your example, you can check if a user exists by checking the existence of the following node in the database:
root/users/$userName
In code should look like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = rootRef.child("Users");
DatabaseReference userNameRef = usersRef.child("aaaaa");
userNameRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
DataSnapshot snapshot = task.getResult();
if(snapshot.exists()) {
String fullName = snapshot.child("fullName").getValue(String.class);
Log.d("TAG", fullName);
} else {
Log.d("TAG", "The user doesn't exist!");
}
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
While #TarikHuber answer it will work, please note that in this case, it's not necessary to create an additional node to hold all usernames, since your database structure already does that. So in terms of checking if a user exists:
root/users/$userName
It's the exact same thing as:
root/usernames/$userName
Since the nodes in the Realtime Database are represented by pairs of keys and values, please note that the keys are unique. So there is no way you can have duplicate nodes. As each node can be considered a Map.
However, if by chance you can have multiple users in the database sharing the same user name, then you should use a query as in the following lines of code:
Query queryByUserName = usersRef.orderByChild("username").equalTo("aaaaa");
queryByUserName.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot ds : task.getResult().getChildren()) {
if(ds.exists()) {
String fullName = ds.child("fullName").getValue(String.class);
Log.d("TAG", fullName);
} else {
Log.d("TAG", "The user doesn't exist!");
}
}
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
According to your screenshot, in both cases, the result in the logcat will be:
james
P.S. While #ZahidIslam answer might also work, downloading the entire "Users" node and performing the check on the client is not the best option, as it's considered very costly. It's a waste of bandwidth and resources.
Edit:
According to you last comment:
I think u misunderstood me. I want to search thru all the nodes under the rootNodes
There is no way you can create a Query that can search under all nodes inside your database. You can, however, download the entire database and do the filtering on the client, but this is very costly and not recommended.
The best option that you have is to create a separate query for each and every node, but only if all the children have the same fields. Or you can keep the users only in the "Users" node (as you do right now), and the code in my answer will always work perfectly fine.
Yes you can do it by following steps .
get all username child from your DatabaseReference and add it to a ArrayList.
Check user provided username is available in ArrayList (from step 1) or not . If contains then set error , otherwise do your job to complete registration .
Update- I think you are performing button click for registration before executing / finished checkForUsername(); method. So the if...else statement not working properly and its overriding data . It was my mistake . We should perform check all users from database first then perform the next part of registration . So without using checkForUsername() method separately in onCreate() , we will do everything in button on click . check the code -
register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pd = new ProgressDialog(LoginActivity.this);
pd.setMessage("Please wait...");
pd.show();
String str_username = username.getText().toString();
String str_fullname = fullname.getText().toString();
String str_email = email.getText().toString();
String str_password = password.getText().toString();
strUsername = username.getText().toString().trim();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users/");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds : snapshot.getChildren()) {
users_from_database = (String) ds.child("username").getValue();
username_list.add(users_from_database);
StringBuilder stringBuilder = new StringBuilder();
for (String s : username_list) {
stringBuilder.append(s + "\n");
}
// Log.d("ZI", stringBuilder.toString());
if (!username_list.contains(strUsername)) {
// do your job here , suppose send verification code to phone number
if (TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_fullname) || TextUtils.isEmpty(str_email) ||
TextUtils.isEmpty(str_password)) {
Toast.makeText(LoginActivity.this, "All fields are required!", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else if (str_password.length() < 6) {
Toast.makeText(LoginActivity.this, "Password must be over 6 characters.", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else {
register(str_username, str_fullname, str_email, str_password);
}
} else {
username.setError("Username Exist");
pd.dismiss();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d("ZI", "Failed");
}
});
}
});
Update- you can check DataSnapshot exist or not . If not exist , then you can set test value to start your database . This will execute only one time . You may check -
register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pd = new ProgressDialog(LoginActivity.this);
pd.setMessage("Please wait...");
pd.show();
String str_username = username.getText().toString();
String str_fullname = fullname.getText().toString();
String str_email = email.getText().toString();
String str_password = password.getText().toString();
strUsername = username.getText().toString().trim();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users/");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (!snapshot.exists()) {
HashMap<String, Object> testHash = new HashMap<>();
testHash.put("username", "testusername");
ref.child("test")
.setValue(testHash).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
ref.keepSynced(true);
Toast.makeText(LoginActivity.this, "Please try again", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else {
Log.d("ZI", "Failed ", task.getException());
}
}
});
} else {
for (DataSnapshot ds : snapshot.getChildren()) {
users_from_database = (String) ds.child("username").getValue();
username_list.add(users_from_database);
StringBuilder stringBuilder = new StringBuilder();
for (String s : username_list) {
stringBuilder.append(s + "\n");
}
Log.d("ZI", stringBuilder.toString());
if (!username_list.contains(strUsername)) {
// do your job here , suppose send verification code to phone number
if (TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_fullname) || TextUtils.isEmpty(str_email) ||
TextUtils.isEmpty(str_password)) {
Toast.makeText(LoginActivity.this, "All fields are required!", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else if (str_password.length() < 6) {
Toast.makeText(LoginActivity.this, "Password must be over 6 characters.", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else {
register(str_username, str_fullname, str_email, str_password);
}
} else {
username.setError("Username Exist");
pd.dismiss();
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d("ZI", "Failed");
}
});
}
});

Validate if data already exist in firebase

I am trying to find if the data already exist in the database. However it doesn't enter the loop. It always go to the else
This is my validation part, it always goes to the else part
full code is in pastebin
private void validate(final String Song) {
final DatabaseReference RootRef;
RootRef = FirebaseDatabase.getInstance().getReference();
RootRef.addListenerForSingleValueEvent(new ValueEventListener()
{
public void onDataChange(DataSnapshot dataSnapshot)
{
if (!(dataSnapshot.child("Participants").child(Song).exists()))
{
HashMap<String, Object> userdataMap = new HashMap<>();
userdataMap.put("song", Song);
RootRef.child("Participants").child(Song).updateChildren(userdataMap).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task)
{
if (task.isSuccessful())
{
Toast.makeText(Register.this, "This song already exists.", Toast.LENGTH_SHORT).show();
}
}
});
}
else {
Toast.makeText(Register.this, "Your have choosed your song", Toast.LENGTH_SHORT).show();
// Toast.makeText(Register.this, "Please try again.", Toast.LENGTH_SHORT).show();
}}
public void onCancelled(DatabaseError databaseError) {
}
});
}
RootRef = FirebaseDatabase.getInstance().getReference().child("Participants").child(Song);
RootRef.addListenerForSingleValueEvent(new ValueEventListener()
{
public void onDataChange(DataSnapshot dataSnapshot)
{
if (dataSnapshot.exists())
{
Toast.makeText(Register.this, "This song already exists.", Toast.LENGTH_SHORT).show();
}
else {
HashMap<String, Object> userdataMap = new HashMap<>();
userdataMap.put("song", Song);
RootRef.setValue(userdataMap).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task)
{
if (task.isSuccessful())
{
Toast.makeText(Register.this, "This song successfully added", Toast.LENGTH_SHORT).show();
}
}
});
}}
public void onCancelled(DatabaseError databaseError) {
}
});
If you want to check exist a song, you can give it as a reference. If datasnapshot is exists then your database has the song. If not, you can add the song to the database.

Couldn't get the output "Username has been used!" when I have entered the username that has been stored in the database

This's the database structure
Database Reference
DatabaseReference referSales;
referSales = FirebaseDatabase.getInstance().getReference("Sales");
Username Validation (Including Password Validation )
referSales.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(!(edtPassword.getText().toString()).equals(edtConfirmPassword.getText().toString())) {
loadingDialog.dismiss();
Toast.makeText(Registration.this, "Password and Confirm Password are not identical!", Toast.LENGTH_SHORT).show();
if(dataSnapshot.child(edtUsername.getText().toString()).exists()){
loadingDialog.dismiss();
Toast.makeText(Registration.this, "Username has been used!", Toast.LENGTH_SHORT).show();
}
Update Database
When the username entered is not duplicated with the username stored in the database, the password and confirm password are identical, the new user information will be added to the database.
}else{
loadingDialog.dismiss();
final Sales salesperson = new Sales(edtFirstName.getText().toString(),edtLastName.getText().toString(),
edtPhoneNo.getText().toString(),edtEmail.getText().toString(), edtUsername.getText().toString(),
edtPassword.getText().toString(),edtConfirmPassword.getText().toString());
referSales.child(edtUsername.getText().toString()).setValue(salesperson).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> salesperson) {
if(salesperson.isSuccessful()){
Toast.makeText(Registration.this, "Added Successfully!", Toast.LENGTH_SHORT).show();
finish();
}
}
});
}
}
You can query the database for the to check if the username has already been used in your database.
Query query = databaseReference.child("users").orderByChild("userName")
.equalTo(edtUserName.getText().toString().trim();
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
//user exist
Toast.makeText(getApplicationContext(),"Usename Has been used" ,
Toast.LENGTH_LONG).show();
}else{
//CREATE THE USER
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Firebase get uid from email

I would like to get a uid from inputing an email for making it possible to add friends with an email.
Here is what I have gotten so far:
final DatabaseReference mRef = FirebaseDatabase.getInstance().getReference().child("users");
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
final String currentUserUid = user.getUid();
mRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild(uid)) {
DatabaseReference newRef = mRef.child(uid);
newRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.hasChild(uid)) {
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
String username = String.valueOf(dataSnapshot.child("username").getValue());
String email = String.valueOf(dataSnapshot.child("email").getValue());
String firebaseToken = String.valueOf(dataSnapshot.child("firebaseToken").getValue());
Friend friend = new Friend(uid, username, email, firebaseToken);
database.child(Constants.ARG_USERS)
.child(currentUserUid)
.child(Constants.ARG_FRIENDS)
.child(uid)
.setValue(friend)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
mOnFriendDatabaseListener.onSuccess(context.getString(R.string.friend_successfully_added));
} else {
mOnFriendDatabaseListener.onFailure(context.getString(R.string.friend_unable_to_add));
}
}
});
} else {
Log.d("Adding Friend", "User already not exist");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
} else {
Log.d("Adding Friend", "User does not exist");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
This works if I input an uid directly but I would like to have my input be an email and get an uid out from it, or if there are other solutions please suggest.
This is how the database structure looks like:
Thanks for the help in advance.
To search for a user by their email address you need to order/filter on that property:
Query query = mRef.orderByChild("email").equalTo("example#example.com");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// There may be multiple users with the email address, so we need to loop over the matches
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
System.out.println(userSnapshot.getKey());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "find email address:onCancelled", databaseError.toException());
// ...
}
});
Not directly related to the question, but please restructure your data to remove the nesting of friends and profiles. For many reasons it's best to keep your Firebase data structure flat and separate user profiles from friends lists.
/users
uid1: ... profile for user 1
uid2: ... profile for user 2
/friends
uid1: ... friends list for user 1
uid2: ... friends list for user 2

Categories

Resources