I am developing an Attendance App. I want to retrieve students list with number of presents and populate it in a list view.
I have tried the below code but i am getting number of presents of one specific student.
DatabaseReference ref =
FirebaseDatabase.getInstance().getReference().child("Students
Attendance").child(selectedItem).child(id).child(subject);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() != null) {
Userlist.add(dataSnapshot.getValue().toString());
addStudents(Userlist);
}else {
Toast.makeText(getApplicationContext(), "****NO Record
FOUND****", Toast.LENGTH_LONG).show();
}
}
I expect the output as a list of students with their number of presents populated in list view.
My firebase Structure
I want this kind of result
Since you are making an app that counts a number of presents of a particular student. You can do it this way:
First you can set the value to be stored in the database as :
mFirebaseDatabaseReference.push().setValue(new String[]{student_name,attendance})
This stores the data as :-
Sam,70 and
Mike,75
Now retrive that data using ChildEventListener:
mChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
String data = dataSnapshot.getValue();
mMyAdapter.add(data);
);
One thing to not here is that, you dont necessarily need to put the student_id as we using the push() method here so it gives every child a new id so that we don't have to worry about the data being disturbed for students with the same name or marks.
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot.exists()) {
String value = dataSnapshot.getValue().toString();
String key = dataSnapshot.getKey();
String record = key + ": " + value;
Userlist.add(record);
addStudents(Userlist);
}
It worked for me.
Related
I want to get data from firebase without changing my database structure because I have two condition:
When admin logins then he can see all employees data for the selected year or say year-wise.
But when employees login then they should be able to see their individual data from all the years using employee code, which is a child also (blue tick in the picture).
Below is my database structure:
The child marked in red is unknown in case of employee's access and the blue tick denotes an employee who may be present in every year.
All I want is to achieve the 2nd condition. But I am unable to get the data.
Here is my code:
private void retrieveData() {
final String shift = kvName.getText().toString();
final String employeeCode = empCode.getText().toString();
dbRef.child("Apar").child(shift);
dbRef.orderByChild(employeeCode).equalTo(employeeCode).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot datas1 : dataSnapshot.getChildren()) {
for (DataSnapshot datas2 : datas1.getChildren()) {
// String aparGrading= datas2.getKey(); //unable to figure out how to get
// Toast.makeText(Apar.this, aparGrading, Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Your current data structure makes it easy to find the information for all employees for a specific year. It does however not make it easy to find the information for a specific employee across all years.
To do the latter, you have two options:
Check each year for the presence of a node for that employee ID.
Add an additional data structure that maps from each employee ID to the years for which they have data, and then load each year's data for that employee individually
For more on this, also see:
Many to Many relationship in Firebase
Firebase query if child of child contains a value
Firebase Query Double Nested
Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly, to learn why the second approach is not as slow as you may think.
After reading the various answers on this topic linked above by Mr. #Frank van Puffelen and spending some times over it, the problem is finally solved now without changing my database structure.
Below is screenshot of the result which I wanted:
Here is my modified and working code :
private void retrieveData() {
final String shift = kvName.getText().toString();
final String employeeCode = empCode.getText().toString();
final DatabaseReference aparRef = dbRef.child("Apar").child(shift);
aparRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
list = new ArrayList<>();
if (dataSnapshot.exists()) {
for (DataSnapshot dataS1 : dataSnapshot.getChildren()) {
if (dataS1.hasChild(employeeCode)) {
AparData aparData = dataS1.child(employeeCode).getValue(AparData.class);
list.add(aparData);
rvAPAR.setHasFixedSize(true);
rvAPAR.setLayoutManager(new LinearLayoutManager(Apar.this));
rvAPAR.setItemAnimator(new DefaultItemAnimator());
aparAdapter = new AparAdapter(Apar.this, list);
rvAPAR.setAdapter(aparAdapter);
} else {
Toast.makeText(Apar.this, "No Data Found!!", Toast.LENGTH_SHORT).show();
}
}
} else {
Toast.makeText(Apar.this, "Not Data Found!!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
The data is saved correctly, as you can see in the following image:
I use this code:
btnDatos.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String name = nameTextView.getText().toString();
String email = emailTextView.getText().toString();
String id = idTextView.getText().toString();
String idJuego = idffTextView.getText().toString();
Map hopperUdates = new HashMap();
hopperUdates.put("name", name);
hopperUdates.put("email", email);
hopperUdates.put("id", id);
hopperUdates.put("idFreeFire", idJuego);
mDatabase.child("Usuario").child(mAuth.getCurrentUser().getUid()).updateChildren(hopperUdates);
}
});
And to obtain the data I use the following code:
mDatabase.child("Usuario").child(mAuth.getCurrentUser().getUid()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
int idJuego = dataSnapshot.getValue(Integer.class);
idffTextView.setText(idJuego);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
But it does not show the data and when I test it on the device the app is closed. What would be the error?
If you want all data then create model class and then stored datasnapshot into that model class like this
Model model = dataSnapshot.getValue(Model.class);
Or you want single data then just get the child like this
String idJuego = dataSnapshot.child("childname").getValue().toString;
And then set that string into textView.
try to convert from Integer to string...
int idJuego = dataSnapshot.getValue(Integer.class);
idffTextView.setText(String.valueOf(idJuego ));
Because you are saving the uid as the key of your user object and in the same time as a property within the user object, to set that id to your idffTextView, please use either the following lines of code:
String idJuego = dataSnapshot.getkey();
idffTextView.setText(idJuego);
Or:
String idJuego = dataSnapshot.child("id").getValue(String.class)
idffTextView.setText(idJuego);
Please note, that in both cases the id is of type String and not int.
I am working on an application similar to tinder but to help users to find people to play a specific sport with.
I currently have the code searching the database for the gender of the users (that the user can be matched with). However each user in the database has a node that contains all of the sports the user can pick. If the user prefers a sport the value is saved as 'true' and if not, the value is saved as 'false'. The appropriate users are then shown on the app.
A screenshot of the database is shown below:
This is the code I have so far:
public void checkUserSex(){
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference userDb = usersDb.child(user.getUid());
userDb.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
if (dataSnapshot.child("sex"). getValue() != null){
userSex = dataSnapshot.child("sex").getValue().toString();
switch (userSex){
case "Male":
oppositeUserSex = "Female";
break;
case "Female":
oppositeUserSex = "Male";
break;
}
getOppositeSexUsers();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
public void getOppositeSexUsers(){
usersDb.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot.child("sex").getValue() != null) {
if (dataSnapshot.exists() && !dataSnapshot.child("connections").child("pass").hasChild(currentUId) && !dataSnapshot.child("connections").child("play").hasChild(currentUId) && dataSnapshot.child("sex").getValue().toString().equals(oppositeUserSex)) {
String profileImageUrl = "default";
if (!dataSnapshot.child("profileImageUrl").getValue().equals("default")) {
profileImageUrl = dataSnapshot.child("profileImageUrl").getValue().toString();
}
cards item = new cards(dataSnapshot.getKey(), dataSnapshot.child("name").getValue().toString(), profileImageUrl);
rowItems.add(item);
arrayAdapter.notifyDataSetChanged();
}
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
How do I change it from matching gender to matching the selected sport?
Unfortunately, Firebase Realtime database does not allow a query based on multiple properties. To achieve what you want, you don't need to restructure your database entirely, you just need to change it a little bit. To solve this problem, you need to add a new node for each sport. Every time you add a new user which plays golf, add it also in its corresponding sport node. Your new node should look like this:
Firebase-root
|
--- golfPlayers
|
--- userId1 : true
|
--- userId2 : true
With this structure you can query your database to get only the users who are playing golf. This can be done by attaching a listener on golf node and iterate on the DataSnapshot object.
This practice is called denormalization and is a common practice when it comes to Firebase. For a better understanding, I recommend you see this video, Denormalization is normal with the Firebase Database.
Note, what you are trying to do and cannot be solved using Firebase Realtime database, can be solved using Cloud Firestore. Give it a try.
How Can I get ArrayList of Java Objects of all Childs from Firebase using updated firebase commands, currently I am using below approach but not able to get the list.
ValueEventListener postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get Post object and use the values to update the UI
if(dataSnapshot!=null){
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
UserDataClass post = postSnapshot.getValue(UserDataClass.class);
members.add(post);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
}
};
mDatabaseRef.addValueEventListener(postListener);
below is datasnapshot which is returning from firebase but I am not able to get the desired result out of it.
DataSnapshot { key = 12345, value = {Members={00000000={phoneNo=00000000, longitude=73.0703307, latitude=33.6396975, password=qwertyuiop, CName=00000000, admin=true, name=Anwar Kamal}, 03028084374={phoneNo=03028084374, longitude=73.0701292, latitude=33.6397129, password=qwerty, CName=00000000, admin=false, name=Nehal Khan}, 03028084516={phoneNo=03028084516, longitude=73.0702659, latitude=33.6397622, password=qwerty, CName=03035356317, admin=false, name=Jamal Khan}}} }
all i want is list of all members
and my java object is
public class UserDataClass {
public double latitude;
public double longitude;
public String Name="";
public String password="";
public String phoneNo="";
public String CircleName="";
public boolean isAdmin=false;
}
The ValueEventListener has another purpose.
You should use ChildEventListener and also dataSnapshop.getValue() to implement what you want, for example:
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
UserDataClass post = postSnapshot.getValue(UserDataClass.class);
members.add(post);
}
//...
Note:
You should use the listener with the current firebase_referance to the Users table. Hence you should replace
mDatabaseRef.addValueEventListener(postListener);
with
mDatabaseRef.child("Members").addChildEventListener(childEventListener);
notice that your full path of the Members table is colored and i couldn't figure the path.
You can find the whole documentation here
good luck
I am writing an Android app and I am trying to retrieve an object of the class User.java by ID from its Firebase pertinent table. I would like to know how to get it from Java side, as long as I tried the examples stated in Firebase Official docs but none of them is working for me.
Taking this SO question as example, I want a method with the following interface:
public User readUser(String userId);
In other words, I want to execute:
readUser(-lnnROTBVv6FznK81k3n)
and retrieve the associated User object
Thanks
--------------------------------------------------------------EDIT--------------------------------------------------------------:
I managed to get the value with this code:
public void retrieveUser(final String email){
firebaseUsersRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot messageSnapshot: dataSnapshot.getChildren()) {
if(messageSnapshot.getKey().equals(Email.encodeID(email))){
retrievedUser = messageSnapshot.getValue(User.class);
break;
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) { }
});
}
Please not retrievedUser is a class attribute, thus a field. I am accessing that field from the code, but even I see it takes the value on the debugger, it is being null on the calling code.
Any hint? CanĀ“t I just return it in the method itself, so it would be?:
public User retrieveUser(final String email);
Thanks
so here is the soultion, I didn't put it in a method though.
final String uid = "your Uid here";
// Get a reference to users
Firebase ref = new Firebase(Constants.FIREBASE_URL_USERS);
// Attach an listener to read our users
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot user: snapshot.getChildren()) {
//this is all you need to get a specific user by Uid
if (user.getKey().equals(uid)){
wantedUser = user.getValue(User.class);
}
//**********************************************
}
Log.i(TAG, "onDataChange: " + wantedUser.getName());
}
#Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});