Get uid in list by searching child values firebase android - java

{
"Mp6FLLdcSeXpfGPwP5i0ZBNZxd63" : {
"Age" : "20",
"Full name" : "Mike",
"Intent" : "Both",
"Reward" : "Nothing ",
"Variablex" : "one name",
"imageuri" : "images/Mp6FLLdcSeXpfGPwP5i0ZBNZxd63.jpeg"
},
"fWJcCPF16dUMKn1Sxz01VjF9Kgq2" : {
"Age" : "19",
"Full name" : "Other guy",
"Intent" : "Looking for help",
"Reward" : "nothing ",
"Variablex" : "one name",
"imageuri" : "images/fWJcCPF16dUMKn1Sxz01VjF9Kgq2"
}
}
This is my database. I want to get all the users with the same variablex. But i want only the id, the parent node. I want basically to build an array that contains all the ids of the users whose child value variablex is the same. And then use this array to call one user at a time get the id, perform other tasks with it etc.
public void othershit() {
Query qname3 = mDatabase.child("Variablex").orderByChild("Variablex").equalTo(userinput);
qname3.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
GenericTypeIndicator<List<String>> t = new GenericTypeIndicator<>();
List users = dataSnapshot.getValue(t);
textView8.setText(users.get(0).toString());
}
This is trigered with a button but everytime it crashes. Also i have three users with the same variablex. The structure is the same, this is a bit outdated version of my database but it is essentially the same.

Try using
dataSnapshot.getKey();
To retrieve the parent key of the found node which in your case is the FUID.
Edit -
Lets say your parent node for all the data is users
{
"users" :{
"Mp6FLLdcSeXpfGPwP5i0ZBNZxd63" : {
"Age" : "20",
"Full name" : "Mike",
"Intent" : "Both",
"Reward" : "Nothing ",
"Variablex" : "one name",
"imageuri" : "images/Mp6FLLdcSeXpfGPwP5i0ZBNZxd63.jpeg"
},
"fWJcCPF16dUMKn1Sxz01VjF9Kgq2" : {
"Age" : "19",
"Full name" : "Other guy",
"Intent" : "Looking for help",
"Reward" : "nothing ",
"Variablex" : "one name",
"imageuri" : "images/fWJcCPF16dUMKn1Sxz01VjF9Kgq2"
}
}
}
So here is what you need to do to get the list of all the ids which match the required
List<String> userIds = new Arraylist<>();
Query qname3 = mDatabase.child("users").child("Variablex").orderByChild("Variablex").equalTo(userinput)..addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userIds.add(dataSnapshot.getKey());
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});

Related

Read data from Firebase database when I have multiple unique ids

