How to delete a certain data in the Firebase Database? - android

I'm developing a social networking app, where users can follow other users and like their posts, comments ...
Whenever some user follows someone, it shows in a notification fragment in the other user account to inform him that he has a new follower.
The problem is that I couldn't remove the notification when the user hits unfollow. Here is what I have tried:
if ( holder.btn_follow.getText().toString().equals("follow"))
{
addNotifications(user.getId());
}
else{
FirebaseDatabase.getInstance().getReference("Notifications").child(user.getId()).removeValue();
}
and here is how I added notification:
private void addNotifications(String userid)
{
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Notifications").child(userid);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("userid", firebaseUser.getUid());
hashMap.put("text"," started following you");
hashMap.put("postid","");
hashMap.put("ispost",false);
reference.push().setValue(hashMap);
}
the problem with my code is that whenever the user unfollows someone, all the notifications from that user are deleted including his likes and comments. all I want is to delete "started following you".
Here is how it looks in the Firebase database.

Use Firebase Query refers to Firebase Docs, it will be something like this
Query queryRef = mReference.child("Notifications").child(userId).orderByChild("text").equalTo("start following you");
queryRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot snapshot, String previousChild) {
// snapshot.getRef().setValue(null);
snapshot.getRef().remove();
}
});

Related

How can we delete firebase user if he doesn't verify email?

I want to delete user from firebase authentication and also want to delete data from real-time database if the user doesn't verify email address with in 1 hours. Deleting a user is easy but if doesn't verify in 1 hour then how could I do this? The problem is that firebase is server less.
Write and deploy a scheduled function that periodically:
Queries your database for users who have not verified (you will need a child to record that).
Delete the database record and also delete the user account.
You will need to use the Firebase Admin SDK for both of these steps.
It's so easy! just create a real-time database of the unverified user database. and when the user signup the time will be also registered in the database. So when the apps start it check the unverified users and there you write the if-else statement if the difference between time is greater than 1hour the user will be deleted.
It's so simple as I said :)
Run firebaseAuth.getCurrentUser().isEmailVerified() function inside signInWithEmailAndPassword function to see if user is verified or not. if user is verfied then only create users database otherwise give an exception and break the function, it won't save unverified users data.
firebaseAuth.signInWithEmailAndPassword(Email,Pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
if (firebaseAuth.getCurrentUser().isEmailVerified()){
FirebaseUser user = firebaseAuth.getCurrentUser();
Uid = user.getUid();
databaseReference = FirebaseDatabase.getInstance().getReference().child("Users");
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (!snapshot.hasChild(Uid)){
databaseReference = FirebaseDatabase.getInstance().getReference().child("Users").child(Uid);
HashMap<String,String> userMap = new HashMap<>();
userMap.put("Name","default");
userMap.put("email",Email);
databaseReference.setValue(userMap).addOnCompleteListener(new OnCompleteListener<Void>() {
//call your function here when user sign in first time after email verification
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
//call your function when user already registered and verified
//and already saved his information to database
}else{
//show your exception here
}
}else{
//show your exception here
}
}
});

Getting info of user off firebase Android

I'm trying to create an app on Android that stores user contact info.
When the user creates a "contact card" to send to another user, I'd like it to display things I stored when registering the user, name, year, number etc.
When I push, firebase creates a unique key, and when I create a FirebaseUser it creates a uid. for ease, I save the uid as part of the user structure.
I'm now attempting to access that user using the uid, unfortunately the uid is not the key.
So, I'm trying to query.
I create a Firebaseuser
currentUser = firebaseAuth.getCurrentUser.getUid.
then I try to query by
DatabaseReference ref = firebase.getinstance().getReference("user);
ref.orderByChild("Uid").equalto(currentUser.getUid());
Is this correct? after I try to add a single valuelistener to obtain the actual values inside this user. Unfortunately this crashes. Can someone point me in the right direction?
You can use the user uid as the key to save the user info like this:
private DatabaseReference mDatabase;
// ...
mDatabase = FirebaseDatabase.getInstance().getReference();
User user = new User(name, email);
mDatabase.child("users").child(userUid).setValue(user);
Then you can get the user info like this
ValueEventListener userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get User object and use the values to update the UI
User user= dataSnapshot.getValue(User.class);
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting User failed, log a message
Log.w(TAG, "loadUser:onCancelled", databaseError.toException());
// ...
}
};
mDatabase.child("users").child(userUid).addValueEventListener(userListener);
If this doesn't work, write the error log on the OP please ;)

How to know which user is trying to Sign-in?

