Firebase Realtime Database retrieve last-child data - java

I'm trying to retrive the data of the last-child in my Firebase Database.
.
What I would like to do is to add another Records child, that is called like the last-child id-number, increased by 1.
So in this specific case, for example, I want to create a child called "3", with all its relative fields (id, months, name, time).
I've tried with the following code, but when I run it, it never enters in the addListenerForSingleValueEvent(), and I don't know why. It doesn't give me any error, but it simply doesn't enter in the method.
String name = Joe;
int months= 5;
long time = 10;
FirebaseDatabase database = FirebaseDatabase.getInstance("db-uri");
DatabaseReference myRef = database.getReference().child("Records");
myRef.limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
int last_db_user = dataSnapshot.child("id").getValue(Integer.class);
int new_user = last_db_user++;
//The User class is just a class that helps setting the values in the db
User user = new User(new_user, name, months, time);
String key = String.valueOf(new_user);
myRef.child(key).setValue(user);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
I've also tried writing it like the following but, despite the fact that this time it enters in the addListenerForSingleValueEvent(), it says that it can't execute the toInteger() method because the object is null.
myRef.child("Records").limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
int last_db_user = dataSnapshot.child("id").getValue(Integer.class);
int new_user = last_db_user++;
//The User class is just a class that helps setting the values in the db
User user = new User(new_user, name, months, time);
String key = String.valueOf(new_user);
myRef.child(key).setValue(user);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
Any ideas on how can I make this work?
UPDATE
String name = Joe;
int months= 5;
long time = 10;
FirebaseDatabase database = FirebaseDatabase.getInstance("db-uri");
DatabaseReference myRef = database.getReference().child("Records");
myRef.orderByChild("id").limitToLast(1).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
for (DataSnapshot snapshot: dataSnapshot.getChildren()) {
int last_db_user = snapshot.child("id").getValue(Integer.class);
int new_user = last_db_user++;
//The User class is just a class that helps setting the values in the db
User user = new User(new_user, name, months, time);
String key = String.valueOf(new_user);
myRef.child(key).setValue(user);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
With this code I get the following exception:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.app, PID: 28429
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
at game.GameLogic$1.onDataChange(GameLogic.java:318)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database##19.2.1:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database##19.2.1:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database##19.2.1:55)
at android.os.Handler.handleCallback(Handler.java:900)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8393)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)

It doesn't give me any error
Well, that might be because you're ignoring errors. Please always implement onCancelled, which at its minimum should be:
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
The second problem is that you're not ordering on anything, which makes it unclear what limitToLast(1) actually works on. While this may work, you should always specify an ordering. Here that seems:
myRef.orderByChild("id").limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
...
The next problem: when you execute a query against the Firebase 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.
You need to handle this list in your onDataChange by looping over snapshot.getChildren(). So:
myRef.limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren()) { // 👈
int last_db_user = snapshot.child("id").getValue(Integer.class);
int new_user = last_db_user++;
//The User class is just a class that helps setting the values in the db
User user = new User(new_user, name, months, time);
String key = String.valueOf(new_user);
myRef.child(key).setValue(user);
}
}

Related

How to update an array item in the Realtime Database from within Android

How to access a child inside real time database array child?
String count = item_count.getText().toString();
firebaseDatabase = FirebaseDatabase.getInstance();
reference = firebaseDatabase.getReference()
reference.child("beverages").child(????)
.child("item_count").setValue(count);
this is my code but I don't know what should I put in the question
marks.
]1
You can get the item_count by using foreach loop inside the onDataChange method.
Lets say this is your model class for your Beverage.
public class Beverage {
private long item_count;
private String item_img;
private String item_name;
public Beverage beverage(long itemCount){
this.item_count = itemCount;
//and do others also...
}
//Here your get set...
}
Here you get the data as arrayList
reference.child("beverages").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
ArrayList<Beverage> beveragesList = new ArrayList<Beverage>();
//Get children
for (DataSnapshot snapShot : dataSnapshot.getChildren()) {
if (snapShot.exists()) {
final Beverage beverage = snapShot.getValue(Beverage.class);
if (beverage != null){
//Her you got the data as array list
beverageList.add(beverage);
}
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.i("???","Db error: " + databaseError.getMessage());
}
});
You need to put child of beverages here like 0,1,2, or 3.
reference.child("beverages").child("3").child("item_count").setValue(count);

How to retrieve Specific Data from Firebase Realtime Database?

