Cannot Copy Firebase Database Node Data to Another Node - java

I am simply trying to copy information I have saved in one Firebase location to another:
mFollowingCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b){
mBaseRef.child(USERS_LABEL).child(mUserID).child(FOLLOWING_LABEL).child(USERS_LABEL).child(mPollCreatorID).child(DISPLAY_NAME_LABEL).setValue(mPollCreatorDisplayName);
mBaseRef.child(POLL_LABEL).child(pollID).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mBaseRef.child(USERS_LABEL).child(mUserID).child(FOLLOWING_LABEL).child(POLL_LABEL).child(pollID).setValue(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getContext(), databaseError.getCode(), Toast.LENGTH_LONG).show();
}
});
} else {
mBaseRef.child(USERS_LABEL).child(mUserID).child(FOLLOWING_LABEL).child(USERS_LABEL).child(mPollCreatorID).child(DISPLAY_NAME_LABEL).removeValue();
}
}
});
When I have this code, the app is simply crashing. There is no logging error and I am unable to pinpoint exactly what I am doing incorrectly. Essentially, I would like to know best practice for copying Firebase data.

In onDataChange() you should be storing the value of the DataSnapshot, not the Datasnapshot object itself.
Change:
setValue(dataSnapshot);
to
setValue(dataSnapshot.getValue());
Also, your code to show a Toast is wrong:
Toast.makeText(getContext(), databaseError.getCode(), Toast.LENGTH_LONG).show();
databaseError.getCode() returns an int, which means you are calling the form of makeText() that expects a string resource ID. Change to:
Toast.makeText(getContext(), databaseError.getMessage(), Toast.LENGTH_LONG).show();

Related

Firebase Realtime Databse DataSnapshot only Read the last value in the child

