Firebase Android failed to convert HashMap to String - android

I am getting an error while retriving data from Firebase in Android app.
Error
My code:
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = databaseReference.child(path);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
ClipboardManager clipboard = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
"path" - child's name.
And my

Your code read all data from the root of your data.
So what you get in the dataSnapshot passed to onDataChange is:
{
"uzmtn": "data"
}
Then you call dataSnapshot.getValue(String.class) on it, which isn't possible: the value in the snapshot isn't a string.
There are two simple options to fix it:
read data lower in the tree
get the correct child from the existing snapshot
I'll start with the second, since it stays closest to your code.
get the correct child from the existing snapshot
Since you're already getting the entire JSON in dataSnapshot, you can use the methods of the DataSnapshot class to find the value you want.
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = databaseReference.child(path);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.child("uzmtn").getValue(String.class);
ClipboardManager clipboard = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
While this works, you're reading slightly more data than is needed. It isn't too bad here, but as a general case: it is best to only read the precise data you need.
To do that, we can...
read data lower in the tree
Instead of listening for the root of the database, you can attach a listener straight to the uzmtn node:
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("uzmtn");
DatabaseReference ref = databaseReference.child(path);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
ClipboardManager clipboard = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
If you do that, the dataSnapshot will contain precisely the string you are looking for:
"data"
And with this in the snapshot, the call to dataSnapshot.getValue(String.class) will work.

You are returning a hashmap type because you didn't specify what child you want to return . Imagine your data structure like a tree in firebase database , each node has its own value .
What you want to return it's the child node from a tree , but instead , you return the node itself , which will return the node itself and the whole child node .
Simple solution is
dataSnapshot.child('emtz').getValue() .....

Related

Firebase user details are not retrieved in Android

I am storing user details 'firstname' and 'lastname' in UserNode. But when i want to retrieve that details then no data is being retrieved. I tried almost all solutions on the internet but nothing solved my problem. Here is my code for retrieving data of the current user:
FirebaseUser userr = FirebaseAuth.getInstance().getCurrentUser();
if (userr != null) {
String name = userr.getDisplayName();
Log.e("value", name);
}
but it says "println needs a message"
I also tried with this but nothing happened:
DatabaseReference DataRef;
DataRef = FirebaseDatabase.getInstance().getReference().child("UserNode");
DataRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String acctname = (String)dataSnapshot.child("firstname").getValue();
Log.e("name", acctname);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
]1
Please help me I am stuck with it
You're reading a collection of user with a ValueEventListener. As the [Firebase documentation for reading lists with a value event](Listen for value events) explains:
While using a ChildEventListener is the recommended way to read lists of data, there are situations where attaching a ValueEventListener to a list reference is useful.
Attaching a ValueEventListener to a list of data will return the entire list of data as a single DataSnapshot, which you can then loop over to access individual children.
Even when there is only a single [child node], the snapshot is still a list; it just contains a single item. To access the item, you need to loop over the result.
So in your code:
DatabaseReference DataRef;
DataRef = FirebaseDatabase.getInstance().getReference().child("UserNode");
DataRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String acctname = (String)childSnapshot.child("firstname").getValue();
Log.i("name", acctname);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
Using FirebaseUser:
FirebaseUser implements UserInfo and in UserInfo's getDisplayName() documentation says
Returns the user's display name, if available.
So, it is possible that FirebaseUser.getDisplayName() return null when display name is not set. In that case Log.e() receives null as message and therefore prints println needs a message
Using your own structure:
Instead of using type conversion use getValue(Class<T>) like so:
String acctname = dataSnapshot.child("firstname").getValue(String.class);
Please, read how to retrieve data from firebase. I think you have a problem because you don't have Class Model.
Your steps:
Create model UserModel with firstname and lastname field
Use listener (example from docs):
// Attach a listener to read the data at our posts reference
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Post post = dataSnapshot.getValue(Post.class);
System.out.println(post);
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
See other answers: How to retrieve data from one single userID Firebase Android and retrieving data from firebase android

Unable to retrieve data from Firebase Realtime Database

