I have a class as seen Below:
public class GlobalHighScore {
String name;
int score;
public GlobalHighScore(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
And here I try to make a data receiving.
DatabaseReference scoresRef = firebaseDatabase.getReference("Highscores");
scoresRef.child("GlobalHighScore").orderByChild("score").limitToFirst(10);
scoresRef.addValueEventListener(new ValueEventListener() {
#Override public void onDataChange(DataSnapshot dataSnapshot) {
Iterable<DataSnapshot> keys = dataSnapshot.getChildren();
int i = 0;
for (DataSnapshot key : keys) {
if(i == 10)
break;
orderName[i].setText(key.getValue().toString());
i++;
}
}
When I am doing this, key.getValue().toString() returns json formatted String but I want "name" and "score" seperately. Also, my data is not sorted eventhough I make it sorted.
scoresRef.child("GlobalHighScore").orderByChild("score").limitToFirst(10);
I think I having problem here.
Edit: When I order by "score", it gives data according to date.
Last form is
final TextView[] orderScore = {firstscore, secondscore, thirdscore, fourthscore, fifthscore, sixthscore, seventhscore, eightscore, ninthscore, tenthscore};
final TextView[] orderName = {firstname, secondname, thirdname, fourthname, fifthname, sixthname, seventhname, eightname, ninthname, tenthname};
DatabaseReference scoresRef = firebaseDatabase.getReference("Highscores").child("GlobalHighScore");
scoresRef.orderByChild("score").limitToFirst(10);
scoresRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int i = 0;
for (DataSnapshot data : dataSnapshot.getChildren()) {
if(i == 10)
break;
String name = data.child("name").getValue().toString();
String score = data.child("score").getValue().toString();
orderName[i].setText(name);
orderScore[i].setText(score);
i++;
}
}
It gives no data record at all.
Try this:
DatabaseReference scoresRef = firebaseDatabase.getReference("Highscores").child("GlobalHighScore");
Query q=scoresRef.orderByChild("score").limitToFirst(10);
q.addValueEventListener(new ValueEventListener() {
#Override public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot data : dataSnapshot.getChildren()){
String name=datas.child("name").getValue().toString();
String score=datas.child("score").getValue().toString();
}
}
Since you want the name and the score alone you can do the above, to be able to retrieve them alone.
.orderByChild("score").limitToFirst(10);, using this you will get the first 10, nodes that have the child score.
limitToFirst(10) //to get the first 10 of a specific child
limitToLast(10) //to get the Last 10 of a specific child
When you are using the following line of code:
Iterable<DataSnapshot> keys = dataSnapshot.getChildren();
The childrens that you are getting when iterating are actual objects, not Strings. Using toString() method doesn't make any sense because you cannot cast an Object to a String and expect to get the values within it. That's why you are getting that "json formatted Strings". So what are you getting when iterating are actual maps. So to get the name and score you need to iterate through the map and use: map.get("name"); and map.get("score");.
You don't need to change the entire code, your code is fine. Just solve this minor issue.
Related
This is my database structure on firebase Realtime database:
I am trying to access the data under the last uploaded session, which in this case is Session9 and access the sensor readings taken at a specific time.
I have queried the database to give me the last node under data and added a ListenerForSingleValueEvent, at this location i am getting a key in keys List as session9 (only one item) through the following:
Query lastSession = dbref.child("data").limitToLast(1);
lastSession.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot keyNode : dataSnapshot.getChildren()){
keys.add(keyNode.getKey());
Reading reading = node.getValue(Reading.class);
readings.add(reading);
textView.append(reading.getTemperature());
}
}
}
appending the temperature throws this error:
Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
readings is an arraylist of Reading class
keys is a list of Strings for storing the keys for example "00:00:06"
I am making some mistake and cannot access the data that i want to add to readings list.
public class Reading {
private String Date;
private String Time;
private String Humidity;
private String Temperature;
private int Sound;
public Reading(){
}
Use this code:
dbref = FirebaseDatabase.getInstance().getReference();
Query lastSession = dbref.child("data").orderByKey().limitToLast(1);
lastSession.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot keyNode : dataSnapshot.getChildren()){
for (DataSnapshot ds : keyNode.getChildren()){
keys.add(ds.getKey());
Reading reading = ds.getValue(Reading.class);
readings.add(reading);
}
}
Here your reference is at node date therefore, you need to add two for loops to be able to access the attributes inside the time.
Upon checking your codes your only getting the key or the seesion but not the chidlrens
Well maybe this can help you creating second query to access the last node children
Query lastSession = dbref.child("data").limitToLast(1);
lastSession.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot keyNode : dataSnapshot.getChildren()){
String lastItem = keyNode.getKey();
//second query
Query secondQuery= dbref.child("data").child(lastItem);
secondQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snap: dataSnapshot.getChildren()){
String temp = snap.child("Temperature").getValue(String.class);
//or you can do this
Reading reads = snap.getValue(Reading.class);
String temp2 = reads.getTemperature();
textView.setText(temp);
}
}
});
}
}
}
The issue stems from that the properties of your Reading class are not publicly accessible to get/set their values.
When you call DataSnapshot.getValue(YourClass.class) or DatabaseReference.setValue(instanceOfYourClass), the class YourClass must have the following:
A public constructor that takes no arguments.
(For getting values) Publicly accessible setters for each property
(For writing values) Publicly accessible getters for each property
The getValue(YourClass.class) function will silently ignore when it fails to set an appropriate property on the target instance of that class.
So to make your Reading class compliant, you would define it using:
public class Reading {
public String Date;
public String Time;
public String Humidity;
public String Temperature;
public int Sound;
public Reading(){
}
}
To fix a potential typo:
Query lastSession = dbref.child("data").limitToLast(1);
lastSession.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot keyNode : dataSnapshot.getChildren()){
keys.add(keyNode.getKey());
Reading reading = keyNode.getValue(Reading.class); // changed node to keyNode
readings.add(reading);
textView.append(reading.getTemperature());
}
}
}
Further reading: Read/Write Data Documentation
I'm not getting the output from Firebase database. It's not returning anything. Here is my data structure.
I also tried getting value through query but it returned database error:
Cannot convert java.util.hashmap to String
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference().child("Member").push();
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String value = ds.getValue(String.class);
Log.d("Tag", "Value is" + value);
}
}
JSON:
{
"Member" : {
"-LhKJVG1Tj2628sHPg4D" : {
"age" : "21",
"name" : "Gagan",
"nickname" : "Gaggi"`enter code here`
},
"-LhKKaNFnPrrh1bQNPfH" : {
"age" : "18",
"name" : "Jashan",
"nickname" : "Jassi"
}
}
}
You cannot call getValue with String.class because it does not meet the criteria of the method call.
From the documentation
public T getValue(Class valueType)
This method is used to marshall the data contained in this snapshot into a class of your choosing. The class must fit 2 simple constraints:
The class must have a default constructor that takes no arguments
The class must define public getters for the properties to be assigned. Properties without a public getter will be set to their default value when an instance is deserialized
An example class might look like:
class Message {
private String author;
private String text;
private Message() {}
public Message(String author, String text) {
this.author = author;
this.text = text;
}
public String getAuthor() {
return author;
}
public String getText() {
return text;
}
}
// Later
Message m = snapshot.getValue(Message.class);
You can use String class
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String name= ds.child("name").getValue(String.class);
String age= ds.child("age").getValue(String.class);
//and similar for others
Log.d("TAG", email + " / " + name);
}
}
I'm trying to get the children from my JSON separately and pass them through an intent. Here is how my JSON is formatted:
"allDeeJays" : {
"-LeP1DB6Onzh4-UiN_0E" : {
"acct" : "Aaron A",
"djName" : "uhgvvvbbb"
}
},
Using the DataSnapshot, I have been able to get the djName values, but I am not getting the acct values, with the following code:
#Override
protected void onBindViewHolder(#NonNull ResultsViewHolder holder, final int position, #NonNull final DataSnapshot snapshot) {
// Here you convert the DataSnapshot to whatever data your ViewHolder needs
String s = "";
for(DataSnapshot ds : snapshot.getChildren())
{
s = ds.getValue(String.class);
DjProfile model = new DjProfile(s);
model.setDjName(s);
holder.setDjProfile(model);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("allDeeJays");
String acct = "";
String name = "";
for(DataSnapshot ds : snapshot.getChildren())
{
name = ds.getValue(String.class);
acct = ds.getValue(String.class);
DjProfile model = new DjProfile(name);
model.setDjName(name);
}
Intent i = new Intent(getApplication(), AddSongRequest.class);
i.putExtra("DjName", name);
i.putExtra("UserAcct", acct);
startActivity(i);
}
});
}
};
Finally, my DjProfile class is defined as follows:
package com.example.android.heydj;
import com.google.firebase.database.Exclude;
import com.google.firebase.database.PropertyName;
public class DjProfile
{
String djName;
String key;
public DjProfile(String djName)
{
this.djName = djName;
}
public DjProfile(){}
public void setDjName(String djName)
{
this.djName = djName;
}
public String getdjName()
{
return djName;
}
}
Both variables are returning the same value, and when I run snapshot.getChildrenCount() it says that there are two children (which I assume are acct, and djName). Do I need to add additional getters and setters for the account name? Any help is greatly appreciated :)
Try like this and it's will return exact value for your keys
if(snapShot.getKey().equalsIgnoreCase("djName"))
name = ds.getValue(String.class);
if(snapShot.getKey().equalsIgnoreCase("acct"))
acct = ds.getValue(String.class);
or use
DjProfile model = snapShot.getValue(DjProfile.class);
instead of
for(DataSnapshot ds : snapshot.getChildren())
{
name = ds.getValue(String.class);
acct = ds.getValue(String.class);
DjProfile model = new DjProfile(name);
model.setDjName(name);
}
You can resolve this by adding below line -
DjProfile profile = ds.getValue(DjProfile.class);
You can now pass this profile into an Intent.
So this is my bind model class:
public class UserBanknoteAmountBindModel {
public String id;
public String userId;
public String banknoteType;
public String banknoteAmount;
public UserBanknoteAmountBindModel(){
}
public String getBanknoteAmount() {
return banknoteAmount;
}
public String getBanknoteType() {
return banknoteType;
}
public String getUserId() {
return userId;
}
public void setBanknoteAmount(String banknoteAmount) {
this.banknoteAmount = banknoteAmount;
}
public void setBanknoteType(String banknoteType) {
this.banknoteType = banknoteType;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
(idk if acess modifiers matter in this case).
I am trying to parse my data:
for (DataSnapshot banknoteAmount:dataSnapshot.getChildren()){
UserBanknoteAmountBindModel userBanknoteAmountBindModel=dataSnapshot.getValue(UserBanknoteAmountBindModel.class);
Log.wtf("hgfh", banknoteAmount.getValue().toString());
}
I see that I am receiving my data because I can log it.
{banknoteAmount=3, banknoteType=20_dollar,
userId=112371098270685247195}
Anyway my data doesn't get inside my bind model. I read somewhere that I need not only to provide getters but also setters (that's why I put those setters PS: Is the thing for the setters true?).
Any ideas?
EDIT: Database Structure https://i.stack.imgur.com/o5Hgp.png
PS: The problem was that I was using the parameter from another function for the getValue (not the foorloop variable)
To get the values of banknoteAmount, banknoteType and userId, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userBanknoteAmountRef = rootRef.child("userBanknoteAmount");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
UserBanknoteAmountBindModel userBanknoteAmountBindModel = ds.getValue(UserBanknoteAmountBindModel.class);
String banknoteAmount = userBanknoteAmountBindModel.getBanknoteAmount();
String banknoteType = userBanknoteAmountBindModel.getBanknoteType();
String userId = userBanknoteAmountBindModel.getUserId();
Log.d("TAG", banknoteAmount + " / " + banknoteType + " / " + userId);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
userBanknoteAmountRef.addListenerForSingleValueEvent(valueEventListener);
The output will be:
3 / 20_dollar / 112371098270685247195
When you are using the following line of code:
banknoteAmount.getValue().toString()
You are actually printing the String representation of banknoteAmount.getValue() which has as a return value a Map object which contains those three values.
I am using Firebase database for my project. For the last few days I tried to retrieve data from database but without luck. I tried many tutorials and questions from Stack.. Database looks like this:
Database structure
My user class
I would like to retrieve information and store it in one of the strings..
My code is:
Every time I receive value Null or an Error. I am not sure If I am using correct reference("Users").
Is there is easy way to retrieve users name and store it into the string? Thanks
First you need to have same names for the fields in your database as in your model class. Looking at you model class, there are some things that you need to do. So, I'll provide a correct way to model your class.
public class UserModelClass {
private String name, sureName, date, phoneNumber;
public UserModelClass() {}
public UserModelClass(String name, String sureName, String date, String phoneNumber) {
this.name = name;
this.sureName = sureName;
this.date = date;
this.phoneNumber = phoneNumber;
}
public String getName() {return name;}
public String getSureName() {return sureName;}
public String getDate() {return date;}
public String getPhoneNumber() {return phoneNumber;}
}
In order to make it work, you need to remove all data from the database and add fresh one. There is a workaround when storing users in a Firebase database. Instead of using that that random key provided by the push() method, to use the uid. For that, I recommend you add the data as in the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
UserModelClass umc = new UserModelClass("Jonas", "Simonaitis", "today", "123456789");
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("users").child(uid);
uidRef.setValue(umc);
To read data, please use the following code:
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserModelClass userModelClass = dataSnapshot.getValue(dataSnapshot.class);
String name = userModelClass.getName();
String sureName = userModelClass.getSureName();
String date = userModelClass.getDate();
String phoneNumber = userModelClass.getPhoneNumber();
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
uidRef.addListenerForSingleValueEvent(eventListener);
In one of my tutorials I have explained step by step how to use the model classes when using Firebase.
First you have to do make these declarations:
private DatabaseReference mUserDatabase;
private FirebaseUser mCurrentUser;
in onCreate you need to make smth like this:
mCurrentUser = FirebaseAuth.getInstance().getCurrentUser();
String current_uid = mCurrentUser.getUid();
mUserDatabase =FirebaseDatabase.getInstance().getReference().child("Users")
.child(current_uid);
mUserDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("uName").getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Now you have the user name in "name"
First change userInformationActivity class variable names to match names in the database
example : name -> uName
surname -> uSurname
then
private void showData(DataSnapshot dataSnapshot){
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
userInformationActivity user = dataSnapshot.getValue(userInformationActivity.class);
Log.d("user Name is : " + user.uName);
}
}