Im using exists() method of the snapshot object in Firebase to check if user exists on pressing the SignUp(register) button. But as soon as I press the button, both the if and else conditions are executed(else first). What is going wrong?
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("users");
register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
databaseReference.addValueEventListener(new ValueEventListener() {
public static final String TAG = "user_REG";
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.child(mobileNumber.getText().toString()).exists()){
Log.d(TAG, "onDataChange: if fired");
} else {
Log.d(TAG, "onDataChange: else fired");
if(confirmPass.getText().toString().trim().equals(userPass.getText().toString().trim())){
userModel userModel = new userModel(fullName.getText().toString(), userPass.getText().toString());
databaseReference.child(mobileNumber.getText().toString()).setValue(userModel);
Toast.makeText(user_reg.this, "Successfully Signed Up", Toast.LENGTH_SHORT).show();
finish();
} else {
Toast.makeText(user_reg.this, "Your Passwords do not match", Toast.LENGTH_SHORT).show();
}
}
}
First time mobileNumber doesn't exist, So else part is executed and child node value is added and as data is added under same node, onDataChange will fire again and this time, if part will be executed.
To prevent the onDataChange to call twice, Use SingleEventListener instead of ValueEventListener Like this
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = (String) dataSnapshot.getValue();
// do your stuff here with value
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Related
I have created a Like button in the App. When user click on the Like Button a Node called "Like Posts" with a child (random Key) is created where the details of the posts are saved as you can see in the Image.
But, when i click on the Like button again, the node should get removed as per standards. But, that's not happening.
This is my code :
holder.fav.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String id = likesReference.push().getKey();
FirebaseDatabase.getInstance().getReference("Users").child(firebaseAuth.getUid()).child("Liked Posts").child(id).removeValue();
Toast.makeText(context, "Removed from Favorites !", Toast.LENGTH_SHORT).show();
} else {
likesReference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseAuth.getUid()).child("Liked Posts");
Toast.makeText(context, "Added to Bookmarks", Toast.LENGTH_SHORT).show();
likesReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
HomeModel homeModel1 = new HomeModel(holder.newsTitleTextView.getText().toString().trim(), holder.newsDetailTextView.getText().toString().trim(),
holder.timesAgo.getText().toString().trim(), homeModel.getNewsImage(), homeModel.viewCounts);
String id = likesReference.push().getKey();
Log.e("KEY IS", id); //right one
likesReference.child(id).setValue(homeModel1);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
How to delete the "Liked Posts" ?
Why do I keep getting duplicated data whenever I attempt to delete something from my firebase? In my onStart method I received users informations suscessfully , and I am trying to delete a specific tapped item but whenever I do so I keep getting duplicated data. Why is this?
//looped through Contact node access receiver UID and searched user ref for necessary information..
#Override
public void onStart() {
super.onStart();
contactsRef.child(currentFirebaseUser.getUid()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dsp : dataSnapshot.getChildren()) {
usersFriendsKey = dsp.getKey();
Log.i("friendsKey", usersFriendsKey);
usersRef.child(usersFriendsKey).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userData = dataSnapshot.getValue(UserData.class);
contactsArrayList.add(userData);
chatListAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
String error = databaseError.getMessage();
Toast.makeText(getActivity(), "Error occured", Toast.LENGTH_SHORT).show();
}
});
}
}
Deletes item
//Creates popup and allows user to delete a post from recycle view...
public void deletePostMenu(final View v, final int position) {
PopupMenu popup = new PopupMenu(v.getContext(), v);
popup.getMenuInflater().inflate(R.menu.delete_menu, popup.getMenu());
selectedUserId = contactsArrayList.get(position).getUser();
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.deleteMenu:
contactsRef.child(currentFirebaseUser.getUid()).child(selectedUserId).removeValue();
return true;
default:
//default intent
return true;
}
}
});
popup.show();
}
Like Imran says, when you attach an addValueEventListener to a reference, it will open a socket to keep listening to changes into that reference.
When you do a delete, update or any change to that reference, the trigger will fire and you will be adding new elements at that reference from your first code snippet.
What you can do is attach a addListenerForSingleValueEvent and it will only trigger once.
So, after you delete a certain node, it will not fire the other code that is listening to that node.
#Override
public void onStart() {
super.onStart();
contactsRef.child(currentFirebaseUser.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dsp : dataSnapshot.getChildren()) {
usersFriendsKey = dsp.getKey();
Log.i("friendsKey", usersFriendsKey);
usersRef.child(usersFriendsKey).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userData = dataSnapshot.getValue(UserData.class);
contactsArrayList.add(userData);
chatListAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
String error = databaseError.getMessage();
Toast.makeText(getActivity(), "Error occured", Toast.LENGTH_SHORT).show();
}
});
}
}
In my code, when user click on a button, it calls a function.In that function data has to loaded from firebase. On successful of loading, Intent will pass to another activity with some putExtra data.
SharedPreferences pref = getApplicationContext().getSharedPreferences("My_pref", MODE_PRIVATE);
choice = pref.getInt("language", 0);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(choice==1)
{
firebase("param1","param2","English");
}
if(choice==2)
{
firebase("param1","param2","hindi");
}
}
});
public void firebase(String files,String titles,String language)
{
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference(language);
DatabaseReference myRef1=myRef.child(titles);
DatabaseReference myRef2=myRef.child(files);
myRef1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
language_title = dataSnapshot.getValue(String.class);
t=1;
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
myRef2.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
language_file= dataSnapshot.getValue(String.class);
f=1;
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
if(t==1&&f==1) {
Intent i = new Intent(getApplicationContext(), caf.class);
i.putExtra("titles", language_title);
i.putExtra("files", language_file);
startActivity(i);
}
}
But in that case intent is only passing when I click twice.In single click Intent is not passing. where is the problem?
Any code that needs data from the database, needs to be inside the onDataChange method or be called from there.
See my answer here for a longer explanation: getContactsFromFirebase() method return an empty list.
Since you have two onDataChange methods, you'll need to make sure both have been called before starting the new activity. Using some simple flag variables to track state, you can do that with:
Declare two member fields:
boolean isTloaded, isFLoaded;
And then
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference(language);
DatabaseReference myRef1=myRef.child(titles);
DatabaseReference myRef2=myRef.child(files);
isTloaded = false;
isFloaded = false;
myRef1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
language_title = dataSnapshot.getValue(String.class);
t=1;
isTloaded = true;
if (isTloaded && isFloaded) {
startCafActivity();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
myRef2.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
language_file= dataSnapshot.getValue(String.class);
f=1;
isFloaded = true;
if (isTloaded && isFloaded) {
startCafActivity();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
And then finally:
private void startCafActivity() {
if(t==1&&f==1) {
Intent i = new Intent(getApplicationContext(), caf.class);
i.putExtra("titles", language_title);
i.putExtra("files", language_file);
startActivity(i);
}
}
It might be even simpler, but I had a hard time figuring out your application logic due to the variable names. Consider using more descriptive named than t, f and caf to make it easier for others (and your future self) to understand what each part of the code does in isolation.
My code is as shown below:
private DatabaseReference mFirebaseDatabase;
private FirebaseDatabase mFirebaseInstance;
private static final String TAG = "OrderManagementFragment";
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_order_managment, container, false);
//get reference to the orders node
mFirebaseDatabase = mFirebaseInstance.getReference("orders");
// app_title change listener
mFirebaseInstance.getReference("58ca237b2e2c211dc0c7ed9b").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Toast.makeText(getActivity(), dataSnapshot.getValue(String.class), Toast.LENGTH_LONG).show();
Log.d(TAG, "onDataChange: " + dataSnapshot.getValue(String.class));
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_LONG).show();
Log.d(TAG, "onCancelled: " + error.getMessage());
}
});
return view;
}
My credentials for firebase is as shown below:
Now, what happens here is , whenever data is changed from backend side , onDatachange method never gets called.So is there anything missing in this method?
I am testing this via android emulator, so is it the problem ?
I change your code, u dont need reference inconstructor becouse aplication method will know what u need.
Data is not changed becouse u no have static like textView on your layout. When you got a Toast, its start once so u cant see that its changed
//get reference to the orders node
mFirebaseDatabase = mFirebaseInstance.getReference();
// app_title change listener
mFirebaseInstance.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Toast.makeText(getActivity(), dataSnapshot.child("YOUR REFERENCE HERE")getValue(String.class), Toast.LENGTH_LONG).show();
}
I give you example from my application:
mDatabase = FirebaseDatabase.getInstance().getReference();
settingsText2.setText("Loading...");
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
settingsTextWithScrollView.setText(dataSnapshot.child("Youtube1").child("Text").getValue(String.class));
settingsText2.setText(dataSnapshot.child("Youtube1").child("Information").getValue(String.class));
settingsTextWithScrollView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openYoutubeIntent(dataSnapshot.child("Youtube1").child("Link").getValue(String.class));
}
});
settingsText3.setText(dataSnapshot.child("Youtube2").child("Text").getValue(String.class));
settingsText4.setText(dataSnapshot.child("Youtube2").child("Information").getValue(String.class));
settingsText3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openYoutubeIntent(dataSnapshot.child("Youtube2").child("Link").getValue(String.class));
}
});
settingsText5.setText(dataSnapshot.child("Youtube3").child("Text").getValue(String.class));
settingsText6.setText(dataSnapshot.child("Youtube3").child("Information").getValue(String.class));
settingsText5.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openYoutubeIntent(dataSnapshot.child("Youtube3").child("Link").getValue(String.class));
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
its a static call like this
FirebaseDatabase database=FirebaseDatabase.getInstance();
DataBaseRefrence dbRef=database.getRefrence("nodeOfData");
DataSnapshot ds=dbRef.getChildren("gettingWhatIsInNodeOfData"); or
better yet chain them DataSnapshot
ds=FirebaseDatabase.getInstance().getRefrence("orders").getChildren();
I want to increment score by 1 when user clicks a button, but value of score is not updated. When I updated it manually from Firebase console it updates. I don't know what the problem is. Can anyone help me, please?
#Override
public void onClick(View view) {
if (view == add) {
score++;
databaseReference1 = databaseReference.child("score");
databaseReference1.setValue(String.valueOf(score));
databaseReference1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
textView_earning.setText(score + " ");
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
You have to add the value event listener before changing the value.
#Override
public void onClick(View view) {
if (view == add) {
score++;
ref1 = ref.child("score");
ref1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
textView_earning.setText(score + " ");
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
ref1.setValue(String.valueOf(score));
}
}
If you place addValueEventListener inside onClick(), you'll end up attaching one more listener into databaseReference1 every time the button clicked. It is not a best practice as you'll face more kind of problem if it is clicked multiple time.
You should place addValueEventListener somewhere else, like (not limited to) in activity's onCreate() method:
... onCreate(...) {
databaseReference1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
And place score variable where it is easily got, and update it inside onDataChange() (for this example, I place it on scoreValue:
private String scoreValue;
... onCreate(...) {
databaseReference1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
scoreValue = dataSnapshot.getValue(String.class)
}
...
And then inside onClick(), you just need to get scoreValue, increment it by 1, and save the value:
... onClick() {
if (view == add) {
scoreValue++;
databaseReference.child("score").setValue(scoreValue);
}
}
Then setValue(scoreValue) will update the value at the online database, and trigger onDataChange(). So don't worry if the value is changed online, scoreValue will always have updated value.
Hope this helps.
Note: all of this consider score value is at (your databaseReference
path)\score
you can use updateChildren for update single values.
Firebase ref = new Firebase(Constants.FIREBASE_URL);
HashMap<String, Object> hm = new HashMap<String, Object>();
hm.put("score", score++);
ref.child("YOUR_ROOT_NODE")
.updateChildren(hm);
thanks all for your answer,the problem is fixed,actually i make a stupid mistake as i do not set on click listener on my button