I'm having trouble getting from my Firebase database data to an android app and the Firebase listener and data snapshot documentations aren't really helping.
Say I have a database with the nodes structured as below:
Contacts-->
John : 1334255
May : 3345777
James : 5799862
Ford : 4574878
How can I directly retrieve the contacts from the nodes with the key and value both as strings , without having to cast them into some object(that's not the string object).
I want to be able to display the names(keys) as contact names and the numbers(their values) as Contact number.
Please try this code:
DatabaseReference contactsRef = FirebaseDatabase.getInstance().getReference().child("Contacts");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String name = ds.getKey();
String contactNumber = ds.getValue(String.class);
Log.d("TAG", name + ": " + contactNumber);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
contactsRef.addListenerForSingleValueEvent(eventListener);
Hope it helps.
tl;dr write them as something other than numbers
The values in your example are Long (integers). Assuming they're phone numbers, you'll probably want to store them as strings anyway. When you write a value to Firebase, it will infer the type and store it as one of the following:
String (will appear in quotes)
Long (whole number)
Double (decimal number)
Boolean (true or false without quotes)
Map<String, Object> (key with children)
List<Object> (key with children)
In your case, since you want to treat it as a String type when it's being read, just write it as a string:
If you're setting the values from client code, use the String type when you create the value.
If you're manually entering them from the dashboard, you can either wrap them in quotes or use non-numeric characters like the familiar format (123) 456-7890. Any value you type in that doesn't evaluate to a Long/Double/Boolean will be interpreted as a String.
Related
I am new to android studio and programming and am currently trying to make my first app. In firebase RTDB, I have multiple push ids under a single child that keep on increasing in number as the user presses certain buttons, and they all store only an integer. I want to retrieve the data from all those push ids(or keys, I don't really know what they are actually called) under the child and then sum the integers up and display the result in a textView and do it every time a new field is added. How can I do that? So far I only know how to normally send and receive data to childs sub-childs like this but i have never ever used push ids or keys before:
String recieve = datasnapshot.child("Child").child("subchild").getText().toString();
String send = "send";
databaseReferenc.child("Child").child("sunchile").setValue(send);
The data tree in firebase is as follows:
Assuming that Australia is a direct child of your Firebase Realtime Database root, to sum all those values, please use the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference australiaRef = rootRef.child("Australia");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int total = 0;
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String value = Integer.parseInt(ds.getValue(String.class));
total += value;
}
Log.d("TAG", "total: " + total);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore potential errors!
}
};
australiaRef.addListenerForSingleValueEvent(valueEventListener);
One more thing. Because you are storing numbers, it best to store them as long values and not as String values.
Here is my data structure. I only want to get the "regular" key from the first key which is the -LZHfDw9kqC-3rBf4VRh
Here is my code:
String rates = null;
DataSnapshot ratesSnapshot = dataSnapshot.child(key).child("promos");
Adapter_RoomsModel roomsModel = new Adapter_RoomsModel();
for (DataSnapshot ds : ratesSnapshot.getChildren()) {
rates = ds.getKey();
roomsModel.setRateName(rates);
}
My output :
-LZHfDw9kqC-3rBf4VRh
regular
-LZQu0HReRqMhbnWgFJg
regular
This is working as expected. If you want only a single child value, your query will have to give the entire path to that location. For example, you will need to call out promos/-LZHfDw9kqC-3rBf4VRh/regular. You can't use wildcards.
If you don't know the name of a node, perhaps because it's a random push ID, then you need to query those children for the one(s) you want.
I have implemented firebase realtime database in my android app, everything is fine. I am trying to add a a search function and I am able to search the database with only starting word match.
Below is my database snapshot:
I am querying for movieName. Right now I am able to search if the query string is Pets/Pe/pet. But when I search for Animals, I get zero results. So, basically what I am looking for is searching the database with query text anywhere in the string. ie., I should be able to search Animals/and/pets and should get the results which contain the search query.
Below is my code so far.
mDatabaseReference.child("recent").getRef().orderByChild("movieName").startAt(query)
.endAt(query + "\uf8ff")
To seach for a string within a String please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference animalsRef = rootRef.child("Animals");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Boolean found;
String search = "Animals";
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String movieName = ds.child("movieName").getValue(String.class);
found = movieName.contains(search);
Log.d("TAG", movieName + " / " + found);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
animalsRef.addListenerForSingleValueEvent(eventListener);
As you see, we query the database for all the movie names and then search for the desired word within the movieName.
First of all check the exact child and initialize the Firebase as like. Have a look at this answer,
https://stackoverflow.com/a/34537728/5746625
My Firebase Database is like this
When the coding below was run:
String loc=(snapshot.child("loc").getvalue()).tostring();
The output I get has different sequence with the database:
Why is that so?
Firebase data is stored as JSON and is inherently unordered.
If you want to access the data in a specific order, you should specify an orderBy clause for your query and access the data using the snapshot's getChildren() method.
Say you want to log the items by ascending key:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getRef();
Query locations = rootRef.orderByKey();
locations.addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot locSnapshot: snapshot.getChildren()) {
System.out.println(locSnapshot.getKey() + ": " + locSnapshot.getValue(String.class));
}
}
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// ...
}
});
This sample comes (modified) from the Firebase documentation on reading lists of data.
Frank beat me to my edit, check out his correct solution using orderBy....
You need to use forEach rather than the child method (or child.foreach)
Here is a snippet from the doc:
Because of the way JavaScript Objects work, the ordering of data in
the JavaScript Object returned by val() is not guaranteed to match the
ordering on the server nor the ordering of child_added events. That is
where forEach() comes in handy. It guarantees the children of a
DataSnapshot will be iterated in their query-order.
Source: https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#forEach
I have a database in Firebase for Android and I have an object with the attributes you see in the image. An object is stored in the database with the following code:
FirebaseUser user = mAuth.getCurrentUser();
String videoId = getIntent().getStringExtra("VIDEO_ID");
minuto = player.getCurrentTimeMillis();
Watching watching = new Watching(user.getUid(), videoId, String.valueOf(minuto));
DatabaseReference mRef = database.getReference().child("Watching").push();
mRef.setValue(watching);
The problem I have is as I am using push() to store the nodes I am having duplicate data as you can see in the image.
Is there any way to avoid storing duplicate data? Knowing that I don't have my own ID to store.
Any help ?
It depends on how you define a duplicate.
A common case where people have this question is when they're storing users. There the definition of a duplicate is simple: if two user objects have the same value for uid, they're the same user. So in that case you should store the users under their uid, instead of under a push ID.
The same applies for your situation. If a single user can only watch a single video, store the nodes under Watching by the uid of the user:
Watching
"NX7...A33"
"idVideo": "b13...o4s"
"minute": "0"
But if it's the combination of uid + idVideo that is unique, store the nodes under a combined key:
Watching
"NX7...A33_b13...o4s": "0"
Now you can easily prevent duplicates, by using setValue() instead of push():
String key = user.getUid() + "_" + videoId;
ref.child("Watching").child(key).setValue(String.valueOf(minuto));
I was facing same problem like you and this is how i figure it out. I m checking email address that user entered with the one saved in my db.if any match found then show toast that email already exists otherwise save with new key.
mFirebaseDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
//If email exists then toast shows else store the data on new key
if (!data.getValue(User.class).getEmail().equals(email)) {
mFirebaseDatabase.child(mFirebaseDatabase.push().getKey()).setValue(new User(name, email));
} else {
Toast.makeText(ChatListActivity.this, "E-mail already exists.", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onCancelled(final DatabaseError databaseError) {
}
});