I'm developing an app. The app must able to show the latest 10 registered user detail from real-time database. That is, It removes any user older than latest 10 users. Is there any way I can do this? Right now my app is able to access the user details stored in realtime firebase.
Thanks in advance.
That sounds totally feasible. An incredibly simple way is to retrieve 11 users in your app, and then just remove the last one.
ref.orderByChild("descending_timestamp").limitToFirst(11).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int userCount = 0;
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
if (userCount++ > 10) {
userSnapshot.getRef().remove();
} else {
// TODO: show the user in your app
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "load users", databaseError.toException());
}
});
You'll note that I order on descending_timestamp, which is a property that you must add to the data and that allows you to sort the users in reverse chronological order. For more on this, see Firebase Data Desc Sorting in Android
Related
I want to write the user's data to the database only when it first logs on. I don't want it to be written over and over. I wrote a method for this, but I had a problem because there was more than one value in the for loop. How can I solve this problem?
public void writeFirebase() {
final Users users = new Users();
final List<String> arrayList = new ArrayList<>();
myRef.child("Users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
arrayList.add(ds.getKey());
}
if (arrayList.size() > 0){
for (String cur : arrayList) {
if (cur.matches(mUser.getUid())) {
} else {
Log.e("preee",""+cur);
if (mUser.getPhotoUrl() != null) {
users.setUserProfilPic(mUser.getPhotoUrl().toString());
}
if (mUser.getDisplayName() != null) {
users.setUserName(mUser.getDisplayName());
}
users.setUserId(mUser.getUid());
users.setUserPremium(false);
users.setUserPremiumDate("free");
users.setUserEmail(mUser.getEmail());
myRef.child("Users").child(mUser.getUid()).setValue(users);
}
}
}else {
users.setUserId(mUser.getUid());
users.setUserPremium(false);
users.setUserEmail(mUser.getEmail());
users.setUserName(mUser.getDisplayName());
users.setUserProfilPic(mUser.getPhotoUrl().toString());
users.setUserPremiumDate("free");
myRef.child("Users").child(mUser.getUid()).setValue(users);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
if you want to write your user data in database once and prevent from writing again you just need to check if that user is already in your database. (in this answer i consider your concern is your user existence, it can be anything else for example maybe your don't want to let user update his email address if he already entered once. so you just check that if user has entered email before or not.)
for my example(user existence) i provide some links which help you check if user is already in your database.
How to search if a username exist in the given firebase database?
How to search if a username exist in the given firebase database?
How to check if a value exists in firebase database - android
just seach and find if your user is already in your database or not. check this ifs before any operation. if he was't you will allow him to continue.
I'm using firebase with android to create a simple chat app. When the user chooses another user to chat with I want to check whether they've chatted together or not.
In onCreate() method I'm retrieving all the rooms that the current user used before, and I'm putting them in an arraylist called MyChatRooms<>.
Then I want to check each room to see the users of the room.
The problem is that the loop I'm using to iterate through rooms name is finishing before I'm able to retrieve any data from the database.
I know there's similar questions to mine, but none of the answers worked for me.
Here's the related code:
if (!MYChatRooms.isEmpty()) {
for (j = 0; j < MYChatRooms.size(); j++) {
roomref.child(MYChatRooms.get(j)).child("First User").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot1) {
if (!dataSnapshot1.getValue().toString().equals(Username) && dataSnapshot1.getValue().toString().equals(NUsername)) {
Users += dataSnapshot1.getValue().toString() + ",,, ";
} else if (dataSnapshot1.getValue().toString().equals(Username)) {
roomref.child(MYChatRooms.get(j)).child("Second User").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot2) {
if (dataSnapshot2.getValue().toString().equals(NUsername)) {
Users += dataSnapshot2.getValue().toString() + ",,, ";
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
I would suggest that you change the structure of your data. Imagine if a user has 100 chats that means your have to query 200 times to Firebase that of course does not look feasible.
What i would suggest is that your add a recentChat list in every user and whenever a user starts a new chat with someone you add the id of the second user to that list. That way you can track easily with whom the current user has interacted with.
It structure in firebase can look something like this:
User
recentChats
id of the other user
Try to change you database hierarchy or use firestore instead of real time database
Please check the following topic: https://firebase.google.com/docs/database/usage/optimize?
In my case, I had added and index column and limited the query in Firebase Rules.
My application was token generation mobile application. Iam using Firebase to store my data. The token were generated with the help of childrens count in firebase database. The problem I faced was if two users book their appointment at same time then both the users get same token number. For example, the number of childrens in firebase was 5. If the users A and B book their appointment then both the users get the token number 6. But the other user C book the appointment(after A and B) get the correct token number 8.
My code:
int ct=1;
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
++ct;
Log.d("log", "onDataChange: " + dataSnapshot1.child("Appointment").child("artistName").getValue());
}
}
The variable ct represents the token number.
What was the solution to solve the above problem?
The token should not be generated based on children count under a node. It will not serve the purpose of identifying a token uniquely in your database.
As far as I could understand your problem, you want to provide a token to the users of your application for an automated appointments to some artists. In this case, I would like to suggest you to take another table in your firebase database which will store all the tokens. Tag the token number along with the artist.
So the final table structure will be something like this.
Appointment
-- Artists
-- TokenNumber
Token
--TokenNumber
If you are familiar with the relational database, you might consider thinking of your token number as a foreign key of another table which is incremented automatically each time a token is assigned to some appointment.
Hope that helps!
Update
Based on the comment, I have found a nice answer in stackoverflow regarding this. Please have a look at the answer on how to increment a value in Firebase. The key idea is to setting the value from client side with a transactional mode. I am sharing the sample code from the answer referred.
public void incrementCounter() {
firebase.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(final MutableData currentData) {
if (currentData.getValue() == null) {
currentData.setValue(1);
} else {
currentData.setValue((Long) currentData.getValue() + 1);
}
return Transaction.success(currentData);
}
#Override
public void onComplete(FirebaseError firebaseError, boolean committed, DataSnapshot currentData) {
if (firebaseError != null) {
Log.d("Firebase counter increment failed.");
} else {
Log.d("Firebase counter increment succeeded.");
}
}
});
}
In my Application I am using Firebase to retrieve the mobilnumbers of the Users. Therefore I use this code:
databaseUsers.orderByChild("uid").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
users.clear();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
User contactlists = postSnapshot.getValue(User.class);
users.add(contactlists);
}
ContactList contactAdapter = new ContactList(ContactListActivity.this, users);
listViewContacts.setAdapter(contactAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Now I have the following question: If the number of users is high, is there a possibility to send only the mobilnumbers of your Phonebook maybe in a list? Otherwise I think the traffic to Firebase might be not so efficient?!
The other opportunity would be to send each number individually but this might be quite complex if the user has many contacts.
At the moment I get all numbers from the server but I need to filter for the right contacts AND I need to display the names of the contact.
What is the best solution to use Firebase as efficient as possible and also get the names of the contacts?
Thank you in advance!
You'll have to:
Loop through the local phone book to find the phone number of each contact.
Execute a query to Firebase for each number.
Add the resulting contact (if any) to the list/adapter and update the view.
So say you've done step 1 and have a list of phone numbers. You'd then loop through those and for each:
for (String phonenumber: phonenumbers) {
Query query = databaseUsers.orderByChild("phonenumber").equalTo(phonenumber);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User contactlists = postSnapshot.getValue(User.class);
users.add(contactlists);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore erors
}
});
}
The call to notifyDataSetChanged() ensures that the adapter know that it needs to update the view.
While the code gets a bit convoluted, it is not as slow as you may initially fear, since Firebase pipelines the requests over a single connection. The performance will mostly depend on the number of users you have in the database, but up to a few hundreds of thousands this should be fine.
I am working on the app where I need to pull specific value from the firebase. For this case I need to pull "Score" where "uID" equals current User id. What would be a best way to do so.
Thank you for any help.
Firebase will always return full nodes. So you cannot just return the score for a user. But you can return the common node that both the score and user are under (the one starting with -K...) by using a Firebase query:
DatabaseReference leadersRef = FirebaseDatabase.getInstance().getReference("Leaders");
Query query = leadersRef.orderByChild("uID").equalTo("vUdnKx...");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot child: snapshot.getChildren()) {
System.out.println(child.getKey()+": "+child.child("Score").getValue(Long.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "onCancelled", databaseError.toException());
// ...
}
})
Note that the code loops over the snapshot in the result. That is because a query will potentially have multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
For more reading see the Firebase documentation on handling lists and sorting and filtering data.