Below i have attached the firebase table... here i have to list the child of date (chat2,chat1 from 1312206 followed by chat3,chat2,chat1 from 12122016).
Please anyone help how to query the data.Thanks in advance.
You need to point to the correct node and then just attach a listener where you will get the callback.
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Chat chat = dataSnapshot.getValue(Chat.class);
// do stuff
}
#Override
public void onCancelled(DatabaseError databaseError) {
// do stuff when there is an error
}
}
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference chatNode = database.child("chat_room").child("12122016").child("chat1")
chatNode.addValueEventListener(eventListener);
With this listener you'll be notified whenever there is an update on that node.
You can find more information in Firebase documentation.
Related
I have users on my Application and I store additional information about them in Firebase Database. I need to retrieve additional information in more than one Activity. I do not want to use ValueEventListeners because they are not called unless there is any change in the database. How can I get information about users from Database without using ValueEventListeners?
In my ProfileFragment I need to get name and departmant values.
I get current user from Firebase and I tried to take other information with a function.
talker = new DatabaseTalk();
FirebaseUser currentUser = mAuth.getCurrentUser();
// Get info of logged in user with talker.
loggedInUser = talker.getUserFromID(currentUser.getUid());
This is my DatabaseTalker class to handle read and write operations to database
public class DatabaseTalk {
private FirebaseDatabase mDatabase;
private DatabaseReference UserRef;
private DatabaseReference SurveyRef;
private List<User> userList;
public DatabaseTalk(){
mDatabase = FirebaseDatabase.getInstance();
UserRef = mDatabase.getReference("users");
UserRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot child: dataSnapshot.getChildren()){
userList.add(child.getValue(User.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w("Error", "Failed to read value.", databaseError.toException());
}
});
SurveyRef = mDatabase.getReference("surveys");
}
public void WriteUser(User usr){
UserRef.child(usr.getUserID()).setValue(usr);
}
public void WriteSurvey(Survey survey){SurveyRef.push().setValue(survey);}
public User getUserFromID(String id){
for(User usr: userList){
if(usr.getUserID().equals(id))
return usr;
}
return null;
}
}
I think, I can take additional information about users from userList in DatabaseTalk but userList is null always.
EDIT
I changed getUserFromID method. OnDataChange() does not work when I called getUserFromID method.
public User getUserFromID(String id){
DatabaseReference newRef = mDatabase.getReference("users");
DatabaseReference ds = newRef.child(id);
ds.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userList.add(dataSnapshot.getValue(User.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return userList.get(0);
}
I solved the problem. It turned out I do not know how Firebase works actually. Since onDataChange() make async calls, writing Listener definitions on a function is useless because onDataChange mostly does not trigger before function terminates and this cause function to return null value.
I make the definition of ValueEventListeners in onCreate methods. It triggers now after few seconds my ProfileFragment created. I think it is better to use Progress Dialogs to wait.
Thanks to everyone who interested in the question.
I am trying to retrieve a list of friends for a user so I can display them in a list view. The friends and user info is structured like this in my firebase database:
So basically, I want to take the user ids listed in the friends part and query my users data to get all the info under every node that is in that set of user ids. How can I achieve this using the android firebase database sdk querying? I would like to be able to retrieve all the users in a single database query.
Thanks.
You cannot get that data in single query, you need to query your database twice. This is a common practice when it comes to Firebase. Assuming that friends and users nodes are direct childs of your Firebase root, to achieve this, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference friendIdRef = rootRef.child("friends").child(friendId)
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String key = ds.getKey();
DatabaseReference usersRef = rootRef.child("users").child(key);
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot dSnapshot : dataSnapshot.getChildren()) {
String username = dSnapshot.child("username").getValue(String.class);
Log.d("TAG", username);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
usersRef.addListenerForSingleValueEvent(eventListener);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
friendIdRef.addListenerForSingleValueEvent(valueEventListener);
It will print all user names of those particular users. One more thing to note, is that you don't need to add in your database those friends that have the value of false, only those with the value of true.
I could not figure out how to point my value listener to every child's last node as shown in this picture.
I think I need to use childevent listener but I don't know how to redirect it correctly.
Query searchItemQuery = userDatabaseReference.child(user.getUid());
searchItemQuery.addChildEventListener(new ChildEventListener(){
#Override
public onChildAdded, onChildChanged, onChildRemoved, onChildMoved, onCancelled
});
I would suggest that down for each item0001, item0002, instead of using firebase push id, you can store the unix timestamp in millis. That way you can easily sort your entries and get last child node for each item.
So, with this change your database would look like
root
user
uid
item0001
15089344450000 // this is a timestamp
itemdepositdate
itemwithdrawdate
15989922000000 // another timestamp
itemdepositdate
itemwithdrawdate
item0002
AND SO ON...
Now, for each item, you can point to last child simply by using below code.
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference()
.child("root")
.child("user")
.child("user_id_of_user")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
snapshot.getRef().orderByKey().limitToLast(1).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
dataSnapshot.getValue(); // this is the last itemdepositdate and itemwithdrawaldate for this item
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Query searchItemQuery = userDatabaseReference
.child(user.getUid)
.orderByKey() //order nodes w.r.t. the keys
.limitToLast(1); //gets last item
I've been trying to retrieve an element from my Firebase database using its key. I have a class User and users are present in database.
I want to retrieve an object user using its key with this method :
public User getConnectedUserByUId(final String uid){
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = database.child("users");
final List<User> connectedUser= new ArrayList<User>();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot item: dataSnapshot.getChildren()) {
if (item.getKey()==uid)
{
User user= dataSnapshot.getValue(User.class);
connectedUser.add(user);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return connectedUser.get(0);
}
but it returns an empty list every time.
The issue is here:
if (item.getKey()==uid)
since you are comparing 2 String in java you have to use the method
string.equals(Object other) not the == operator.
Moreover, since you know the key of the data in Firebase you can use it to get the reference without cycling all children.
Something like:
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = database.child("users").child(uid);
Here you try to check a very specific ID only on changed data. Instead, try using a Firebase Query with filterByKey and not using your own function to achieve that. Here's sample code that I would use to try to replace your function:
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = database.child("users");
Query connectedUser = ref.equalTo(uid);
connectedUser.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
// TODO: handle the post here
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// ...
}
});
As specified in the Firebase documentation here: https://firebase.google.com/docs/database/android/lists-of-data#filtering_data
in the line : User user= dataSnapshot.getValue(User.class);
you have to put : User user= item.getValue(User.class);
and you have to check the id after you get the user:
if (user.getKey()==uid){
connectedUser.add(user);
}
There are 2 mistakes and a minor issue:
you are using == to compare two String objects. In java, this is true only if they are the same reference. Use equals instead.
addValueEventListener only adds a listener that gets invoked once after you add it and then every time something changes in the value you are listening to: this is an asynchronous behaviour. You are trying to get data synchronously instead. Please read something about this.
you are fetching useless data: you only need an object but you are fetching tons of them. Please consider to use the closest reference you can to the data you are fetching.
So, in conclusion, here's some code. I'd like to point out right now that forcing synchronous acquisition of naturaly asynchronous data is a bad practice. Nevertheless, here's a solution:
public User getConnectedUserByUId(final String uid){
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = database.child("users").child(uid);
Semaphore sem = new Semaphore(0);
User[] array = new User[1];
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot item: dataSnapshot.getChildren()) {
if (item.getKey()==uid)
{
User user= dataSnapshot.getValue(User.class);
array[0] = user;
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
try
{
sem.tryAcquire(10, TimeUnit.SECONDS);
}
catch (Exception ignored)
{
}
return array[0];
}
EDIT: I've just seen that this post is very old. I'm not sure how I ended up here.
I m currently developing an android app In which I m using firebse as DB.
I want to select a sepcific node and set It's password so how can I do that?
i used this code but it add another password attribute to the selected node.
this is the DB structure and i want to set password value of user toto.
public void resetPassword(){
//setting connexion parameter
final Firebase ref = new Firebase("https://test.firebaseio.com/users");
Query query = ref.orderByChild("username").equalTo("toto");
Firebase statusRef =query.getRef().child("password");
statusRef.setValue("COMPLETED");
System.out.println("Hellooooo FBM ");
}
Your query does not yet have the nodes that match that query. To get the matching nodes, you will have to attach a listener (as shown in the documentation on reading data).
A quick example:
public void resetPassword(){
//setting connexion parameter
final Firebase ref = new Firebase("https://test.firebaseio.com/users");
Query query = ref.orderByChild("username").equalTo("toto");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot user: snapshot.getChildren()) {
Firebase statusRef = user.child("password").getRef();
statusRef.setValue("COMPLETED");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getUser:onCancelled", databaseError.toException());
}
});
}