I'm trying to display the "loc" of a part if its part number I given.
Here is what the data structure looks like:
{
"parts":{
"14521845": { "name":"TOOL EC160B/EC180B/EC210B/EC240", "loc":"EXC1", "sloc":"B3EGU01C03"},
"12829050": { "name":"SWITCH; IGNITION SWITCH", "loc":"PS01", "sloc":"85-06-013"},
"12829050": { "name":"SWITCH; IGNITION SWITCH", "loc":"COM1", "sloc":"B3RGK03D06"},
"20044893": { "name":"PARTS CATALOG_ENG_SPA_FRE_GER_KOR_EC210D", "loc":"EXC1", "sloc":"B3EGT01B02"}
}
}
Activity Code:
FirebaseDatabase firebaseDatabase=FirebaseDatabase.getInstance();
DatabaseReference databaseReference =firebaseDatabase.getReference("parts/"+curP);
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Products data=dataSnapshot.getValue(Products.class);
Log.i("",String.valueOf(data.getLoc()));
}
getLoc is the getter function for the Product class, and it returns the corresponding "loc" for the given curP. curP denoted the child values in parts.
The logic seems right to me, but I am not getting an output. Where am I going wrong here?
try this
getReference("parts").child(curP).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Products data = dataSnapshot.getValue(Products.class);
Log.i("", String.valueOf(data.getLoc()));
}
});
The problem is that what you are getting in onChildAdded() is not a whole Product object as you expect it to be.
In your database reference you are targeting a specific Product ("parts/"+curP) but using a ChildEventListener. The children of a specific product node are name, loc and sloc, so the onChildAdded() will trigger several times, giving you each of these properties as a dataSnapshot separately.
The two patterns you might use to get whole Product objects are either:
add a ChildEventListener directly to the "parts" node and you will get each of the Products as a child of that node, or;
if you are adding a listener directly to the node of a particular product, use a ValueEventListener, to get the whole of that nodes entry as one dataSnapshot.
You can try to use ValueEventListener. If you want read data once so use the addListenerForSingleValueEvent method, something like this:
private void getFirebaseLocValue(int curP) {
FirebaseDatabase firebase = FirebaseDatabase.getInstance();
DatabaseReference mDatabase = firebase.getReference("parts");
mDatabase.child(Integer.toString(curP))
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.hasChildren()) {
Products data = dataSnapshot.getValue(Products.class);
Log.e("TAG", data.getLoc());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Or you can use addValueEventListener and will get data with any changes. I really don't think that ChildEventListener is a good idea to retrieve data from Firebase.

Get element by key with Firebase

I've been trying to retrieve an element from my Firebase database using its key. I have a class User and users are present in database.
I want to retrieve an object user using its key with this method :
public User getConnectedUserByUId(final String uid){
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = database.child("users");
final List<User> connectedUser= new ArrayList<User>();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot item: dataSnapshot.getChildren()) {
if (item.getKey()==uid)
{
User user= dataSnapshot.getValue(User.class);
connectedUser.add(user);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return connectedUser.get(0);
}
but it returns an empty list every time.
The issue is here:
if (item.getKey()==uid)
since you are comparing 2 String in java you have to use the method
string.equals(Object other) not the == operator.
Moreover, since you know the key of the data in Firebase you can use it to get the reference without cycling all children.
Something like:
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = database.child("users").child(uid);
Here you try to check a very specific ID only on changed data. Instead, try using a Firebase Query with filterByKey and not using your own function to achieve that. Here's sample code that I would use to try to replace your function:
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = database.child("users");
Query connectedUser = ref.equalTo(uid);
connectedUser.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
// TODO: handle the post here
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// ...
}
});
As specified in the Firebase documentation here: https://firebase.google.com/docs/database/android/lists-of-data#filtering_data
in the line : User user= dataSnapshot.getValue(User.class);
you have to put : User user= item.getValue(User.class);
and you have to check the id after you get the user:
if (user.getKey()==uid){
connectedUser.add(user);
}
There are 2 mistakes and a minor issue:
you are using == to compare two String objects. In java, this is true only if they are the same reference. Use equals instead.
addValueEventListener only adds a listener that gets invoked once after you add it and then every time something changes in the value you are listening to: this is an asynchronous behaviour. You are trying to get data synchronously instead. Please read something about this.
you are fetching useless data: you only need an object but you are fetching tons of them. Please consider to use the closest reference you can to the data you are fetching.
So, in conclusion, here's some code. I'd like to point out right now that forcing synchronous acquisition of naturaly asynchronous data is a bad practice. Nevertheless, here's a solution:
public User getConnectedUserByUId(final String uid){
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = database.child("users").child(uid);
Semaphore sem = new Semaphore(0);
User[] array = new User[1];
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot item: dataSnapshot.getChildren()) {
if (item.getKey()==uid)
{
User user= dataSnapshot.getValue(User.class);
array[0] = user;
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
try
{
sem.tryAcquire(10, TimeUnit.SECONDS);
}
catch (Exception ignored)
{
}
return array[0];
}
EDIT: I've just seen that this post is very old. I'm not sure how I ended up here.

How to get the key in firebase

I want to retrieve the messages data under a specific key. But I don't how to get the key. Please help, I'm new to firebase.
In my case right now, I want to get the key encircled below.
I have tried this code below but this returns "chat-mates" not the key.
final DatabaseReference ref =FirebaseDatabase.getInstance().getReference().child("chat").child("single-chat").child("converstation").child("chat-mates");
ref.orderByChild("receiverName").equalTo("Liza Soberano").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()){
String key = child.getKey();
Log.e("Key", key);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I have tried this code below but this returns "chat-mates" not the key.
You must be using DataSnapshot method to access the JSON tree.
The DataSnapshot element has a method called getKey(). That returns the key of an object.
Official Doc: DataSnapShot getKey() method
Example Code:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot objSnapshot: snapshot.getChildren()) {
Object obj = objSnapshot.getKey();
}
}
#Override
public void onCancelled(DatabaseError firebaseError) {
Log.e("Read failed", firebaseError.getMessage());
}
});
In your case, first get to the child node "conversation" and then apply the above method getKey().
You're building your path wrong and likely end up iterating a different part of the tree, one level above child-mates. In that case it would be correct that child-mates is a child key.
The problem is in the last child() call when you create the ref:
final DatabaseReference ref =FirebaseDatabase.getInstance().getReference()
.child("chat")
.child("single-chat")
.child("converstation")
.child("chat-mates");
There is no child chat-mates under converstation, so this ref won't be correct.
You probably want to do this:
final DatabaseReference ref =FirebaseDatabase.getInstance().getReference()
.child("chat")
.child("single-chat")
.child("converstation");
ref.orderByChild("chat-mates/receiverName")
.equalTo("Liza Soberano")
.addListenerForSingleValueEvent(new ValueEventListener() {
This will filter on the chat-mates/receiverName child of each chat.
Note that you're going against one of Firebase's recommendations with this data structure. Firebase recommends against nesting data types in the way you do here.
A more denormalized data model would be:
chat-mates
$chatRoomId
receiverName
senderName
chat-messages
$chatRoomId
$messageId
This way you can get the mates/participants in a chat, without accessing (or even needing to have access to) the messages themselves.

How to retrieve all objects from a Node in Firebase database?

I followed the documentation, but no matter what, I cannot figure out how to return all the objects from a single node. For example, I want to return a list of all company objects from the companies node. Once I have that list, I want to parse them all into JSON objects. This is my first time with a NoSQL database so I'm sure that I'm missing something small.
Currently I have:
DatabaseReference companiesRef = FirebaseDatabase.getInstance().getReference("12265");
companiesRef.child("companies").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("Count ", dataSnapshot.getChildren().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
But it just returns null for the value: DataSnapshot { key = companies, value = null }.
Here's my database:
You create your reference like this:
FirebaseDatabase.getInstance().getReference("12265");
This means that Firebase looks at the root of the database and returns the child 12265 from under there. It does not automatically search the tree for a node with a matching name.
So you'll need to specify the entire path:
FirebaseDatabase.getInstance().getReference("android/users/12265");
Don't add any parameters to your getReference() (let it go to the root of database) and then set the addListenerForSingleValueEvent. And you have not used getvalue() on you datasnapshot as well. Try this code:
DatabaseReference companiesRef = FirebaseDatabase.getInstance().getReference();
// this is the patch that I see from the image that you have attached.
companiesRef.child("telenotes").child("android").child("user").child("12265").child("companies").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("Count ", dataSnapshot.getChildren().getValue().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Categories

Resources