So, I recently learn about firebase database, and now i'm able to insert a data. I have this script which is to store data to my firebase .
mDatabase = FirebaseDatabase.getInstance().getReference("Biodata");
String userId = mDatabase.push().getKey();
Biodata bio = new Biodata("MyUser", "MyUser#email.com");
mDatabase.child(userId).setValue(bio);
The script above is in oncreate, so when i run the activty again and again the data will insert twice or more
and here is my firebase
Biodata
-LAuyJho4kTnJt5WuCtJ
Email: "MyUser#email.com"
Fullname: "MyUser"
My bidata class
#IgnoreExtraProperties
public class Biodata {
public String Fullname;
public String Email;
public Biodata() {
}
public Biodata(String Fullname, String Email) {
this.Fullname = Fullname;
this.Email = Email;
}
}
So, how can i prevent my app to insert same data twice ?
Please try below code may help you
public void setData(){
final DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference();
Query queryToGetData = dbRef.child("Biodata")
.orderByChild("Email").equalTo("MyUser#email.com");
queryToGetData.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(!dataSnapshot.exists()){
String userId = dbRef.child("Biodata").push().getKey();
Biodata bio = new Biodata("MyUser", "MyUser#email.com");
dbRef.child("Biodata").child(userId).setValue(bio);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
First of all, you don't have to call it on the onCreate method. But theres another easy way for not creating duplicates. You have to create a random key for each user. Like, say emails id is unique for all users. So
mDatabase = FirebaseDatabase.getInstance().getReference("Biodata");
Biodata bio = new Biodata("MyUser", "MyUser#email.com");
mDatabase.child("MyUser#email.com").setValue(bio);
In this way, the user's details are under their own email id. It will be easier for u to get the details too. Also, this will not create duplicates, since the email id is unique. In firebase it will look like this:
Biodata
MyUser#email.com
Email: "MyUser#email.com"
Fullname: "MyUser"
So later if you want to get the users name, you just have to
DatabaseReference ref= mDatabase.child("MyUser#email.com");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Biodata bio = dataSnapshot.getValue(Biodata .class);
// and bio.getName() for getting the name
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You should not add the email as a parent node or you will get an error.
First you are adding data twice, it is because you have this under onCreate(), it should be under a button or any event that can occur.
Second, you are generating a random id using push() so every time onCreate() is invoked new data will be added since push() is used to separate records.
To prevent this problem, add the creation of a user under a button (example under a Sign up button).
If you want to keep it under onCreate() then do the following:
mDatabase = FirebaseDatabase.getInstance().getReference("User");
FirebaseUser user=FirebaseAuth.getInstance().getCurrentUser();
String userId=user.getUid();
Biodata bio = new Biodata("MyUser", "MyUser#email.com");
mDatabase.child(userId).setValue(bio);
The above will work if you use firebase authentication and also after login of the user. The getUid() will retrieve the user id from the firebase authentication which is unique for each user. Then you will be able to add it to the database.
Related
I need to get the specific user data using the user email on the real time database. This is my code, This code running without errors but the data is not display in the interface.I think datasnapshot retrieving part is not correct. please help me to solve this.
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String userEmail = user.getEmail();
DatabaseReference rootReference = FirebaseDatabase.getInstance().getReference();
Query myUsersQuery = rootReference.child("Children").orderByChild("childrenParentEmail").equalTo(userEmail);
myUsersQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("Children").getValue(String.class);
childrenNameEdt.setText(name);
childrenBirthdayEdt.setText(dataSnapshot.child("childrenBirthday").getValue(String.class));
childrenParentNameEdt.setText(dataSnapshot.child("childrenParentName").getValue(String.class));
childrenParentAddressEdt.setText(dataSnapshot.child("childrenParentAddress").getValue(String.class));
childrenParentContactNumberEdt.setText(dataSnapshot.child("childrenParentContactNumber").getValue(String.class));
childrenParentEmailEdt.setText(dataSnapshot.child("childrenParentEmail").getValue(String.class));
childrenTransportTypeEdt.setText(dataSnapshot.child("childrenTransportType").getValue(String.class));
childrenTransportContactNumberEdt.setText(dataSnapshot.child("childrenTransportContactNumber").getValue(String.class));
//childrenID.setText(dataSnapshot.child("password").getValue(String.class));
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});
When you execute a query against the Firebase Realtime Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
Your code will need to handle that list, by looping over dataSnapshot.getChildren(). So something like:
myUsersQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren();
String name = snapshot.child("Children").getValue(String.class);
childrenNameEdt.setText(name);
...
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Based on logged in user i want to display their information like name, address, bloodgroup etc.
My database structure is like the below.
Donor:
O+:
einsein:
name: einstein
email: einstein#gmail.com
bloodgroup: O+
age: 20
address: 11/237
A-:
thamizh:
name: thamizh
email: thamizh#gmail.com
bloodgroup: A-
age: 21
address: 11/23.
public class userinfo extends AppCompatActivity {
TextView t1,t2,t3,t4,t5;
DatabaseReference oref;
FirebaseAuth auth;
FirebaseUser user;
String uid,email;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_userinfo);
auth = FirebaseAuth.getInstance();
user = auth.getCurrentUser();
uid = user.getUid();
email = user.getEmail();
t1 = (TextView) findViewById(R.id.l11);
t2 = (TextView) findViewById(R.id.l22);
t3 = (TextView) findViewById(R.id.l33);
t4 = (TextView) findViewById(R.id.l44);
t5 = (TextView) findViewById(R.id.l55);
oref = FirebaseDatabase.getInstance().getReference().child("Donor");
oref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("donorID").getValue().toString();
String bldgrp = dataSnapshot.child("bloodgroup").getValue().toString();
String mob = dataSnapshot.child("mobile").getValue().toString();
String eid = dataSnapshot.child("email").getValue().toString();
String add = dataSnapshot.child("address").getValue().toString();
t1.setText(name);
t2.setText(bldgrp);
t3.setText(mob);
t4.setText(eid);
t5.setText(add);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Right now your code is loading all users from the database, and then tries to read the properties for one of those users from the /Donor node. That won't work.
At the very least you'll need to loop over the users in your onDataChange:
oref = FirebaseDatabase.getInstance().getReference().child("Donor");
oref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshots) {
for (DataSnapshot dataSnapshot: snapshots.getChildren()) {
String name = dataSnapshot.child("donorID").getValue().toString();
String bldgrp = dataSnapshot.child("bloodgroup").getValue().toString();
String mob = dataSnapshot.child("mobile").getValue().toString();
String eid = dataSnapshot.child("email").getValue().toString();
String add = dataSnapshot.child("address").getValue().toString();
t1.setText(name);
t2.setText(bldgrp);
t3.setText(mob);
t4.setText(eid);
t5.setText(add);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
The above code still gets all child nodes from /Donor, but now loops through them and sets the properties in the text view. Since you only have text views for one user, you are overwriting the previous values each time. So in the end you'll have the properties for the last user from the JSON. That's not what you want, but at least it's better than what you currently have.
Next up is loading only the data for the single user that you want to display. This requires that you can identify that single user.
The most common way to do this, is to store the data in your database under the UID of that user. So:
Users: {
"uidOfUser1": { ... },
"uidOfUser2": { ... },
"uidOfUser3": { ... }
}
With this type of structure you can get a reference to the data for the currently signed in user with:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
oref = FirebaseDatabase.getInstance().getReference()
.child("Donor")
.child(uid);
If you add the listener to this reference, you can remove the loop we just added, since you're only loading data for one user.
That leaves the question: what to do if you didn't store the user info under their UID?
In that case, I'd recommend first considering restructuring the data, as storing user data under UIDs is the idiomatic way to get fast and easy lookups.
But sometimes you really can restructure, and in that case you can perform a database query to find the node(s) for a user. To be able to use a query, you must know the value of one (preferably unique) property of the user.
Say that you know their email address. You can then get the node(s) for that email address with:
FirebaseDatabase.getInstance().getReference()
.child("Donor")
.orderByChild("email").equalTo("einstein#gmail.com");
When you attach your listener to this query, you may get multiple results again, so you need the same for loop that we added above.
Initially, I wrote a code to store the value in Firebase realtime database.
mDbRef = mDatabase.getReference().child("Users");
mDbRef.child("name").setValue(rname);
mDbRef.child("email").setValue(remail);
The child value was stored under its Uid in 'Users' child.
Then I changed the code to
String name = userName.getText().toString();
mDbRef = mDatabase.getReference().child("Users").child(name);
mDbRef.child("name").setValue(rname);
mDbRef.child("email").setValue(remail);
Now, the child value was stored under its name in 'Users' child.
Now I have two issues,
If I add same name with different sub child values, it was not accepted. How to rectify it?
I wrote the following code to check user before starting an activity.
public void checkUserExists () {
final String user_id = Objects.requireNonNull(uAuth.getCurrentUser()).getUid();
mDbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild(user_id)) {
startActivity(new Intent (LoginActivity.this, HomeActivity.class));
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
The new Intent activity was working fine when the child was under Uid. When it was changed to 'name' in lieu of Uid, the intent activity doesn't start. But if I restart the app after closing it, it directly goes to Home activity. What should be done to rectify the issue?
May I suggest something like that:
String key = mDatabase.child("users").push().getKey();
// key is generated by Firebase and is unique
mDbRef = mDatabase.getReference().child("users").child(key);
mDbRef.child("name").setValue(rname);
mDbRef.child("email").setValue(remail);
And check the documentation
happy to help!
I currently have a users collection in my Firebase real-time database that contains all my users and a collection that contains the name of books and the ratings(number of thumbs up and down). I am trying to make a application that will display book titles constantly(or the ones that are in my db) so that people can rate them, however I need to be able to check if a user has already viewed this book title or not(this is the part i need help with). Can someone help me with pulling the data from Firebase and comparing it to see if the user has viewed this book title or not. This is what my db setup looks like
Also if someone has a better way of doing this please explain!!!
First, change books_viewed into an array. Read this for arrays in Firebase Realtime Database
Now that it's an array, you can get that as a ArrayList<String> in your app.
public class User {
public ArrayList<String> booksViewed;
... // Other variables
}
Then just use the contains function to check if the book you need to find is in that list
DatabaseReference userRef = FirebaseDatabase.getInstance().getReference().child("Users").child("<UserID>")
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
String bookTitleYouAreChecking = "Twilight"
if (user.booksViewed.contains(bookTitleYouAreChecking)) {
// User has viewed
} else {
// User has not viewed
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// ...
}
})
To solve this, please use the following method that checks if a user had viewed a book or not:
private void checkBookTitle(String bookTitle) {
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = rootRef.child("Users").child(uid).child("books_viewed");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue().equals(bookTitle)) {
Log.d(TAG, "User has viewed this book");
} else {
Log.d(TAG, "User has not viewed this book");
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
};
ref.addListenerForSingleValueEvent(valueEventListener);
}
This is pretty direct forward but I have a problem with multiple users.When the first user signs in,his name and email are fetched with no issues but when he signs out and another user signs in (same phone), current user details return null.
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
String uid = Objects.requireNonNull(firebaseAuth.getCurrentUser()).getUid();
userDetails = FirebaseDatabase.getInstance().getReference().child("Users").child(uid);
myref.keepSynced(true);
userDetails.keepSynced(true);
name = view.findViewById(R.id.my_name);
mail = view.findViewById(R.id.my_mail);
userDetails.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String Name = dataSnapshot.child("name").getValue().toString();
String Email = dataSnapshot.child("email").getValue().toString();
name.setText(Name);
mail.setText(Email);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Turns out the code is fine, only problem is my firebase structure. The first user "email" and "name" are in lowercase, the rest start with a capital letter users node, firebase Image