How to get a list of data from firebase database? - java

I am trying to get some list data and put in a list. But I couldn't make it. I tried so many things but none of them is worked.
This is my database structure.
So there is a main root which is user then username in this case it is "mm". This node includes some data and some other nodes. Expenses is one of them. In expenses there are some unique keys. Every unique key indicates a different receipt. And each unique key stores products of this receipt. In this case there are three ( 0-1-2). There is no limitation to three. It can be 3 or 1 or 15. Each of this nodes store a value in "Expenses" class type.
I want to take this datas into a list. So this list should store data like that.
{
{
Receipt1: {
amount: 1,
marketName: "aa",
price: 2,
productName: "bb"
},
{
amount: 2,
marketName: "cc",
price: 3,
productName: "dd"
}
}, {
Receipt2: {
{
amount: 3,
marketName: "ee",
price: 5,
productName: "ff"
},
{
amount: 1,
marketName: "gg",
price: 7,
productName: "jj"
},
{
amount: 9,
marketName: "nn",
price: 5,
productName: "vv"
}
}
}
So I should able to access Receipts seperately. If I search for Receipt1 then I should get 3 nodes like example.
I try to get this datas like that. But It doesn't work.
private void receiptGetter(String userName,SimpleCallback<Boolean> finishedCallback) {
DatabaseReference rootRef = databaseManager.getReference();
DatabaseReference expensesRef = rootRef.child("user").child(userName).child("expenses");
Query queryReceiptFinder = expensesRef.orderByKey();
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
expenses = ds.getValue(Expenses.class);
expensesList.add(expenses);
}
finishedCallback.run(true);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("error", databaseError.getMessage());
finishedCallback.run(false);
}
};
queryReceiptFinder.addListenerForSingleValueEvent(valueEventListener);
}
Then I try to get this data like that.
searchButton.setOnClickListener(v -> {
receiptGetter("userName", (success) -> {
if (success) {
String receipt = expensesList.toString();
receiptText.setText(receipt);
} else
Log.d("error", getString(R.string.ErrorOccured));
});

I think Firestore is more suitable for your purpose than realtime database. If you can use it in the documentation you can see how to access every document.
This is a link for the official documentation:
https://firebase.google.com/docs/firestore/query-data/get-data
In general you can access a document with:
DocumentReference docRef = db.collection("cities").document("SF");
// asynchronously retrieve the document
ApiFuture<DocumentSnapshot> future = docRef.get();
// ...
// future.get() blocks on response
DocumentSnapshot document = future.get();
if (document.exists()) {
System.out.println("Document data: " + document.getData());
} else {
System.out.println("No such document!");
}
if you have nested document:
db.collection("cities").document("SF").collection("nameCollection").document("documentName");

Related

Reading data from firebase realtimedatabase

I am writing data to the database using another class with a constructor, but I still need to read data from the database. In the documentation, when using other classes, you need to create HashMap lists for each element, but I have 2 classes (since I need to write more than 255 entries to the database) and in each class, I will have to write a HashMap. How can I load the name of a DB variable that is identical to the name in the file itself? For example int b = 0; and in the database - b: 0 and how can you get the value of each variable from the database?
I send data like this:
if (user != null) {
if(database.child(getEmail)==null) {
User newUser = new User(getEmail, coins, ....);
User1 newUser1 = new User1(a256, a257, ....);
database.child(getEmail).push().setValue(newUser1);
database.child(getEmail).push().setValue(newUser);
}
I read data like this:
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot ds : snapshot.getChildren()){
User user = ds.getValue(User.class);
//saving information witch will read from db in SharedPreferences
PreferenceConfig.GetEmail(getApplicationContext(), getEmail);
PreferenceConfig.GetCoin(getApplicationContext(), getEmail);
PreferenceConfig.GetA256(getApplicationContext(), a256);
...
}
}
database.addValueEventListener(valueEventListener);
But i can`t understend how can i get data from db without hashmap
JSON file:
{
"User": {
"mail#gmail:com": {
"-NHTVinbEVUAqJwK8Umt": {
"getEmail": "mail#gmail.com",
"coins": 100,
.....
},
"-NHTVinpCPOJ4UPZvgpN": {
"a256":0,
"a257":0
...............
}
}
}
}
You won't be able to read the data under fields that are dynamically created:
{
"User": {
"mail#gmail:com": {
"-NHTVinbEVUAqJwK8Umt": {
"getEmail": "mail#gmail.com",
"coins": 100,
},
"-NHTVinpCPOJ4UPZvgpN": {
"a256":0, //πŸ‘ˆ
"a257":0 //πŸ‘ˆ
}
}
}
}
You'll be able to read all the data if your second child will have the same fields as the first one:
{
"User": {
"mail#gmail:com": {
"-NHTVinbEVUAqJwK8Umt": {
"getEmail": "mail#gmail.com",
"coins": 100,
},
"-NHTVinpCPOJ4UPZvgpN": {
"getEmail": "other#gmail.com", //πŸ‘ˆ
"coins": 200, //πŸ‘ˆ
}
}
}
}
Now, to read the data from such a structure, you have to create a reference that points to mail#gmail:com node and make a get() call as you can see in the following lines of code:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference emailRef = db.child("User").child("mail#gmail:com");
emailRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot ds : task.getResult().getChildren()) {
String email = ds.child("getEmail").getValue(String.class);
Log.d("TAG", email);
}
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
The result in the logcat will be:
mail#gmail.com
other#gmail.com
Or you can map each DataSnapshot object into an object of type User:
User user = ds.getValue(User.class);
This operation will work, only if your User class contains two fields called getEmail and coins. The first being a string and the second one a number.

How to do Arithmetic operations between two nodes of Firebase Realtime Database in Android Studio

I am having two tables Customers and Transaction nodes. Transaction node is related to data of Customer node by Vehicle Number a data in Customer node. I want to subtract the amount paid from the Customer node Due Amount
Customer Table:-
"Customers": {
"-NFFTcWFGLXi063jCTcT": {
"branch": "Rajeev Nagar",
"currentDownPayment": "80000",
"currentdueAmount": "20000.0",
"customerAadharNumber": "123456",
"customerAddress": "ANYWHERE",
"customerName": "VIKASH",
"customerPhoneNumber": "7481900892",
"customerTenure": "12",
"dateOfdelevry": "28/10/2022",
"downPayment": "100000",
"duePayment": "100000.0",
"emiPerMonth": "8333",
"emiStartDate": "26/10/2022",
"granterName": "RATHI",
"granterPhoneNumber": "7481900896",
"localitymodal": "NEAR ME",
"motorNumber": "QWERT",
"outStandingAmount": "120000.0",
"vehicleAmount": "200000",
"vehicleBodyType": "Steel",
"vehicleColour": "Gray",
"vehicleNumber": "1234567890QWERTYU"
},
Transection table:-
Transaction": {
"1234567890QWERTYU": {
"-NFFZLr7-9sTrZ1OlbjF": {
"dateOfPayment": "27/10/2022",
"discountGiven": "00",
"discountRemarks": "8000",
"lateFine": "no discount ",
"paymentReceived": "500"
}
The key of the Transaction Table is the same as the Customer Table Vehicle Number see the last data of the Customer Table
databasePaymentUpdate = FirebaseDatabase.getInstance().getReference("Customers");
databasePaymentUpdate.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
for (DataSnapshot ds : snapshot.getChildren()) {
String VehicleNumber = ds.child("vehicleNumber").getValue(String.class);
String vehNo = PaymentUpdateVehicleNumber.getText().toString().trim();
if (VehicleNumber.equals(vehNo)) {
Toast.makeText(PaymentUpdate.this, "Welcome to Jyoti Motors", Toast.LENGTH_SHORT).show();
}
To solve this problem, you have to use nested listener, as you can see in the following lines of code:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference customersRef = db.child("Customers");
customersRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> customersTask) {
if (customersTask.isSuccessful()) {
for (DataSnapshot customerSnapshot : customersTask.getResult().getChildren()) {
String vehicleNumber = customerSnapshot.child("vehicleNumber").getValue(String.class);
DatabaseReference vehicleNumberRef = db.child("Transaction").child(vehicleNumber);
vehicleNumberRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> vehicleNumberTask) {
if (vehicleNumberTask.isSuccessful()) {
long sum = 0;
for (DataSnapshot paymentSnapshot : vehicleNumberTask.getResult().getChildren()) {
String paymentReceived = paymentSnapshot.child("paymentReceived").getValue(String.class);
sum += Integer.valueOf(paymentReceived)
}
Log.d("TAG", "sum: " + sum);
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
}
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
And the result in the logcat will be:
sum: 500
Please also note, that is recommended to store the prices as numbers and not as strings, case in which the above addition should look like this:
long paymentReceived = paymentSnapshot.child("paymentReceived").getValue(Long.class);
sum += paymentReceived;

Retrieve count data from Firebase Java

I am trying to count the number of children in my DB table that meet a certain condition. If the isSeen column equals false then I want to count that, if it equals true I don't want to count it.
Currently, it's not working but if I change the query from Query query = usersRef.orderByChild("isSeen").equalTo(true); to Query query = usersRef.orderByChild("isSeen"); I get a number but it's not the correct way. Can someone please help me?
Rules:
{
"rules": {
".read": true,
".write": true,
"Messages": {
".indexOn": "isSeen"
}
}
}
"Messages": {
"b3vYlKZFrje0e3wHyBlWIK4ooK93": {
"DIt5bGqw2WS4eGHNqQJKxZSn3B72": {
"-N8NCgnwX6V7ghfGlcWS": {
"dateAdded": 1659337356887,
"date_time": "Aug-01-2022 3:02:36 AM",
"from": "DIt5bGqw2WS4eGHNqQJKxZSn3B72",
"isSeen": true,
"message": "Yoo",
"to": "b3vYlKZFrje0e3wHyBlWIK4ooK93",
"type": "text"
},
"-N99iQjlMfeyOM_VCAEB": {
"dateAdded": 1660184797462,
"date_time": "Aug-10-2022 10:26:37 PM",
"from": "DIt5bGqw2WS4eGHNqQJKxZSn3B72",
"isSeen": true,
"message": "Wassup",
"to": "b3vYlKZFrje0e3wHyBlWIK4ooK93",
"type": "text"
}
}
}
},
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("Messages");
Query query = usersRef.child(firebaseUser.getUid()).orderByChild("isSeen").equalTo(true);
query.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
long count = task.getResult().getChildrenCount();
Log.d("TAG1", "count: " + count);
} else {
Log.d("TAG2", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
Error message:
D/TAG2: Index not defined, add ".indexOn": "isSeen", for path "/Messages/b3vYlKZFrje0e3wHyBlWIK4ooK93", to the rules
Database schema
When you're using the following query:
Query query = usersRef.orderByChild("isSeen").equalTo(true);
Firebase will always return the exact data you are querying, meaning that you'll get all elements that have the isSeen field set to true. Please note that there is no way you can query by a negation. So something like this is not possible:
Query query = usersRef.orderByChild("isSeen").notEqualTo(true);
// πŸ‘†
According to your comment in which you say that you don't have any elements where the isSeen field is set to true, then your query will yield no results, and that's the expected behavior.
While #TimothyPham's answer will work, using getChildrenCount() might be the best solution. Why? Because if you have a lot of messages this operation requires you to read all of them in order to provide a number. The best solution I can think of would be to increment/decrement a counter as explained in my answer from the following post:
How to save users score in firebase and retrieve it in real-time in Android studio
Edit:
Query query = usersRef.orderByChild("isSeen").equalTo(true);
query.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
long count = task.getResult().getChildrenCount();
Log.d("TAG", "count: " + count);
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
But this code will only work if you have elements in the database that have he isSeen field is set to true.
I think you should try this, it working for me. It read your messages for the first time
usersRef.orderByChild("isSeen").equalTo(true).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Log.d("TAG", "Count:" + String.valueOf(dataSnapshot.getChildrenCount()));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Try this:
Log.e(dataSnapshot.getKey(),dataSnapshot.getChildrenCount() + "");

iterate all data in firestore

I am making an android app to average all rating data in Firestore. This is the structure of my Firestore. I want to retrieve all rating_num which are [1, 4, 5] using DocumentSnapshot
reviews
|-my_document1
|- rating_num:1
|-my_document2
|- rating_num:4
|-my_document3
|- rating_num:5
This is what I have done so far:
Query query = FirebaseFirestore.getInstance().collection("reviews").whereEqualTo(rating_num,??) //no clue
query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
Log.d("debug", "print all rating number using for loop");
for (QueryDocumentSnapshot document : task.getResult()) {
String cum_rating = document.getString("avg_quality");
Log.d("debug", cum_rating);
}
}
});
I have no clue how to match the only rating_num in all of my documents, and it does not show anything in my for loop, any help would appreciate.
Please also note that there is no need to call any .whereEqualTo(), as you don't need to match any property to a specific value.
To get the value of rating_num property from all documents and create an average, please use the following lines of code:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference reviewsRef = rootRef.collection("reviews");
reviewsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
long count = 0;
for (QueryDocumentSnapshot document : task.getResult()) {
count =+ document.getLong("rating_num");
}
long average = count / task.getResult().getDocuments().size();
Log.d("TAG", "avarage: " + average);
}
}
});
If you only have three documents with those three values, 1, 4, and 5, the result in the logcat will be:
3.33

Android Firebase realtime database get data is so slow

When I was using firebase for initialization of data and setText on UI, It was delayed for 10~15 seconds.
On the other hand, When I use Volley, It was delayed for only 1 seconds.
why is it so slow when i'm using firebase and How can I modifying this code?
here is my code (using ValueEventListener) and JSON tree
"couple_profile" : {
"TEST999AhCBcHK32AQzU3JglVbAxhTD6Mn1" : {
"birthday_1" : "1994-06-29",
"birthday_2" : "19940629",
"couple_nick" : "TEST999",
"exp" : 0,
"gold" : 0,
"level" : 1,
"member" : {
"AhCBcHK32AQzU3JglVbAxhTD6Mn1" : {
"FCM" : "d5Y-fl_0VCs:APA91bHX7HA531PXc1e4clUg61uB3XsKlwmQ_2U9OaESUTP0r-dnwbitSvxQ4EDMqPzK-t_5b9qPOhLm01FRffgB9-Ot6bZmx1JzwZvc07yoyhashGUS79E7Dztr2J7NfR1NGXw1LT2V",
"birthday" : "1994-06-29",
"name" : "κΉ€μ€€κ²Έ",
"phone_number" : "01050639201"
},
"FMsH7leNTOXBgbOFoWdaTMjt05T2" : {
"birthday" : "19940629",
"name" : "kimGod",
"phone_number" : "1541"
}
},
"mileage" : 0,
"name_1" : "κΉ€μ€€κ²Έ",
"name_2" : "kimGod",
"uid_1" : "AhCBcHK32AQzU3JglVbAxhTD6Mn1",
"uid_2" : "FMsH7leNTOXBgbOFoWdaTMjt05T2"
}
private void get_home_info() {
valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
coupleProfile = dataSnapshot.getValue(CoupleProfile.class);
if (coupleProfile == null) {
Log.e(TAG, "User " + FirebaseAuth.getInstance().getCurrentUser().getEmail() + " is unexpectedly null_1");
Toast.makeText(Home_Fragment.this.getContext(), "Error_1", Toast.LENGTH_SHORT).show();
} else {
StorageReference storageRef2 = storage.getReferenceFromUrl("FirebaseURL").child("Profile_image/" + FirebaseAuth.getInstance().getCurrentUser().getUid());
Glide.with(getContext()).using(new FirebaseImageLoader()).load(storageRef2).centerCrop()
.bitmapTransform(new CropCircleTransformation(new CustomBitmapPool()))
.into(me_view);
SharedPreferences.Editor sh = home_info.edit();
if (My_UID.equals(coupleProfile.uid_1)) {
my_number = 1;
sh.putString("my_name",coupleProfile.name_1);
sh.putString("op_name",coupleProfile.name_2);
sh.apply();
my_name_text.setText(coupleProfile.name_1);
op_name_text.setText(coupleProfile.name_2);
state_text.setText(coupleProfile.state_1);
op_state_text.setText(coupleProfile.state_2);
StorageReference storageRef = storage.getReferenceFromUrl("FirebaseURL").child("Profile_image/" + coupleProfile.uid_2);
Glide.with(getContext()).using(new FirebaseImageLoader()).load(storageRef).centerCrop()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.bitmapTransform(new CropCircleTransformation(new CustomBitmapPool()))
.into(friend_view);
} else if (My_UID.equals(coupleProfile.uid_2)) {
my_number = 2;
sh.putString("my_name",coupleProfile.name_2);
sh.putString("op_name",coupleProfile.name_1);
sh.apply();
my_name_text.setText(coupleProfile.name_2);
op_name_text.setText(coupleProfile.name_1);
state_text.setText(coupleProfile.state_2);
op_state_text.setText(coupleProfile.state_1);
StorageReference storageRef = storage.getReferenceFromUrl("FirebaseURL").child("Profile_image/" + coupleProfile.uid_1);
Glide.with(getContext()).using(new FirebaseImageLoader()).load(storageRef).centerCrop().diskCacheStrategy(DiskCacheStrategy.SOURCE)
.bitmapTransform(new CropCircleTransformation(new CustomBitmapPool()))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(friend_view);
} else {
Log.e(TAG, "User " + FirebaseAuth.getInstance().getCurrentUser().getEmail() + " is unexpectedly null_2");
Toast.makeText(Home_Fragment.this.getContext(), "Error", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "onCancelled: ", databaseError.toException());
}
};
ref = databaseReference.child("couple_profile").child(room_token);
ref.addValueEventListener(valueEventListener);
}
I think if you use this method from firebase you will have better loading of data:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Use the above code, explanation about it:
Firebase provides great support when comes to offline data. It automatically stores the data offline when there is no internet connection. When the device connects to internet, all the data will be pushed to realtime database. However enabling disk persistence stores the data offline even though app restarts.
Also try and retrieve the data in onStart()
Also, look for uses of .keepSynced(true). This likewise causes the entire node for which it is called to be fetched before it makes any updates. This can be very slow, depending on what node it is called for.

Categories