Social network - Follow functionality using firebase database - android

I am building a social network like Instagram. I have worked on many social networks before, using mySQL. I am new to firebase server.
I want to search users via name and want to show the follow/following button on the list view. But I am little confused to run android firebase queries in a standard format. I do not want to run unnecessary loops. Below is my database structure for the follow table.
Node name is follow and follower_id refers to the user who is following the user and user who gets followed is referred as followed_id.
How to write a simple query using android firebase to show all the users with the name starting (e.g "an") and with the status that I am already following him/her or not.
FYI: I am not using firebase rest API's.

How to write a simple query using android firebase to show all the users with the name starting (e.g "an") and with the status that I am already following him/her or not.
I think you can't do it in a single query.
You could try to do it with nested queries, something like this:
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
// Retrieve the userId
User user = dataSnapshot.getValue(User.class);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot usersFollowedDataSnapshot) {
for ( DataSnapshot userFollowedDataSnapshot : usersFollowedDataSnapshot.getChildren() ) {
// Retrieve the follower structure
Follow follow = userFollowedDataSnapshot.getValue(Follow.class);
if ( myUserId == follow.getFollowerId() ) {
// This is a user that I'm following and which name starts with "am"
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
Query secondQuery = mFirebaseDatabaseReference.child("follow").orderByChild("followedId").equalTo(user.getId());
secondQuery.addListenerForSingleValueEvent(valueEventListener);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
Query firstQuery = mFirebaseDatabaseReference.child("users").orderByChild("name").startAt("am").endAt("am\uf8ff");
firstQuery.addChildEventListener(childEventListener);
I know it's not very straightforward and looks disapponting. It could be also slow, but it worth trying.
Alternatively, you should consider to structure your database in a way to simplify the firebase queries.
See more on firebase queries for example here and here.

Related

Retrieve multiple datab by synchronization from Firebase Android

I am trying send my contacts to firebase one by one and checking if the user is present or not but due to the asynchronous behavior of firebase some information is showing twice.
I want to synchronize this method like this:
loop send one number to firebase, firebase response, save, and continue
for (int i=0 ; i< list.size();i++) {
Check_Contact(list.get(i));
}
public void Check_Contact(String number)
{
DatabaseReference myRef = database.getReference("user").child(number);
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
}
else {
UserProfile row = dataSnapshot.getValue(UserProfile.class);
ls.add(row);
Adapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Can somebody tell me how to synchronize this method?
Firebase Structure
output coming
It is not the firebase async behaviour. You may have duplicate contents in your database. Please check ur database and update a screenshot of your database in your question.
It will be more helpful to understand your question.

Android - Firebase searching with filtering

I'm developing an app that will help the user to search the books and download them which have been uploaded by other users as a form of the post.
In order to download the books first, the user should search them owing to attribute such as Title.
The posts which meet the requirement of the user should be displayed in the firebase-UI recyclerview.
This is my Firebase data structure:
I want the sample code that will create a Query which returns Id of convenient Posts such as ImgBRr2YFYfAu1WwENS1Ucj6jz13_1514813350760.
Please help me to solve the problem, any suggestions and ideas will be welcomed
Here is what you can do,
For search by language and then filter by title & author
public void search(String languangeSearchString, String title, String author){
FirebaseDatabase.getInstance().getReference().child("Posts").equalTo("language").startAt(languangeSearchString).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String id = dataSnapshot.getKey();
if(dataSnapshot.child("title").exists() && dataSnapshot.child("author").exists()){
if(dataSnapshot.child("title").getValue(String.class).equals(title) && dataSnapshot.child("author").getValue(String.class).equals(author)){
//Here are the results
}
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
To perform searching on firebase-database, we commonly use orderBy(). Like
firebaseDatabase.getReference("Posts").child("postId")
.orderBy("authorId")
But it can't possible to use multiple orderBy() like,
firebaseDatabase.getReference("Posts").child("postId")
.orderBy("authorId")
.orderBy("title") // this will throw an error
.orderBy("language")
So you have to perform searching only on one child-node.
For more info check this Query based on multiple where clauses in Firebase

Proper way of handling messages in chat

I have recently added a chat feature to my app.
I am storing the messages and their timestamps in Firebase database.
I am trying to figure out a way of displaying (in the current chat room) only the last (let's say) 60 messages. This would mean retrieving only the last 60 items of the current conversation from Firebase using limitToLast().
Furthermore I would like to add a Load more button that would appear only when the 60 messages limit has been reached by swiping up and it should load another 60.
Is there a proper way of handling the message archive as I stated above?
Using the code below I actually retrieve the whole specific message archive. I find this ineffective when the specific chat archive has thousands of messages.
mChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
mMessageAdapter.add(chatMessage);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
mDatabaseReference.child("chat_messages").child(chatId).addChildEventListener(mChildEventListener);
To achieve this, I recomand you using the following logic:
pageEndOffset = 0;
pageLimit = 60;
pageEndOffset += pageLimit;
Query query = mDatabaseReference.child("chat_messages")
.orderByChild("chatId").limitToFirst(pageLimit)
.startAt(pageEndOffset);
query.addValueEventListener(YourActivity.this);
Hope it helps.

Read Firebase Data Once With ValueEventListener

Within my app I often have the need to read data once. I originally started by using the addListenerForSingleValueEvent() method for this, however I ran into problems using this method as it does not work as I wanted when offline capabilities are enabled (see here the issue: Firebase Offline Capabilities and addListenerForSingleValueEvent)
In the question above it is mentioned that a workaround is to use the addValueEventListener() method, however I do not fully understand how to do this (particularly how to remove the ValueEventListener as soon I am finished grabbing the data I need).
Take this method which I created in a standalone class to query the Users node on Firebase where I store the users FCM Token. It seems to have an issue of not returning the latest token from the server everytime.
public class SendFCMMessage {
String userToken;
String currentUser;
String userName;
ValueEventListener userListener;
public void sendMessage(final String contactNumber) {
final DatabaseReference ref = FirebaseDatabase.getInstance().getReferenceFromUrl(link).child("Users").child(contactNumber);
userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
userToken = user.getToken();
// Send FCM Message after getting user token and then remove event listener
ref.removeEventListener(userListener);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("TAG", "Something terrible went wrong: " + databaseError);
}
};
ref.addValueEventListener(userListener);
}
}
If I remove the line
ref.removeEventListener(userListener);
Then this code works fine, however I would like to know how I could remove the ValueEventListener as soon as I receive the data I need?
Thanks,
R
ValueEventListener vel; //Declared Global
Listen your DatabaseReference like this;
vel = yourDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChanged(DataSnapshot dataSnapShot) {
//Do your stuff here. I suggest you create another method for this if you don't want a problem with inner class.
//For example, workDataSnapshot(DataSnapshot dataSnapShot) <-- Work here
yourDatabaseReference.removeEventListener(vel);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Hope it helps you.

Update recyclerview item ui in client to indicate that Firebase Database on server got updated

I'm building a chat app using Firebase Realtime Database. I want to implement the functionality like WhatsApp, where the user can send the message without internet (Add the message object on RecyclerView) but will have the clock icon (To show that the message was not sent yet).
When the Firebase Database receives the message (The user device connects to the internet and Firebase sends the message), I want to update the added element on the recyclerview(change the clock icon for a positive icon).
What have I tried? I have that
mFirebaseDatabaseReference = FirebaseDatabase.getInstance().getReference();
mFirebaseAdapter = new ChatFirebaseAdapter(mFirebaseDatabaseReference.child("chat_id"), user.getId());
recyclerChat.setLayoutManager(mLinearLayoutManager);
recyclerChat.setAdapter(mFirebaseAdapter);
My adapter extends FirebaseRecyclerAdapter from firebase-ui-database
I tried to add a addChildEventListener on my DatabaseReference where I get a dataSnapshot of the new element, but I don't know how to get the right position on recyclerview.
mFirebaseDatabaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
UPDATE RECYCLERVIEW ITEM
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I added an onCompletionListener when I add a new message, but I don't know how get the right position again.
mFirebaseDatabaseReference.push().setValue(message, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
UPDATE RECYCLERVIEW ITEM
}
}
});
Does someone have an idea why I cant accomplish that? Thanks. I search a lot before asked, but I didn't find the right answer.
The solution to your problem lies in adding a delivered boolean which can be set to true and once you receive successful push id from your code in onCompletionListener, then all you need to do is set this boolean to that particular push id.
Now on your android client in your firebase ui you can check if this boolean is set to true and change the state of recycler view items accordingly. This solution will work because firebase database is real-time.
//setting boolean onComplete
mFirebaseDatabaseReference.push().setValue(message, new DatabaseReference.CompletionListener() { #Override public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) { if (databaseError == null) { databaseReference.child("delivered").setValue(true); } } });
For chat apps like whatsapp, messenger etc you would take another messaging route if not using firebase as backened. Which I am not discussing here as it is out of scope of asked question.

Categories

Resources