Users are created using Email and Password. This is how I do the Sign-up:
mSignup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mEmailStr = removeSpaces(mEmail.getText().toString());
mPasswordStr = mPassword.getText().toString();
mUsernameStr = mUsername.getText().toString();
mIsSgl = mSglCheckBox.isChecked();
mUsernameStr=mUsername.getText().toString();
final User mUser = new User();
mUser.setEmail(mEmailStr);
mUser.setPassword(mPasswordStr);
mUser.setIsSgl(mIsSgl);
mUser.setStudyGroupName(mStudyGroupName);
mUser.setUsername(mUsernameStr);
FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(Task<AuthResult> task) {
if (task.isSuccessful()) {
Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();
generateUser(mUser);
startActivity(new Intent(getActivity(), MainActivity.class));
} else {
Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
}
}
});
}
});
This is how I push the data into database:
public void generateUser(User user)
{
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference users;
if(user.getIsSgl())
{
users = database.getReference(user.getStudyGroupName()).child("SGL");
}
else
{
users = database.getReference(user.getStudyGroupName()).child("Student");
}
users.push().setValue(user);
}
This is how I Sign-in:
mSignin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mEmailStr = SignupActivityFragment.removeSpaces(mEmail.getText().toString());
mPasswordStr = mPassword.getText().toString();
mAuth.signInWithEmailAndPassword(mEmailStr, mPasswordStr).addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(Task<AuthResult> task) {
if (task.isSuccessful()){
FirebaseDatabase database = FirebaseDatabase.getInstance();
// thats not worked for me
database.getReference("StudyGroups").child("Student").orderByChild("email").equalTo(mEmailStr).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapShot : dataSnapshot.getChildren()) {
userKey = childSnapShot.getKey();
}
Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
Log.v("himaAbousalem",userKey);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Toast.makeText(getActivity(), "Sucsses ", Toast.LENGTH_SHORT).show();
startActivity (new Intent(getActivity(),Controller.class));
}else {
Toast.makeText(getActivity(), "not sucsses", Toast.LENGTH_SHORT).show();
}
}
});
}
});
I want to query the database so that when a user signs-in by Email and password, it returns all the data of that user from the database.
How can I make the key of userId in Auth equal to the userId in database and how do I use that feature?
tl;dr - In this case, store each user using their associated uid generated by Fireabase Auth instead of using a push ID.
In your situation the challenge with using a push ID to store info specific to each user is that when a user signs in you don't know the push ID you used when you first stored their info. To find a user each time they sign in you would have to search through every user in your database until you find a matching email/password to retrieve their correct profile information - the more users you have, the longer it would take to do the search. One alternative, which would probably be faster, is to use Firebase Authentication to create users and the Firebase Database to store any user specific information.
When you create a new user using Firebase Authentication it will assign a unique user id to the user that will be the same throughout the lifetime of the user. You then use the unique user id generated by Firebase Auth instead of a push ID to store user info in the database. The next time a user signs in you get the user's uid from Firebase Auth and use it to query the database to get that user's information.
Check the guide for how to create a password-based user and how to sign a user in using Firebase Auth: Create a password-based account
In order to use the unique uid generated by Firebase Auth I suggest a few changes to your code.
Update database structure
I suggest you update your database structure by adding a new location (maybe "allUsers") for use when you create/sign in users. Right now it looks like your are breaking up students into groups. If you need to keep this structure, for reasons beyond authentication, you can use it along with my suggestion. The reason for a single location which stores all users is that you need a definite location to query when a user signs in. When using Firebase Auth, without a single location which stores all users there is no way to tell what group a user belongs to when they first sign in. You would have to check every group in order to find a match and that may take a long time. Having a location which stores all users solves that problem. Also, the query for retrieving user information from that single location is much simpler. If you do need to keep a user's information in multiple places just be sure to update their information in both places if any changes occur.
Create a class variable used to distinguish between create user and sign in existing user.
If you use the same Activity to create a new user and sign in an existing user then create a boolean variable to make a distinction between when a new user is being created and when an existing user is signing in. It will be used later in the AuthStateListener. If you handle user creation in a separate activity from general sign in then you shouldn't need this variable because each activity would have a separate AuthStateListener.
boolean mIsNewUser = false;
Move the call to generateUser() from the create user completion listener to an AuthStateListener. Also move your database query from the sign in completion listener to the AuthStateLisener
Whenever you create a user successfully they will automatically be signed in too. So, if you move your call to generateUser() from the createUserWithEmailAndPassword OnCompleteListener to your AuthStateListener you can get access to the created user's uid. When signing an existing user move your database query to the AuthStateListener as well, again so we can access the user's uid. I'm also going to create a helper method for the database query called getExistingUserInfo. As an FYI, the onComplete() callback in the OnCompleteListeners for creating and signing in users gives you access to an AuthResult which according to the API has a method for returning the current user but the documentation says to access user information in the AuthStateListener.
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
if(mIsNewUser){
//call to generate user using Uid instead of pushID
generateUser(mUser, user.getUid());
} else{
getExistingUserInfo(user.getUid());
}
startActivity(new Intent(getActivity(), MainActivity.class));
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
// ...
}
}
#Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
#Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
Update your generateUser() helper method to use the uid instead of a push ID:
I'm going to assume you want to keep you existing database structure and add the single location for all users as suggested. Based on this I've made a couple of changes to the write operation you were using in generateUser(). Mainly, instead of using setValue() to write to the database I'm using updateChildren(). By using updateChildren() we can take advantage of Firebase's ability to do atomic updates. This will allow us to write to the appropriate student group location and the location storing all users simultaneously. By taking this approach if the write operation to either location fails neither location will be updated. This way you can be certain if a student is added to a group they will also be listed in the allUsers location.
private void generateUser(User user, String uid)
{
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
String userType;
String allusers = "allUsers/" + uid;
Map<String, Object> newUserUpdate = new HashMap<>();
if (user.getUsername() != null) {
if (user.isSgl()) {
userType = user.getStudyGroupName() + "/" + "SGL" + "/" + uid;
} else {
userType = user.getStudyGroupName() + "/" + "Student" + "/" + uid;
}
newUserUpdate.put(userType, user.serialize());
newUserUpdate.put(allusers, user.serialize());
database.updateChildren(newUserUpdate);
}
}
Update database query to use new location which stores all users
As I mentioned above, by creating a single location for all users you can reduce the complexity of the query used to find a user's info when they sign in. Again, if you need to store users by group you can keep that but be sure to update both locations if a users info changes.
public void getExistingUserInfo(String uid){
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference("allUsers").child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//get user data from dataSnapshot
Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
Log.v("himaAbousalem",userKey);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Set the variable used to distinguish between existing user sign in and new user creation in the create user completion listener
FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(Task<AuthResult> task) {
if (task.isSuccessful()) {
//set boolean used in the AuthListener
mIsNewUser = true;
Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
}
}
});