I'm having trouble writing in my database because I have multiple unique ids that I don't know how to access.
I know that for writing I need to use something like this:
DatabaseReference ref=database.getReference().child("Children")
ChildData data = new ChildData(fullName,age);
ref.push().setValue(data);
My database looks like this:
{
"Children" : {
"55hxObZjRLY9PSZxZxGgSTRKzpc2" : {
"-MzUih5e40OsWPF_Dj0q" : {
"age" : "22",
"fullName" : "Cristina "
},
"plays" : {
"-MznnNih5fItYf2usXB4" : {
"centiseconds" : "70",
"currentDate" : "01.04.2022",
"currentHour" : "04:23:30",
"numberOfFails" : "5",
"seconds" : "2"
}
}
}
},
"Data" : {
"id1" : {
"centiseconds" : "70",
"currentDate" : "01.04.2022",
"currentHour" : "04:23:30",
"numberOfFails" : "5",
"seconds" : "2"
}
}
}
I need the "plays" child to be under "fullName" in "-MzUih5e40OsWPF_Dj0q", not as a separated child. How can I access the path without hardcoding it like this ref.child("MzUih5e40OsWPF_Dj0q").child("plays").push().setValue(data)? I will have multiple children in "Children" with different ids, I won't be able to harcode them.
Is there any function that returns the path for the unique id?
Here is the entire function:
public void writeNewData
(String fullName,String age) {
DatabaseReference reference = database.getReference().child("Data");
DatabaseReference ref=myRef.push();
ChildData data = new ChildData(fullName,age);
ref.push().setValue(data);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds : snapshot.getChildren()) {
DatabaseReference playRef=ref.child("plays");
DatabaseData databaseData = ds.getValue(DatabaseData.class);
playRef.push().setValue(databaseData);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
Edit: This is my desired schema:
{
"Children" : {
"55hxObZjRLY9PSZxZxGgSTRKzpc2" : {
"-MzUih5e40OsWPF_Dj0q" : {
"age" : "22",
"fullName" : "Cristina ",
"plays" : {
"-MznnNih5fItYf2usXB4" : {
"centiseconds" : "70",
"currentDate" : "01.04.2022",
"currentHour" : "04:23:30",
"numberOfFails" : "5",
"seconds" : "2"
}
}
},
}
},
"Data" : {
"id1" : {
"centiseconds" : "70",
"currentDate" : "01.04.2022",
"currentHour" : "04:23:30",
"numberOfFails" : "5",
"seconds" : "2"
}
}
}
If you want the plays information to be a sibling of the age and fullName properties, then you will need to have a plays field/property in your ChildData class.
You'll need two classes, one to represent a "play" and one to represent a "child". At its minimum these will look like:
public class Play {
public String centiseconds, currentDate, currentHour, numberOfFails, seconds;
}
public class Child {
public String age, fullName;
public Map<String, Play> plays = new HashMap<>();
}
If you read/write this class, you will get plays nested under the child's data.

Trying to retrieve data from firebase where the category is equal to the string

I am trying to retrieve data from the Firebase Realtime Database and I only want where the category is equal to a String. For example, if my string is football then I should get all the data that has the category football in it. I run my app with the code I am about to show you but I get nothing but a blank page. I don't know what I am doing wrong.
databaseReference = FirebaseDatabase.getInstance().getReference();
if (Categories.InternetConnection.checkConnection(Categories.this)) {
databaseReference.child("Sports").orderByChild("category").equalTo("football")).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
myUploads.clear();
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
for (DataSnapshot postsnapshot : userSnapshot.getChildren()) {
Model_Information upload = postsnapshot.getValue(Model_Information.class);
Collections.shuffle(myUploads);
myUploads.add(upload);
recyclerView.invalidate();
}
}
linearLayoutWithoutItems.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
aAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(Categories.this, databaseError.getMessage(), Toast.LENGTH_LONG).show();
}
});
Firebase Json
{
"MyStudents" : {
"KihlyfLkJMQ5uZWBDgLWNuBHKAE2" : {
"-MSr8HG6QCR2sO8MZHoM" : {
"category" : "Football",
"created" : "2-19-2021",
"name" : "Benny",
"time" : "2:47 AM",
"timestamp" : 1613684875762
},
"-MSr8awtvzrmm3P6A2LB" : {
"category" : "Basketball",
"created" : "2-19-2021",
"name" : "patrick",
"time" : "2:49 AM",
"timestamp" : 1613684960454,
},
"-MSr8mSn5OSTu5vdT4Wt" : {
"category" : "Football",
"created" : "2-19-2021",
"name" : "Shawn",
"time" : "2:50 AM",
"timestamp" : 1613685007616,
}
{
"MyStudents" : {
"WahlyfLkJMQ5uZWBDgLWNuBHKAE2" : {
"-MSr8HG6QCR2sO8MZHoM" : {
"category" : "Football",
"created" : "2-19-2021",
"name" : "Len",
"time" : "2:47 AM",
"timestamp" : 1613684875762
},
"JJr8awtvzrmm3P6A2LB" : {
"category" : "Basketball",
"created" : "2-19-2021",
"name" : "Armstrong",
"time" : "2:49 AM",
"timestamp" : 1613684960454,
},
"-JJr8mSn5OSTu5vdT4Wt" : {
"category" : "Football",
"created" : "2-19-2021",
"name" : "Bill",
"time" : "2:50 AM",
"timestamp" : 1613685007616,
}
The problem in your code lies in the fact that you are using an incorrect query:
databaseReference.child("Sports").orderByChild("category").equalTo("football"))
Assuming that MyStudents is a child right under your root node and the following statement:
if (Categories.InternetConnection.checkConnection(Categories.this)) { /* ... */ }
Returns true, please use the following query:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child(uid);
Query queryByCategory = uidRef.orderByChild("category").equalTo("Football");
queryByCategory.addValueEventListener(/* ... */);
Things to notice:
KihlyfLkJMQ5uZWBDgLWNuBHKAE2 is the UID of the logged-in user and should be added as a child in the reference.
The value of the category property is called "Football" and not "football", with lower-case "f".
Edit:
According to your last comment:
I'm not trying to just get their information I'm trying to get everyone that has students whose category is Football
There is no way you can achieve that using your actual database structure. The most simple solution I can think of is to create a new node that contains all Model_Information objects, no matter the user is. 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.
Also, when you are duplicating data, there is one thing that needs to keep in mind. In the same way, you are adding data, you need to maintain it. In other words, if you want to update/delete an item, you need to do it in every place that it exists.
Here is the answer. Hopefully its helpful for someone :)
databaseReference = FirebaseDatabase.getInstance().getReference().child("MyStudents");
if (Categories.InternetConnection.checkConnection(Categories.this)) {
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
myUploads.clear();
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
for (DataSnapshot postsnapshot : userSnapshot.getChildren()) {
Model_Information upload = postsnapshot.getValue(Model_Information.class);
Collections.shuffle(myUploads);
if (upload.getCategory().equals("Football")) {
myUploads.add(upload);
}else{
Toast.makeText(Categories.this, "No results", Toast.LENGTH_LONG).show();
}
recyclerView.invalidate();
}
myUploads.add(upload);
recyclerView.invalidate();
}
}
aAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(Categories.this, databaseError.getMessage(), Toast.LENGTH_LONG).show();
}
});

