Getting error:
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.example.ken.careerapp.Models.Jobs
Using a fragment below:
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.job_listings_fragment, container, false);
recyclerView = view.findViewById(R.id.recyclerviewjob);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerAdapterJob = new RecyclerAdapterJob(jobs,JobFragment.this::onJobClick);
recyclerView.setAdapter(recyclerAdapterJob);
jobs = new ArrayList<Jobs>();
//initData();
databaseReference = FirebaseDatabase.getInstance().getReference().child("Jobs");
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot ds: dataSnapshot.getChildren()){
Jobs data = ds.getValue(Jobs.class);
jobs.add(data);
}
recyclerAdapterJob.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
//recyclerView.setAdapter(new RecyclerViewAdapter2(initData()));
return view;
}
The job model class which is passed to getValue in datasnapshot above:
public class Jobs {
private String description;
private String location;
private String deadline;
public Jobs() {
}
public Jobs(String description, String location, String deadline) {
this.description = description;
this.location = location;
this.deadline = deadline;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDeadline() {
return deadline;
}
public void setDeadline(String deadline) {
this.deadline = deadline;
}
}
FirebaseRealtime database
You are getting the following error:
Getting error: com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.example.ken.careerapp.Models.Jobs
Because you are trying to convert a String, into an object of type Jobs, and this actually not possible in Java. As I see in your screenshot, under the Jobs node, there is only a single Jobs object that contains exactly three String properties. So when you iterate that node, you get String objects back and not Jobs objects, hence that error.
To solve this, you should create multiple objects under that node, as I understand, you want to display them in a RecyclerView. To solve this, you should use the push() method, when you add those jobs to the database. You didn't share that part of code, but I imagine that looks similar to this:
databaseReference = FirebaseDatabase.getInstance().getReference().child("Jobs");
databaseReference.setValue(jobs);
In which jobs is an object of type Jobs. This is not correct, as it produces that error when reading data. To solve this, please change the above line of code to:
databaseReference.push().setValue(jobs);
In this case, your new structure will look like this:
Firebase-root
|
--- Jobs
|
--- pushedId
|
---deadline: "September"
|
---description: "Intern Software Developer"
|
---location: "Moi Avenue Street"
And the rest of the code should work.
P.S.
Don't ignore potential errors!
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage());
}
Always log the error message.
Give a photo or your realtime database architecture.
that will help much to ans this issue.
Related
how can i retrieve all hospitalNames from Hospitals where all userIds are unknown.
There are two main ways to navigate the DataSnapshot that you get in onDataChange.
If you know the name of a child node in a snapshot, you can use snapshot.child("hospitalData") to get that child snapshot from its parent.
If you don't know the name of the children in a snapshot, you can loop over snapshot.getChildren() to access each child snapshot.
By combining these, you can navigate any structure.
So you'll want to loop over the users with getChildren(), then access child("hospitalData") of each user, and get the values of each individual property with something like child("hospitalName").getValue(String.class).
How about this.
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("medicine/Hospitals");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
hospitalArrayList.clear();
for (DataSnapshot item : dataSnapshot.getChildren()) {
Hospital hospital = item.getValue(Hospital.class);
hospitalArrayList.add(hospital);
System.out.println(hospital);
}
dataRetrieved();
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
private void dataRetrieved() {
adapter.notifyDataSetChanged();
}
Hospital.java simple example
public class Hospital {
public HospitalData hospitalData;
public Hospital(HospitalData hospitalData) { }
public Hospital() { }
public static class HospitalData {
public String hospitalName;
public String hospitalAddress;
public HospitalData(String hospitalName, String hospitalAddress) { }
public HospitalData() { }
}
}
You can use this in adapter like this.
String name = hospitalArrayList.get(position).hospitalData.hospitalName;
You have to modify your structure.
Make a new Node name hospital and put userId in each hospital object
i.e
- medicine
..........
- medicineData
..........
- Patients
..........
- Pharmacies
..........
- hospitals
..........
Using Android Studio and Firebase, i'm trying to write and read some data.
I have a Pub Class which contains the folowing:
package com.example.jef.pubbuddy.Database;
import java.util.ArrayList;
public class Pub {
private String name;
private float longitude;
private float lattitude;
private ArrayList<Pub> Pubs = new ArrayList<>();
public Pub() {}
public void setName(String name)
{this.name = name;}
public void setLongitude(float longitude)
{this.longitude = longitude;}
public void setLatitude(float lattitude)
{this.lattitude = lattitude;}
public String getName()
{return name;}
public float getLatitude()
{return lattitude;}
public float getLongitude()
{return longitude;}
I write my Pub object to the database using the .push() method. Below is how i write it to the database. It appears just fine in the Firebase console, so I believe the problem doesn't lie here:
Pub p1 = new Pub();
p1.setName("The name of the pub");
p1.setLatitude((float) 4.699545);
p1.setLongitude((float) 50.878267);
myRef.child("PUSH_TEST").push().setValue(p1);
Afterwards I try to read it using the following code. Please note the message method is just used to append some information to a TextView, so i'm able to debug on my physical device. However, none of the listener events get triggered.
Does anyone knows what i'm doing wrong here? Already followed the official firebase documentation and the "Firebase in a weekend" training videos. Also looked up countless answers here on Stackoverflow, but I can't seem to make it work.
Thanks in advance.
public class Database extends AppCompatActivity {
private TextView tv;
int messages;
private ArrayList<Pub> pubList = new ArrayList();
private FirebaseDatabase database;
private DatabaseReference myRef;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_database);
database = FirebaseDatabase.getInstance();
myRef = database.getReference();
init();
writeData();
message("creating and attaching the listener");
ChildEventListener myListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s)
{
message("The childEvent triggered");
Pub p = dataSnapshot.getValue(Pub.class);
message("The name of this pub = " + p.getName());
pubList.add(p);
}
#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) {}
};
myRef.child("PUSHTEST").addChildEventListener(myListener);
}
Everything is correct, except this:
Here you set the value:
myRef.child("PUSH_TEST").push().setValue(p1);
and here you retrieve the value:
myRef.child("PUSHTEST").addChildEventListener(myListener);
the child that you wrote is wrong as it is not in your database. So just change it into this:
myRef.child("PUSH_TEST").addChildEventListener(myListener);
the name inside child(..) needs to be the same as in your database
You write data to "PUSH_TEST" child and trying to read from "PUSHTEST". Make it same.
For not getting similar errors in future, create a class called "Constants.java" and add constant strings inside it. Like,
public class Constants {
public static final String CHILD_NODE="PUSH_TEST";
}
So that , you can use this constant, where ever u need. Just call Constants.CHILD_NODE. So there will not be such errors.
I am using Firebase.
1. Question:
I create a Key with:
final String CHATS_CHILD = "chats/" + mFirebaseDatabaseReference.push().getKey();
mFirebaseDatabaseReference.child(CHATS_CHILD).push().setValue("and so on...");
The result you see in the picture. Now I created a key with childrens in Firebase but how to I get the key into my android app? (I mean the first key, after Chats)
2. Qestion is similar
You see the databe in my Picture. How can I get the first key after chats, when I search after the text? So for example I want the key which has as child the Text "Test1"
How to do that?
Thanks in advance.
I think you should flatten your data in order to get message key and chat key using just message text. You can keep actual messages in a separate path (like "messages") and keep only message keys inside related chat's path, as shown in the following structure:
Create Chat class:
public class Chat {
private Map<String, Boolean> messageKeys;
public Chat() {
// Default constructor required for calls to DataSnapshot.getValue(Chat.class)
}
public Chat(Map<String, Boolean> messageKeys) {
this.messageKeys = messageKeys;
}
public Map<String, Boolean> getMessageKeys() {
return messageKeys;
}
public void setMessageKeys(Map<String, Boolean> messageKeys) {
this.messageKeys = messageKeys;
}
}
..and Message class:
public class Message {
private String chatKey;
private String text;
private long time;
public Message() {
// Default constructor required for calls to DataSnapshot.getValue(Message.class)
}
public Message(String chatKey, String text, long time) {
this.chatKey = chatKey;
this.text = text;
this.time = time;
}
public String getChatKey() {
return chatKey;
}
public void setChatKey(String chatKey) {
this.chatKey = chatKey;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
}
Then query messages and find those whose text field is equal to the term you are searching, for example "Test1":
DatabaseReference chatsRef = FirebaseDatabase.getInstance().getReference("chats");
DatabaseReference messagesRef = FirebaseDatabase.getInstance().getReference("messages");
messagesRef.orderByChild("text").equalTo("Test1").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
String messageKey = child.getKey();
Message message = child.getValue(Message.class);
String chatKey = message.getChatKey();
// Now you have both the chatKey and the messageKey...
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
Creating a new chat and its first message would look like below in this case (can be considered as answer to your first question):
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
String chatKey = rootRef.push().getKey();
String messageKey = rootRef.push().getKey();
Message newMessage = new Message(chatKey, "My message trial", Calendar.getInstance().getTimeInMillis());
Map<String, Boolean> messageKeys = new LinkedHashMap<>();
messageKeys.put(messageKey, true);
Chat newChat = new Chat(messageKeys);
rootRef.child("messages").child(messageKey).setValue(newMessage);
rootRef.child("chats").child(chatKey).setValue(newChat);
Retrieving all messages that belongs to a chat whose key is known:
String chatKey = "chatKey1"; // Get it somehow
DatabaseReference messagesRef = FirebaseDatabase.getInstance().getReference("messages");
messagesRef.orderByChild("chatKey").equalTo(chatKey).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<Message> messageList = new ArrayList<>();
for (DataSnapshot child : dataSnapshot.getChildren()) {
String messageKey = child.getKey();
Message message = child.getValue(Message.class);
messageList.add(message);
}
// Now you have all messages in messageList...
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
in additional to answer of Mehmed: Firebase DB supports not only setting/retrieving single fields, but also whole the objects of some class.
In the example below I define class MyChat, create few objects of it and put them into Firebase DB. Then I retrieve all of them (as objects, not just strings) and put them into ArrayList.
FirebaseDatabase frDb = FirebaseDatabase.getInstance();
DatabaseReference mFirebaseDatabaseReference = frDb.getReference();
final String CHATS_CHILD = "chats/theChat" ; //+ mFirebaseDatabaseReference.push().getKey();
// Create 3 objects of class MyChat
MyChat chat1 = new MyChat("Test1", "21-Sep-2017");
MyChat chat2 = new MyChat("Test21", "26-Sep-2017");
MyChat chat3 = new MyChat("TestB", "28-Sep-2010");
//Add all the chats to Firebase DB
mFirebaseDatabaseReference.child(CHATS_CHILD).push().setValue(chat1);
mFirebaseDatabaseReference.child(CHATS_CHILD).push().setValue(chat2);
mFirebaseDatabaseReference.child(CHATS_CHILD).push().setValue(chat3);
// Here we will retrieve all the chats and put them to array
// Declare array to keep results
final ArrayList<MyChat> arr1 = new ArrayList<MyChat>();
//Listener
ChildEventListener chEvLst = mFirebaseDatabaseReference.child("chats").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot ds1 : dataSnapshot.getChildren()) {
MyChat chatRes = ds1.getValue(MyChat.class);
Log.i("Next chat text:",chatRes.getmText());
Log.i("Next chat date:",chatRes.getmText());
arr1.add(chatRes); // retrieve and save chats to array
}
}
#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) {
}
});
And this is class MyChat
public class MyChat {
String mText = "Test1"; // default values...
String mDate = "26-Sep-2017";
// *** MUST TO HAVE EMPTY CONSTUCTOR FOR FIREBASE !!! ***
public MyChat() {
}
// Second constructor
public MyChat(String mText, String mDate) {
this.mText = mText;
this.mDate = mDate;
}
// *** MUST TO HAVE ALL GETTERS/SETTERS FOR FIREBASE!!! ***
// Getters/setters
public String getmText() {
return mText;
}
public void setmText(String mText) {
this.mText = mText;
}
public String getmDate() {
return mDate;
}
public void setmDate(String mDate) {
this.mDate = mDate;
}
}
And this is resulting DB structure :
Best regards!
How Can I get ArrayList of Java Objects of all Childs from Firebase using updated firebase commands, currently I am using below approach but not able to get the list.
ValueEventListener postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get Post object and use the values to update the UI
if(dataSnapshot!=null){
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
UserDataClass post = postSnapshot.getValue(UserDataClass.class);
members.add(post);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
}
};
mDatabaseRef.addValueEventListener(postListener);
below is datasnapshot which is returning from firebase but I am not able to get the desired result out of it.
DataSnapshot { key = 12345, value = {Members={00000000={phoneNo=00000000, longitude=73.0703307, latitude=33.6396975, password=qwertyuiop, CName=00000000, admin=true, name=Anwar Kamal}, 03028084374={phoneNo=03028084374, longitude=73.0701292, latitude=33.6397129, password=qwerty, CName=00000000, admin=false, name=Nehal Khan}, 03028084516={phoneNo=03028084516, longitude=73.0702659, latitude=33.6397622, password=qwerty, CName=03035356317, admin=false, name=Jamal Khan}}} }
all i want is list of all members
and my java object is
public class UserDataClass {
public double latitude;
public double longitude;
public String Name="";
public String password="";
public String phoneNo="";
public String CircleName="";
public boolean isAdmin=false;
}
The ValueEventListener has another purpose.
You should use ChildEventListener and also dataSnapshop.getValue() to implement what you want, for example:
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
UserDataClass post = postSnapshot.getValue(UserDataClass.class);
members.add(post);
}
//...
Note:
You should use the listener with the current firebase_referance to the Users table. Hence you should replace
mDatabaseRef.addValueEventListener(postListener);
with
mDatabaseRef.child("Members").addChildEventListener(childEventListener);
notice that your full path of the Members table is colored and i couldn't figure the path.
You can find the whole documentation here
good luck
So in the above data structure, I want to get value Aprilia Caponord 1200 (marked in fig.). I have Firebase reference to Aprilia (root node) and I can get all the key/value pair data.
Here's my code
#override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChild()) {
Map<?, ?> value = (Map<?, ?>) child.getValue();
String bike_price = value.get("price").toString();
String image_url = value.get("image_url").toString();
}
}
So clearly I can get all the values of child nodes having key/value relations. But I can't specifically get the name of the parent node. So how can I get the value of parent node in String format?
If I print child.getValue().toString(), I get JSON value, but I am not interested in parsing JSON. Is there any specific way to get parent node value?
{Aprilia Caponord 1200={image_url=____________, price=18.35}.. }
You're probably looking for the getKey() method on DataSnapshot:
mFirebaseRef = new Firebase("https://yours.firebaseio.com");
mFirebaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
Log.i("MainActivity", child.getKey());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("MainActivity", "onCancelled", firebaseError.toException());
}
});
A few things to note here:
I changed getChild() in your code to getChildren(), since there is not method getChild() that I'm aware of.
You should consider using addChildEventListener, which gives you DataSnapshots on the lower-level nodes
Things will get considerably easier if you create "wrapper classes" for your cars. The Firebase SDK for Android will then automagically unwrap the JSON into instances of that class. See our AndroidChat repo for a good example of this.
I met this case and solved the way as below:
final ChildEventListener countsListener = new ChildEventListener() { //for querying how many card created by each user in a specific period
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
/**
* $ROOT/Apirilia/Apirilia_id/CardId/IMG_URL
* $ROOT/Apirilia/Apirilia_id/CardId/PRICE
* ^[key] :[value]
*/
if (dataSnapshot == null) {
Logger.e("!!! dataSnapshot is null");
return;
}
String apirilia_id = dataSnapshot.getRef().getParent().getKey();
Logger.d("... Apirilia_id:" + apirilia_id);
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
I'm appreciated to be able to give one a hand.
for those who looking for key in firebaseUi then this code will work for u:-
firebaseadapterinstance.getRef(position).getKey();