How to get out the stored data from Firebase? - java

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);
}
}

Related

In Firebase and Java, how to get value from datasnapshot correctly?

Recently I use Firebase in my Android application and try to get used of NoSQL data structure but I met some problems.
First, my data structure is very simple:
{
"user": {
"userid1" :{
"id: "userid1"
"name": "Samantha",
"age": 25
"email" : "abc#gmail.com"
}
}
}
So I wrote my Entity class like this
public class User implements Serializable {
private String id;
private String name;
private int age;
private String email;
}
When I want to get all user into list:
FirebaseDatabase.getInstance().getReference("user").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot dataSnapshot : snapshot.getChildren()){
User user = dataSnapshot.getValue(User.class);
listUser.add(user);
}
}
}
But if I want to change my data structure like this, I don't know how to do the same:
{
user: {
userid1 :{
id: "userid1"
name: "Samantha",
age: 25
email : "abc#gmail.com"
posts:{
postid1: {
postid : "postid1"
content : "content1"
}
postid2: {
postid : "postid2"
content : "content2"
}
}
}
}
}
I figure I have to create a Post entity class but how can I fetch list of user like before? Anyone can explain to me would be helpful.
Nesting data like you want to do is an anti-pattern in Firebase, and goes against the recommendations in the documentation on data structuring. See https://firebase.google.com/docs/database/android/structure-data#best_practices_for_data_structure
That said: if you have a structure like this, you can read it by adding posts map to the class to read its data:
public class User implements Serializable {
public String id;
public String name;
public int age;
public String email;
public Map<String, Object> posts;
}
If you want to get them type-safely, you might need to use a GenericTypeIndicator.

Get Children in JSON DataSnapshot

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.

Retrieve data from Firebase into an entity

I'm trying to retrieve data from Firebase database to add it to local database.
This code :
database = FirebaseDatabase.getInstance();
myRef = database.getReference();
Query LANGUAGES_REF = myRef.child("languages").orderByChild("id");
LANGUAGES_REF.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if (dataSnapshot.hasChildren()) {
Iterator<DataSnapshot> iterator = dataSnapshot.getChildren().iterator();
do {
Language language = iterator.next().getValue(Language.class);
languageR.insert(language);
} while (iterator.hasNext());
}
is not working , and I know it's because Language.class is an entity.
Is there a way other than creating a new class with getters and setters and full constructor ... and repeating everything??
The error I got was:
com.google.firebase.database.DatabaseException: Can't convert object
of type java.lang.Long to type
com.android.android.Database.Entities.Language
at this line :
Language language = iterator.next().getValue(Language.class);
Thanks
edit:
firebase database structure
"languages" : {
"LHZ7cAeOdPn-LwHNjIk" : {
"id" : 1,
"langName" : "Russian"
},
"LHZ7cAtXTGBlnWsdQOd" : {
"id" : 2,
"langName" : "French"
},
"LHZ7cAvrRs0rgI-PaJd" : {
"id" : 3,
"langName" : "Turkish"
}
}
language.class
import java.io.Serializable;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
#Entity
public class Language implements Serializable {
#PrimaryKey(autoGenerate = true)
private int id;
private String langName;
public int getId() {
return id;
}
public String getLangName() {
return langName;
}
public Language(String langName) {
this.langName = langName;
}
public void setId(int id) {
this.id = id;
}
}
To solve this, you need to remove the do-while loop because there is no need to iterate using getChildren() method, you can get the data directly from the dataSnapshot object like this:
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Language language = dataSnapshot.getValue(Language.class);
languageR.insert(language);
Log.d(TAG, language.getLangName());
}
The output in your logcat will be:
Russian
French
Turkish

Firebase Android getValue(class) doesn't work

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.

Firebase Database - Unable to retrieve nested data

I'm unable to retrieve the data which is nested inside "Leagues" and "Season".
In the database below, I cannot retrieve Season 2016/2017 points and results.
I am able to access the data that is not nested, such as Email and Username without problems
"Users" :
"User1" : {
"Email" : "dfs#sdf.com",
"Last_login" : "5:15pm",
"Username" : "Test",
"Leagues" : {
"FootballLeague" : true,
"CricketLeague" : true
},
"Season" : {
"2017" : {
"Points" : 5,
"Results" : 2
"newdata" : {
"randomdata1: data1",
"randomdata2: data2"
},
}
"2018" : {
"Points" : 7,
"Results" : 2
}
}
The following class is what I'm using to store data as objects:
public class Users {
private String Username;
private String Email;
private String Last_login;
private Map<String, Boolean> Leagues;
private Map<String, thisSeason> Season;
public Users() {
}
//All getters and setters for the strings.
public Map<String, Boolean> get_joined_Leagues() {
return Leagues;
}
public void set_joined_Leagues(Map<String, Boolean> leagues) {
Leagues = leagues;
}
public Map<String, thisSeason> getSeason() {
return Season;
}
public void set_thisSeason(Map<String, thisSeason> season) {
Season = season;
}
public static class thisSeason {
private int Points;
private int Results;
private Map <String, thisNewData> newdata;
public thisSeason() {
}
public int getthisSeason_results() {
return Results;
}
public void setthisSeason_results(int resultsin) {
Results = resultsin;
}
public int getthisSeason_points() {
return Points;
}
public void setSeason_points(int Pointsin) {
Points = Pointsin;
}
public Map<String, thisNewData> getNewData() {
return newdata;
}
public void set_thisNewData(Map<String, thisNewData> newdata_in) {
newdata= newdata_in;
}
public static class thisNewData {
private String randomdata1;
private String randomdata2;
//Getters and Setters
}
Here is part of my Java class where I access the Database:
List<Users> usersList= new ArrayList<Users>();
DatabaseReference fbDB = FirebaseDatabase.getInstance().getReference();
fbDB.child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Users C = ds.getValue(Users.class);
usersList.add(C);
System.out.println(C.getSeason().getthisSeason_points()); //ERROR occurs here - null object reference
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I get a null object reference error as shown in the code above.
Also, on a slight side note - I'm aware my implementation for getting Leagues is incorrect. How can I retrieve the keys instead?
The main problems that I found in your code:
First, your Leagues object:
Well, it should not be a custom object at all, if it stays in the current structure, but a Map. This is the map object - a collection which has a key, and a value, just like a child in the Realtime Database.
If a league name (=key) didn't have a true (=value) next to it - the names could have been stored in String variables, but this is not the case, because every child in the Realtime Database must have a value, and storing a "dummy" value next to a league name makes each league a part of a Map. This current "dummy" is a boolean, and that's why this will be the leagues' data type:Map<String, Boolean> leagues.
Second, your Season object:
You are confusing between one season and many seasons. Your child - "Season" actually stores a lot of seasons. Thats why this case will be similar to the one above - each season's time is the key and the season itself is the value.
Therefore, the User class's variables should be:
private String Username;
private String Email;
private String Last_login;
private Map<String,Boolean> Leagues;
private Map<String, Season> Seasons;

Categories