FirebaseDatabase reference objects with UserAuthentication

I am working on a android application assignment for school and I am having a hard time understanding Firebase Database reference objects for signed in users. It is a chatroom app and users can sign up or login to enter the app. Once in, they can send messages in the chatroom that will be visible to other authorized users that sign in.
App structure:
Everything in the app is in a fragment. The main activity calls the Login fragment first. If new user, they can click on sign up and the main activity will replace the login fragment with sign up fragment. Once logged in, the main activity replaces the current fragment with the ChatRoom fragment. This isn't a requirement, but my User authentication steps happen in my MainActivity. That is the only Firebase related task that happens there.
My progress:
I have the sign up and login sections completed properly.
I am able to send a message and that message shows up in the DB under the current user node properly.
My code:
All the code I am having issues with is in the ChatRoom fragment.
This is the addEventListener code I have:
ArrayList<ChatMessage> chatData; //ChatMessage is my class that takes the message text, sent user, and time.
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance(); //Root node
DatabaseReference rootReference = firebaseDatabase.getReference("Users"); //Users node
DatabaseReference currentUserReference; //CurrentUser node
FirebaseUser currentUser; //CurrentUser value is obtained from MainActivity after the user signs in
public void onAttach(Context context) {
//Other event listeners for buttons......
chatData = new ArrayList<>();
rootReference.addValueEventListener(new ValueEventListener() {
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
chatData.clear();
currentUserReference = rootReference.child(currentUser.getUid());
for (DataSnapshot snap : dataSnapshot.getChildren()) {
for (DataSnapshot snapChild : snap.getChildren()) {
ChatMessage chatMessage = snapChild.getValue(ChatMessage.class);
chatData.add(chatMessage);
}
}
PopulateListView();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
The problem I am facing is, when I send a message from say xxx#xxx.com, if there are messages in the DB from say yyy#yyy.com, they get added to xxx's node on top of the message that xxx sends.
Here is my DB JSON:
First message from user xxx:
{
"Users" : {
"xxx" : [ {
"messageText" : "Hello",
"messageTime" : "2019/04/06 16:32:33",
"messageUser" : "xxx"
} ]
}
}
Second message from user xxx:
{
"Users" : {
"xxx" : [ {
"messageText" : "Hello",
"messageTime" : "2019/04/06 16:32:33",
"messageUser" : "xxx"
}, {
"messageText" : "Hello number 2 from xxx",
"messageTime" : "2019/04/06 16:33:16",
"messageUser" : "xxx"
} ]
}
}
First message from user yyy:
{
"Users" : {
"xxx" : [ {
"messageText" : "Hello",
"messageTime" : "2019/04/06 16:32:33",
"messageUser" : "xxx"
}, {
"messageText" : "Hello number 2 from xxx",
"messageTime" : "2019/04/06 16:33:16",
"messageUser" : "xxx"
} ],
"yyy" : [ {
"messageText" : "Hello",
"messageTime" : "2019/04/06 16:32:33",
"messageUser" : "xxx"
}, {
"messageText" : "Hello number 2 from xxx",
"messageTime" : "2019/04/06 16:33:16",
"messageUser" : "xxx"
}, {
"messageText" : "Hello from yyy",
"messageTime" : "2019/04/06 16:34:13",
"messageUser" : "yyy"
} ]
}
}
How do I fix this issue? I can see exactly why this is happening, it is because of my nested foreach loops for all users and all messages within and adding it all to the current user's node. But if I set my listener directly to the child node, my chatData ArrayList does not get populated with the messages from other users. How do I work around this?

Check if user exists in Firebase database across multiple children nodes

I've a database like this
"Node" : {
"Location_1" : {
"ID1" : {
"address" : "address1",
"balance" : "20",
"batch" : "xyz",
.
.
.
"studentID" : "ID1",
"studentName" : "Username",
"total" : "amount"
}
},
"Location_2" : {
"ID2" : {
"address" : "address2",
"balance" : "0",
"batch" : "xyz",
.
.
"studentID" : "ID2",
"studentName" : "username",
"total" : "amount"
}
}
"Location_3" : {
"ID3" : {
"address" : "address3",
"balance" : "0",
"batch" : "xyz",
.
.
"studentID" : "ID3",
"studentName" : "username",
"total" : "amount"
}
}
I'm able to check if the ID1 exists in a particular Location_1 using the code given below, but I'm unable to find if the ID1 exists across different Location_X id's.
String url = "https://firebaseURL/Node/";
url = url + Location_1;
databaseReference = FirebaseDatabase.getInstance().getReferenceFromUrl(url);
databaseReference.child(ID1).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
Toast.makeText(getApplicationContext(), "ID already present. Enter unique ID!", Toast.LENGTH_SHORT).show();
}
else { // not present, so go ahead and add
}
I tried using a function like this to check if the user is present in all the subNodes.
private boolean checkIfUserExists(String ID) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("Location_1");
.
.
String url = "https://firebaseURL/Node/";
databaseReference = FirebaseDatabase.getInstance().getReferenceFromUrl(url);
for(String s: arrayList){
if(getUserExists())
break;
databaseReference.child(s).child(ID).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
setUserExists(true);
}
}
But always the function getUserExists return false. So I end up adding a new user in different location or updating the user's info in the same location.
Please let me know how to proceed on checking the existence of the userID in all the locationIDs

how to fetch multiple data simultaneously from firebase database

Fetch messages method
private void fetchMessages() {
rootRef.child("Messages").child(MessageSenderId).child(MessageRecieverId)
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Messages messages = dataSnapshot.getValue(Messages.class);
messagesList.add(messages);
messageAdapter.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) {
throw databaseError.toException();
}
});
}
Defining Ids
MessageSenderId = mAuth.getCurrentUser().getPhoneNumber();
MessageRecieverId = getIntent().getStringExtra("visit_user_id");
trying to make a basic chat app
Since only the senders id is called in rootref only the messages i send r being displayed in d recyclerview... im unable to receive messages because of this... how can i make it to retrieve recievers id and senders id also at the same time
Database strucutre
{
"Messages" : {
"+918105571584" : {
"+919945342730" : {
"-L58IPCLEeE21vH_-1Ry" : {
"message" : "Hi",
"seen" : false,
"time" : 1518427022478,
"type" : "text"
},
"-L58IU1VIHN0rHaUox3a" : {
"message" : "Hello",
"seen" : false,
"time" : 1518427042257,
"type" : "text"
},
"-L58IYN1GpHPdkWCY7Hn" : {
"message" : "Hi",
"seen" : false,
"time" : 1518427060021,
"type" : "text"
}
}
},
"+919945342730" : {
"+918105571584" : {
"-L58IPCLEeE21vH_-1Ry" : {
"message" : "Hi",
"seen" : false,
"time" : 1518427022478,
"type" : "text"
},
"-L58IU1VIHN0rHaUox3a" : {
"message" : "Hello",
"seen" : false,
"time" : 1518427042257,
"type" : "text"
},
"-L58IYN1GpHPdkWCY7Hn" : {
"message" : "Hi",
"seen" : false,
"time" : 1518427060021,
"type" : "text"
}
}
}
},
"Users" : {
"+918105571584" : {
"Email" : "",
"Name" : "Akash",
"Quote" : "",
"Status" : ""
},
"+919945342730" : {
"Email" : "",
"Name" : "Sav",
"Quote" : "",
"Status" : ""
}
}
}
According to your last comment, I understand that you can display only the messages that correpond to a single user. A user can see only his messages butd not other user messages. To solve this, you need to create chat rooms, in which every user can add messages that can be seen by all chat room members.
So for that, you need to change your database structure. You cannot achieve this, using the actual database.

Categories