I am trying to retrieve Messages/child sorted on the base of time. I have access to Messages/child. I am unable to find any useful solution. Please help me figure this out.
My current code is:
FirebaseDatabase.getInstance()
.getReference()
.child("Messages")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable, String s) {
Log.d("children",dataSnapshot.getKey());
users_list.add(dataSnapshot.getKey());
}
you can do this way :-
mChatReference = FirebaseDatabase.getInstance().getReference("Messages")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid());
Query query = mChatReference.orderByChild("time");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Log.d("children",dataSnapshot.getKey());
users_list.add(dataSnapshot.getKey());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
As far as I can see you have a data structure:
Messages: {
uid1: {
uid2: {
messageId1: ...
messageId2: ...
messageId3: ...
}
}
}
You attach a ChildEventListener to /Messages/uid1, which means that your onChildAdded gets called for user second-level UID from your JSON. To get to the individual messages, you still need to loop over the child nodes of the DataSnapshot:
FirebaseDatabase.getInstance()
.getReference()
.child("Messages")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable, String s) {
for (DataSnapshot messageSnapshot: dataSnapshot.getChildren()) {
Log.d("message key: ", messageSnapshot.getKey());
Log.d("message time: ", messageSnapshot.child("time").getValue(String.class));
}
}
A few things to note:
As said, this code loops over the children of the DataSnapshot to get to the individual messages.
Consider storing the data as chat rooms where the key of each chat room is based on the UID of its participants as explained here: Best way to manage Chat channels in Firebase
You will need to add your messages to a list, and sort them client-side.
You're storing the time as a display string, which makes it harder to sort them. Consider storing them in a format that is easier to sort, such as "20190513T073306" or a timestamp such as 1557758003677.
Related
I created a social media app. Suppose I have one array list which contains all the uids of users I follow on my app, stored in child of (following), I also created a child of (posts) which has all posts, posted by all users. The problem is I don't want to use snapshot.getChildern() to retrieve posts which equals following because it downloads whole data under 'posts' child. Is there any way I can retrieve only those posts which matches with 'following' array list?(for Posts Database looks like this)-->
Clicks / UID {title : "sky" imageurl : "https...." publisher : "UID" timestamp : "1666456456.."}
and second one --> follow / UID / following / other user's uid : true
functions I use :
private void checkFollowing(){
followingList = new ArrayList<>();
DatabaseReference reference = Util.getDatabase().getReference("follow")
.child(Objects.requireNonNull(FirebaseAuth.getInstance().getCurrentUser()).getUid())
.child("following");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
followingList.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
followingList.add(dataSnapshot.getKey());
}
readClicksPosts();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void readClicksPosts() {
DatabaseReference reference = Util.getDatabase().getReference("Clicks");
reference.orderByChild("timestamp").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
clicks_models_List.clear();
for (DataSnapshot datasnapshot : snapshot.getChildren()) {
Clicks_Model clicks_model = datasnapshot.getValue(Clicks_Model.class);
for (String id : followingList) {
assert clicks_model != null;
if (clicks_model.getPublisher().equals(id)) {
clicks_models_List.add(clicks_model);
}
}
}
Collections.reverse(clicks_models_List);
clicksAdapter.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
DatabaseReference.goOffline();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
I just want to show posts from people I follow, what should I do if I don't to use .getChildren() method. Please keep in mind the posts are going to update frequently.
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);
...
I have to fetch all children data from firebase real time database? I want to fetch received messages of User2. How to do that? Database example is as given below -
To be able to fetch the children data, try the following:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("users").child("User1").child("MSG_TYPE_SENT");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
String msgContent=datas.child("msgContent").getValue().toString();
String msgType=datas.child("msgType").getValue().toString();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
This will give you the msgContent and the msgType, to retrieve any data from the database, you need to pass through every node example:-
getReference("users").child("User1").child("MSG_TYPE_SENT");
Then you can loop inside the ids and retrieve the data.
Here you can fetch the User2 Messages Received
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference("users");
mDatabase.child("User2").child("MSG_TYPE_RECEIVED").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot spanshot : dataSnapshot.getChildren()){
String content=snapshot.child("msgContent").getValue(String.class);
String type=snapshot.child("msgType").getValue(String.class);
//then you can log those values
Log.d("Values:",""+content+""+type);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
If the message received change at any time (lets say you want to implement the delete option in realtime of the message like whatsapp) .addValueEventListener will update your UI in realtime if you have coded to show that the message has been deleted
I am working on app where I want to show the data only of the users whose contact numbers are saved in the phone. So, I retrieved a list of contact numbers contactList. Now, I want to get all the contactList user's post from Firebase. Is there any way I can ask the Firebase for only those nodes in my contactList. One Way is to retrieve all users and then get relevant users from that (like I did below). Is there any better way to do so ?
Users: {
7828272892 : {
name: xyz,
gender: male,
phoneNo: 7828272892
Posts: {
SomeKey1: {
content: "This is post 1", Var2: "kkk"} }},
7924272894 : {name: abc, gender: male, phoneNo: 7924272894}
}
Code:
databaseReference.child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
List<Post> allItems = new ArrayList<Post>();
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
if (contactList.contains(postSnapshot.child("phoneNo").getValue())) {
// retrieve posts
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Is there any way I can ask the firebase for only those nodes in my contactList?
Yes, the way in which you already do this.
Is there any better way to do so?
The way in which you do this is a common practice used in Firebase. You query the database and check is the data already exists in the list, in your case in the contactList. If the list contains that phoneNo then you can retrieve the posts.
Try this code to read multiple nodes data..
mFirebaseInstance = FirebaseDatabase.getInstance();
mDatabase = mFirebaseInstance.getReference("usersDb/UserTable");
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mUserList.clear();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
User user = dataSnapshot1.getValue(User.class);
mUserList.add(user); // add all data into list.
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
So in the above data structure, I want to get value Aprilia Caponord 1200 (marked in fig.). I have Firebase reference to Aprilia (root node) and I can get all the key/value pair data.
Here's my code
#override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChild()) {
Map<?, ?> value = (Map<?, ?>) child.getValue();
String bike_price = value.get("price").toString();
String image_url = value.get("image_url").toString();
}
}
So clearly I can get all the values of child nodes having key/value relations. But I can't specifically get the name of the parent node. So how can I get the value of parent node in String format?
If I print child.getValue().toString(), I get JSON value, but I am not interested in parsing JSON. Is there any specific way to get parent node value?
{Aprilia Caponord 1200={image_url=____________, price=18.35}.. }
You're probably looking for the getKey() method on DataSnapshot:
mFirebaseRef = new Firebase("https://yours.firebaseio.com");
mFirebaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
Log.i("MainActivity", child.getKey());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("MainActivity", "onCancelled", firebaseError.toException());
}
});
A few things to note here:
I changed getChild() in your code to getChildren(), since there is not method getChild() that I'm aware of.
You should consider using addChildEventListener, which gives you DataSnapshots on the lower-level nodes
Things will get considerably easier if you create "wrapper classes" for your cars. The Firebase SDK for Android will then automagically unwrap the JSON into instances of that class. See our AndroidChat repo for a good example of this.
I met this case and solved the way as below:
final ChildEventListener countsListener = new ChildEventListener() { //for querying how many card created by each user in a specific period
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
/**
* $ROOT/Apirilia/Apirilia_id/CardId/IMG_URL
* $ROOT/Apirilia/Apirilia_id/CardId/PRICE
* ^[key] :[value]
*/
if (dataSnapshot == null) {
Logger.e("!!! dataSnapshot is null");
return;
}
String apirilia_id = dataSnapshot.getRef().getParent().getKey();
Logger.d("... Apirilia_id:" + apirilia_id);
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
I'm appreciated to be able to give one a hand.
for those who looking for key in firebaseUi then this code will work for u:-
firebaseadapterinstance.getRef(position).getKey();