How to Handle Offline Transactions in Firebase Realtime Database?

I have an addValueEventListener which listens to any value changes in Firebase Realtime Database. In online mode, everything is working fine.
But in offline mode, device is offline and my Web Server has done multiple transactions on Firebase Realtime Database on same value for which I put the listener from Android. After the device comes online, it will only listen for the last transaction and skipping the other transactions done in between.
PFB reference link. PFB code which i have done so far:
FirebaseDatabase.getInstance().setPersistenceEnabled(false);
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference myRef = firebaseDatabase.getReference("mykey");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
HashMap<String, Object> key_Value = (HashMap<String, Object>) dataSnapshot.getValue();
for (String key : key_Value.keySet()) {
System.out.println("firebase key is "+key);
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w("feroz ", "Failed to read value.", error.toException());
}
});
}
The Firebase Realtime Database stores information came back from an inquiry for use when disconnected. For questions developed while disconnected, the Firebase Realtime Database keeps on working for already stacked information. On the off chance that the asked for information hasn't stacked, the Firebase Realtime Database loads information from the nearby reserve. When we return online our information will stack and mirror the inquiry.
For instance, here we have a bit of code in our application that questions for the last four things in our Firebase Realtime Database of scores
DatabaseReference scoresRef = FirebaseDatabase.getInstance().getReference("scores");
scoresRef.orderByValue().limitToLast(4).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot snapshot, String previousChild) {
System.out.println("The " + snapshot.getKey() + " dinosaur's score is " + snapshot.getValue());
}
});

Android firebase chat app getting user data has delay

I'm making a Android chatting app with firebase.
When Framgment is creating a view, I try to get user lisst,
But it has delay like 4~5 sec. Is there faster way to get data immediately with firebase?
Firebase firebase = new Firebase(AppDefine.FIREBASE_URL).child("friendlist-"+ac.getUserId());
firebase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
HashMap<String,String> map = (HashMap) dataSnapshot.getValue();
mFriends.add(new ChatUserInfo(map.get("id"),map.get("name")));
mAdapter.notifyDataSetChanged();
}
}

Categories

Resources