I have been trying to retrieve data from Firebase Realtime Database, but somewhere it's going wrong.
Here is the screenshot of database
I want to retrieve all the Question(Question1,Question2,etc) data under "CS102" node and store it in arraylist.
I tried doing it in a few ways:
reference = FirebaseDatabase.getInstance().getReference().child("CreateQuizQuestions").child(code);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull #NotNull DataSnapshot snapshot) {
if(snapshot.exists()) {
for(DataSnapshot ds:snapshot.getChildren()){
String QuizName=ds.child("QuizName").getValue().toString();
String TotalQuestions=ds.child("TotalQuestions").getValue().toString();
String ques=ds.child("Question").getValue().toString();
String option1=ds.child("Option1").getValue().toString();
String option2=ds.child("Option2").getValue().toString();
String option3=ds.child("Option3").getValue().toString();
String option4=ds.child("Option4").getValue().toString();
String correctAnswer=ds.child("CorrectAnswer").getValue().toString();
GetQuestion getQuestion=new GetQuestion(ques,option1,option2,option3,option4,correctAnswer);
list.add(getQuestion);
Log.d("Data Values: ","Question:"+list.get(0).question+" Option1: "+list.get(0).option1);
Log.d("Inner Size Tag","Size of list: "+list.size());
}
} else {
Toast.makeText(getApplicationContext(),"No Data",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull #NotNull DatabaseError error) {
}
});
But somewhere it's going wrong
Please help me in finding the solution
Like this, you should be able to gather the info of all "Question1" nodes. You will have to do this for each "Question2", "Question3" node. If for example "Question2" node has different children, you won't have to use same number of variables to retrieve the data. Of course you must add another event listener because database reference will be different. If your other question children have same number of children (answer, optrion1, 2,3,4 and question) you can use the for loop I have shown you before. Hope this works for you!!!
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("CreateQuizQuestions").child("CS102").child("Question1");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull #NotNull DataSnapshot snapshot) {
if(snapshot.exists())
{
String answer=snapshot.child("Answer").getValue().toString();
String op1=snapshot.child("Option1").getValue().toString();
String op2=snapshot.child("Option2").getValue().toString();
String op3=snapshot.child("Option3").getValue().toString();
String op4=snapshot.child("Option4").getValue().toString();
String q=snapshot.child("Question").getValue().toString();
//GetQuestion getQuestion=new GetQuestion(ques,option1,option2,option3,option4,correctAnswer);
//list.add(getQuestion);
//Log.d("Data Values: ","Question:"+list.get(0).question+" Option1: "+list.get(0).option1);
//Log.d("Inner Size Tag","Size of list: "+list.size());
}
else
{
Toast.makeText(getApplicationContext(),"No data",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull #NotNull DatabaseError error) {
}
});
}

How to count number of particular child occurrence in firebase for Android in Java

I am making an attendance app and I need to count the particular student attendance from the Firebase. I need to count the number of "prof" occurrence and I am new to this.
DatabaseReference attendance = FirebaseDatabase.getInstance().getReference("Attendance");
attendance.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
totaldays++; // total class days
if(snapshot.child("name").getValue(String.class).equals("prof")){
//count no of days present
}
Log.e(snapshot.getKey(), snapshot.getChildrenCount() + "");
}
Log.e(TAG, totaldays + "");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
But the result is showing null value.
In order to solve this, you need to change your database structure. You cannot query your database since your nodes are dynamically generated. As #FrankvanPuffelen mentioned in his comment, the nodes that are causing you troubles are: 04Jul2018 with dcbch... and 05Jul2018 with hello. Because Firebase can only return results that are at a fixed path under each child of the node, to solve this, I recommend you create the date as a property. This is how it can be done and this is how your database structure should look like:
Firebase-root
|
--- dcbch..._dkjh...
|
--- Prof
|
--- email: "profeamil#gmail.com"
|
--- name: "prof"
|
--- present: true
|
--- date: 1530784439 //Current timestamp
And here is the corresponding query:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.orderByChild("Prof/name").equalsTo("prof");
Now you can attach a listener and use getChildrenCount() method on the DataSnapshot object to get the number of occurrence.
If there is a prof occurrence you can add that child data in a list. In this way you can get the number of childs by using list.size() and also use this list of data in other operations if you have.
its very simple to count any field child in the root reference
for example you have a root name attendance then you count to name where type is professor
databaseReference = FirebaseDatabase.getInstance().getReference().child("Attendance").child(istrustnumberavailable);
databaseReference.limitToFirst(5);
Query query = databaseReference.orderByChild("name").equalTo("prof");
ChildEventListener removedListener = query.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if (dataSnapshot.exists()){
long count= dataSnapshot.getChildrenCount();
}
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if (dataSnapshot.exists()){
long count= dataSnapshot.getChildrenCount();
}
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
long count= dataSnapshot.getChildrenCount();
}
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Getting values from Posts

How would I loop through, and get these values from the Posts node? I'm still new to Firebase... Also using Java.
I'm targeting the specific user key, by:
mPostsRef.child(userKey)
Thank you!
To get the body and title, try the following:
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Posts").child(userKey);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
String body=datas.child("body").getValue().toString();
String title=datas.child("title").getValue().toString();
}
}
#Override
public void onCancelled(DatabaseError error) {
}
});
The snapshot will be at direct key under the node Posts then you can loop inside the random keys and get the values of body and title.

How can I retrieve values from Firebase database based on email entered by user in text field?

I am working on Firebase database. How can I retrieve values from database based on email entered by user in text field. Below is my database structure. Kindly help.
Here is my code:
Ref = database.getReference("Registeration");
Ref.orderByChild("UserRegistration/email").equalTo(emailval).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
user_reg user=dataSnapshot.getValue(user_reg.class);
Toast.makeText(getApplicationContext(), user.toString(), Toast.LENGTH_SHORT).show();
}
You have:
Registration
UserRegistration
12
pushid
key:values
email:emailvalue
To retrieve values always you have to go from top to bottom, so you cannot skip any node.
Only orderByChild(..) query can skip one node (which means you use this query if you want to get children that are not direct children)
Try this:
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Registration").child("UserRegistration").child("12");
ref.orderByChild("email").equalTo(emailenteredbyuser).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot datas : dataSnapshot.getChildren()) {
String email=datas.child("email").getValue().toString();
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
As you can see in the above, the reference passes through every node until node 12.
Then you use this orderByChild("email").equalTo(emailenteredbyuser) to get the email entered by the user.
for (DataSnapshot datas : dataSnapshot.getChildren()) this for loop the datas iterates in inside the direct children of 12 which is the pushid that way you do not need to retrieve the pushid to get the values inside of it.
Try this! here I am running for each loop to get each child.
Ref.child("UserRegistration").child("email").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot:dataSnapshot.getChildren()){
user_reg user=dataSnapshot.getValue(user_reg.class);
System.out.println(user.email);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Categories