Deleting data and immediately creating a new one - android

I am deleting user's data in realtime database. However, whenever I am trying to delete it, there's this one child that remains. I don't know why it won't delete it, even though I have tried using .removeValue().
Here's the image of my database
as you can see the image above ( orange-ish line ) that is the data of the user, and every time I want to delete that user, the "termsAgreement" child remains, and here's my code on removing the whole child.
holder.btndel_stud.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle("Delete Student Record");
alert.setMessage("Are you sure you want to delete");
alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Users");
final String uniqueKey = addingStudentsArrayList.get(position).getUniqueid();
Toast.makeText(context, uniqueKey, Toast.LENGTH_SHORT).show();
databaseReference.child(uniqueKey).removeValue();
Toast.makeText(context, "Student has been deleted, re-authenticate to delete the Registered Email", Toast.LENGTH_SHORT).show();
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(context, "Cancelled", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
alert.show();
}
});
so basically the user have to agree on terms and condition first and this is my code whenever the user will agree on the terms and conditions.
checkBoxAgreement.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
AgreementBtn.setEnabled(isChecked);
AgreementBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseAuth userAuth = FirebaseAuth.getInstance();
final String firebaseUser = userAuth.getCurrentUser().getUid();
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
databaseReference.child("termsAgreement").setValue("yes");
Toast.makeText(TermsAndConditionActivity.this, "You have agreed to Terms and Condition", Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(), WelcomeStudentActivity.class));
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
});
}
});
I really don't know why the termsAgreement remains even tho I use .removeValue() to the unique id wherein the information was saved.