I'm calling addValueEventListener inside the button click, but this method only reads the last item in the node. I want to read all the child value in the node What went wrong here?
btnorder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot dataSnapshot1:dataSnapshot.getChildren())
{
SelectedItems si=dataSnapshot1.getValue(SelectedItems.class);
si.getItemname();
Toast.makeText(MyBookedItems.this, ""+si.getItemname(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
I think you can create an array list and put all snapshot data into it, and then you can find the last data of the list with the value you find by subtracting one from the length of the list. Sorry for my bad English :( I have tried to explain in the solution in the code below)
ArrayList<SelectedItems> selectedItems = new ArrayList<SelectedItems>();
for(DataSnapshot dataSnapshot1:dataSnapshot.getChildren())
{
SelectedItems si=dataSnapshot1.getValue(SelectedItems.class);
selectedItems.add(si);
}
selectedItems.get(selectedItems.size());
It's read all the values but I got the output as a Toast message, because of that I only see the last value)

How can I read values from Firebase Realtime Database by using a Java method in AndroidStudio?

My Firebase Realtime Database has been built by loading an object of the Java class HashMap. In my Android Studio app I'm trying to write a method that takes a String (the key) as input, searches through the database and if the string is found it returns the associated Float (the value), otherwise it returns 0. How can I do this? Any help would be really appreciated!
EDIT: I've tried to follow the suggestions, adapting them to my particular case, but I didn't manage to solve the problem yet.
I wrote the following code in MainActivity:
DatabaseReference myRef;
Float tempValue;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
myRef = FirebaseDatabase.getInstance().getReference("myRoot");
tempValue=0f;
...
}
public void retrieveValueFromDatabase(String childName, final MainActivity activity){
myRef.child(childName).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Float value=dataSnapshot.getValue(Float.class);
if (value==null){
value=0f;
}
activity.tempValue=value;
//First Toast
//Toast.makeText(activity,"tempValue = "+tempValue.toString(), Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
public void useValues(){
retrieveValueFromDatabase(childName,this);
//Second Toast
//Toast.makeText(this,"tempValue = "+tempValue.toString(), Toast.LENGTH_LONG).show();
//code using tempValue from here
...
}
If I uncomment the first toast, the correct value inside tempValue is shown, but if I uncomment the second toast, the value of tempValue shown is the default one (0.0). What am I missing?
You need to use addValueEventListener to retrieve data from the database:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("myRoot").orderByChild("name").equalTo("peter");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i("Database", dataSnapshot.child("floatValue").getValue(Long.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})
Here, you add a reference to the root node, then query using equalTo() to check if name = peter exists in the database and return the float value.
You should read the guide:
https://firebase.google.com/docs/database/android/read-and-write

Notify user if Firebase database id exists

I want to check if an id already exists before inserting it (prevent updating an already existing id).
This is the code I have so far:
database.child(id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Toast.makeText(getApplicationContext(), "it exists.", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getApplicationContext(), "it's OK.", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
The problem is that, when the id does not exists, it shows both toasts. But, when it does exist, it only shows the "it exists." one.
How can I show the "it exists." toast only when the id exists / How can I prevent the "it exist." toast from showing when the id doesn't exist?
EDIT:
Firebase database structure:
-DATABASE
-ID
-NAME
-DESCRIPTION
Try like this
database.child(id).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue()!=null) {
Toast.makeText(getApplicationContext(), "it exists.", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getApplicationContext(), "it's OK.", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Please do this:
database.child(id).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Toast.makeText(getApplicationContext(), "it exists.", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getApplicationContext(), "it's OK.", Toast.LENGTH_SHORT).show();
}
}
Since the valueeventListener will iterate through all the child(id) thus you will get both Toast the one for exists and for does not exists.
Use the addListenerForSingleValueEvent then it will only iterate in the id that you specify before.
Try replacing your addValueEventListener Method with addListenerForSingleValueEvent .
Because possibly addValueEventListener will be called twice due to change in data Thats the reason it first shows Exist and than not Exist for same id.
For addListenerForSingleValueEvent firebase states that it supposed to:
Read Data Once.
In some cases it may be useful for a callback to be called once and
then immediately removed. We've created a helper function to make this
easy:

Android firebase no data query

Im using the Android SDK for firebase database.
In the database I have a structure where I keep the messages ordered by user, that way if I need their messages I just query by user.
myDatabase -> messages -> JonDoe
-> "You forgot your mail"
-> "Buy groceries"
-> JaneDoe
-> "Dog's birthday!"
The problem is if the user doesnt exist the listener keeps waiting forever, and I want to show "You have no messages" in that case. (For example, if I query the user "CharlesDoe" in the example above)
Is there a way to check if a reference exists before/after/during a query?
try this:
DatabaseReference root =FirebaseDatabase.getInstance().getReference();
DatabaseReference user = root.child("myDatabase").child("messages");
user.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.child("CharlesDoe").exists()) {
// run some code
}else{
Toast.makeText(this,"no messages",Toast.Length_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here it will query on node messages and then it will check if the child exists and do the required.
Try this on
DatabaseReference root =FirebaseDatabase.getInstance().getReference();
DatabaseReference user =
root.child("myDatabase").child("messages").child("CharlesDoe");
user.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.exists()) {
// run some code
}else{
Toast.makeText(this,"no messages",Toast.Length_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Value of variable changes after applying the same method twice Firebase

I have a Firebase database that I want to retrieve the friend ID from. This works perfectly as I'm getting the right value when logging the friendUserId in the for loop. However, the log at the end of the method only displays the right value after executing the method twice. At first it displays "s", the second time it displays the string that I want. I feel like it has got something to do with processing time of the query, but I'm not sure really. How do I solve this?
public String friendUserId="s";
public void checkUserExistence() {
mDatabase.child("Users")
.orderByChild("username")
.equalTo(EmailSearchQuery)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
friendUserId = childSnapshot.getKey();
Log.d("dwada",friendUserId);
}
} else
Toast.makeText(AddAFriend.this, "Gebruiker niet gevonden", Toast.LENGTH_LONG);
}
#Override
public void onCancelled(DatabaseError firebaseError) {
Log.e("MainActivity", "onCancelled", firebaseError.toException());
}
});
Log.d("dwada",friendUserId);
}

Categories

Resources