When a user logs in, you get them to agree to the terms agreement. When they click the "AgreementBtn", it writes "yes" to /Users/{USER_ID}/termsAgreement. However, when this "AgreementBtn" is clicked, it doesn't check if this user's data has been deleted first - it just writes the value anyway.
final DatabaseReference currentUserDataRef = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser);
currentUserDataRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (!snapshot.exists()) {
// this user's data has been deleted/doesn't exist yet
// TODO: do something, like re-register user
} else {
currentUserDataRef.child("termsAgreement").setValue("yes")
.addOnCompleteListener(TermsAndConditionActivity.this, new OnCompleteListener<Void> {
#Override
public void onComplete(Task<Void> task) {
/* TODO: listen for success/failure events here */
if (task.isSuccessful()) {
Toast.makeText(TermsAndConditionActivity.this, "You have agreed to Terms and Condition", Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(), WelcomeStudentActivity.class));
} else {
// TODO: Handle error in task.getException()
Toast.makeText(TermsAndConditionActivity.this, "Error when agreeing to terms: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
// TODO: Handle this error, don't ignore it.
Toast.makeText(TermsAndConditionActivity.this, "Error when fetching user data: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
So it appears there's nothing inherently wrong with your code, but one with the flow of events. If a user's account is deleted, you prompt them to login with that email, which when they do log in, it writes termsAgreement = "yes" to where their user data was deleted.
Note: Don't use databaseReference as a variable name. Use something meaningful such as usersRef (for /Users) or currentUserDataRef (for /Users/{USER_ID}) as appropriate.

So the problem is with your terms & conditions database ref:
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser);
Which is different from when you are deleting the data:
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Users");
They are not the same database ref.
That's why when you are trying to use removeValue() it's not deleting at the right location.

Related

How can I delete this Specific node from Firebase Database?

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" ?

Firebase's exists() function behaving abruptly

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

check if an email exists before creating a user firebase android

So the issue I am having is I have a registration form in which users enter information (which also contains an email).
I have an onClick method called
public void onCreateAccount(View view);
when the user clicks "Register", it validates the fields on the form.
public class Foo extends AppCompatActivity {
//OTHER PRIVATE MEMBERS
private EditText etEmail;
boolean isValid;
private DatabaseReference databaseUser = FirebaseDatabase.getInstance().getReference().child("User");
#Override
protected void onCreate(Bundle savedInstanceState) {
//DOES SOME INITIALIZATION
}
public void onCreateAccount(View view){
String email = etEmail.getText().toString().trim();
if(validateEmail(email)){
String id = databaseUser.push().getKey();
User user = new User(id, email);
databaseUser.child(user.getId()).setValue(user);
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.putExtra("isCreateAccount", true);
startActivityForResult (intent,0);
}
}
private boolean validateEmail(String email) {
isValid = true;
databaseUser.orderByChild("email").equalTo(emailUserEntered).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists())
isValid=false;
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Before inserting the record into the firebase database, I want to first check if the email already exists prior to inserting. So a person typing email = a#mail.com would not allow so.
Have an index on the email field. Then you can do a query to find by email.
That will improve performance as no need to loop through the children.
Something like:
orderByChild('email').equalTo(email).once('value').exist();
Data is loaded from Firebase asynchronously, which makes it impossible to have a method like boolean validateEmail(String email) on Android. Loading data from the database would have to be a blocking operation to enable such a method, and Android doesn't allow blocking operations (as it would leave the phone inoperable).
So instead, you have to *either( move the code to create the user into validateEmail or pass in a custom interface that you then call once the result from the database is back. The code for that last one is below.
First we'll create a custom interface that you can implement anywhere where you need to check if a user already exists.
public interface UserExistsCallback {
void onCallback(boolean value);
}
This interface can be as specific or generic as you want. It's very similar to Firebase's ValueEventListener, but this interface is just for your own use.
With this interface, we can define the validateEmail method like this:
private void validateEmail(String email, final UserExistsCallback callback) {
isValid = true;
databaseUser.orderByChild("email").equalTo(emailUserEntered)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
callback.onCallback(dataSnapshot.exists())
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
And then invoke it from onCreateAccount like this:
public void onCreateAccount(View view){
String email = etEmail.getText().toString().trim();
validateEmail(email), new UserExistsCallback() {
public void onCallback(boolean exists) {
if (!exists) {
String id = databaseUser.push().getKey();
User user = new User(id, email);
databaseUser.child(user.getId()).setValue(user);
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.putExtra("isCreateAccount", true);
startActivityForResult (intent,0);
}
})
}
}
Also see many of the (linked) answers below:
getContactsFromFirebase() method return an empty list
Setting Singleton property value in Firebase Listener
more questions about async loading
Stopping the user from logging in if such email exists should be simple and you may use a code like this to do so:
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("User");
boolean flag=false;
databaseReference.orderByChild("email").equalTo(emailUserEntered).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists())
flag=true;
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
return flag;
But if you want the user to be stopped from writing an email which is in database in mid-way, without authentication, it would be pretty difficult.
You'd have to run a check through the database letter by letter and not only this would decrease efficiency, it would be not so good looking at the end.
EDIT:
Data is loaded asynchronously from Firebase so you should be placing something like this right inside the if(dataSnapshot.exists()) to avoid the issue you're facing right now.
if(validateEmail(email)){
String id = databaseUser.push().getKey();
User user = new User(id, email);
databaseUser.child(user.getId()).setValue(user);
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.putExtra("isCreateAccount", true);
startActivityForResult (intent,0);
}
else
Toast(YourActivity.this, "Email already exists", LENGTH_LONG).show();
This method is for auth only: firebase.auth().fetchProvidersForEmail("emailaddress#gmail.com")

How to get the unique key of a Firebase database when one of its child is clicked in Android Studio

Firebase_database
Card_view_android
In my android app, the user creates events and details are sent to the firebase database. The event then is visible as a card view inside another activity.
I wish to make this as when the user clicks on +add me in that card, his details get added to that card. This part is ready, but I want his details to be pushed to the database as well. Can anyone help me?
FirebaseUser current_user = FirebaseAuth.getInstance().getCurrentUser();
String uid = current_user.getUid();
DatabaseReference eventRef = FirebaseDatabase.getInstance().getReference().child("Events").child("lists");
String key = eventRef.push().getKey();
final DatabaseReference groupRef = eventRef.child("").child(key);
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
final String uName = dataSnapshot.child("member").getValue().toString();
addMe.setText(uName);
groupRef.child("members").setValue(uName).addOnCompleteListener(new OnCompleteListener < Void > () {
#Override
public void onComplete(#NonNull Task < Void > task) {
Toast.makeText(v.getContext(), "Success Adding you in Event", Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(v.getContext(), "some error", Toast.LENGTH_LONG).show();
}
});
The above code just adds a member child below my firebase database. I wish to have it appended inside the key of the card view clicked.

Need the state of a Firebase thread

I´m using Firebase and in the login screen I have a method that it´s called when the user put the correct login credentials(that method start a Firebase thread in order to get all the info I need for the main screen), and when the main screen opened I need to wait until that method finish, I need some kind of flag or something, let me paste you my code:
Login.java:
mProgress.setMessage("Verificando Datos Usuario...");
mProgress.show();
mAuth.signInWithEmailAndPassword(usuario, pass)
.addOnCompleteListener(Login.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
Toast.makeText(Login.this, "Los Datos administrados no son correctos",
Toast.LENGTH_SHORT).show();
mProgress.dismiss();
} else{
Toast.makeText(Login.this, "Bienvenido... ",
Toast.LENGTH_SHORT).show();
AdminFirebase.loadAdmin(task.getResult().getUser());
mProgress.dismiss();
Intent intento=new Intent(Login.this, Principal.class);
startActivity(intento);
}
}
});
AdminFirebase.java:
public static void loadAdmin(FirebaseUser user){
DatabaseReference userRef=adminRef.child(user.getUid());
userRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Administrador administrador=dataSnapshot.getValue(Administrador.class);
Sesion.admin=administrador;
Sesion.admin.loadTaxis();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
the method I need to wait to finish to run it´s on the class Taxifirebase.java:
public static void loadTaxis(List<String> chapas){
for (String chapa :chapas) {
DatabaseReference taxiref=childRef.child(chapa);
taxiref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Taxi taxi=dataSnapshot.getValue(Taxi.class);
Sesion.taxis.add(taxi);
}
}
Thanks in advance.
If the flag is for you can use Log class.
If you need for the logic of program use a boolean and change to true when you need. Later you can check the value.

Categories

Resources