I am working on an application similar to tinder but to help users to find people to play a specific sport with.
I currently have the code searching the database for the gender of the users (that the user can be matched with). However each user in the database has a node that contains all of the sports the user can pick. If the user prefers a sport the value is saved as 'true' and if not, the value is saved as 'false'. The appropriate users are then shown on the app.
A screenshot of the database is shown below:
This is the code I have so far:
public void checkUserSex(){
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference userDb = usersDb.child(user.getUid());
userDb.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
if (dataSnapshot.child("sex"). getValue() != null){
userSex = dataSnapshot.child("sex").getValue().toString();
switch (userSex){
case "Male":
oppositeUserSex = "Female";
break;
case "Female":
oppositeUserSex = "Male";
break;
}
getOppositeSexUsers();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
public void getOppositeSexUsers(){
usersDb.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot.child("sex").getValue() != null) {
if (dataSnapshot.exists() && !dataSnapshot.child("connections").child("pass").hasChild(currentUId) && !dataSnapshot.child("connections").child("play").hasChild(currentUId) && dataSnapshot.child("sex").getValue().toString().equals(oppositeUserSex)) {
String profileImageUrl = "default";
if (!dataSnapshot.child("profileImageUrl").getValue().equals("default")) {
profileImageUrl = dataSnapshot.child("profileImageUrl").getValue().toString();
}
cards item = new cards(dataSnapshot.getKey(), dataSnapshot.child("name").getValue().toString(), profileImageUrl);
rowItems.add(item);
arrayAdapter.notifyDataSetChanged();
}
}
}
#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) {
}
});
}
How do I change it from matching gender to matching the selected sport?
Unfortunately, Firebase Realtime database does not allow a query based on multiple properties. To achieve what you want, you don't need to restructure your database entirely, you just need to change it a little bit. To solve this problem, you need to add a new node for each sport. Every time you add a new user which plays golf, add it also in its corresponding sport node. Your new node should look like this:
Firebase-root
|
--- golfPlayers
|
--- userId1 : true
|
--- userId2 : true
With this structure you can query your database to get only the users who are playing golf. This can be done by attaching a listener on golf node and iterate on the DataSnapshot object.
This practice is called denormalization and is a common practice when it comes to Firebase. For a better understanding, I recommend you see this video, Denormalization is normal with the Firebase Database.
Note, what you are trying to do and cannot be solved using Firebase Realtime database, can be solved using Cloud Firestore. Give it a try.
Related
How do i Check Check in Database with User Entered Phone Number?
And i Want Notice to the User If he already registered.
String _getUserEnteredPhoneNumber = pNumber.getEditText().getText().toString().trim();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("People");
Query checkUser = reference.orderByChild("uid").equalTo(_getUserEnteredPhoneNumber);
checkUser.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
pNumber.setError("Username Exists,Please Enter Another User Name");
} else {
updateData();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
If you want to query on the phone number, you need to specify that property in your call to orderByChild(). So:
Query checkUser = reference.orderByChild("phone").equalTo(_getUserEnteredPhoneNumber);
I highly recommend checking out the documentation on sorting and filtering data, which covers Firebase's query capabilities in more detail.
I'm trying to set up an order placing system.
Once the user is verified via email, it can create/update/delete order.
Order is saved into Firebase Real-time Database and users are saved in Authentication.
I would like to allow user to only see/edit orders that were placed by this specific user. Basically make use of UserUID from Authentication section.
public class FirebaseDatabaseHelper {
private FirebaseDatabase mDatabase;
private DatabaseReference mReferenceOrders;
private List<Order> orders = new ArrayList<>();
public interface DataStatus{
void DataIsLoaded(List<Order> orders, List<String> keys);
void DataIsInserted();
void DataIsUpdated();
void DataIsDeleted();
}
//Initialize Database object
public FirebaseDatabaseHelper() {
mDatabase = FirebaseDatabase.getInstance();
mReferenceOrders = ((FirebaseDatabase) mDatabase).getReference("order");
}
public void readOrders(final DataStatus dataStatus){
mReferenceOrders.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
orders.clear();
List<String> keys = new ArrayList<>();
for(DataSnapshot keyNode : dataSnapshot.getChildren()) {
keys.add(keyNode.getKey());
Order order = keyNode.getValue(Order.class);
orders.add(order);
}
dataStatus.DataIsLoaded(orders,keys);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public void addOrder(Order order, final DataStatus dataStatus) {
String key = mReferenceOrders.push().getKey();
mReferenceOrders.child(key).setValue(order).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
dataStatus.DataIsInserted();
}
});
}
// Update and Delete methods
public void updateOrder(String key, Order order, final DataStatus dataStatus){
mReferenceOrders.child(key).setValue(order).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
dataStatus.DataIsUpdated();
}
});
}
public void deleteOrder(String key, final DataStatus dataStatus){
mReferenceOrders.child(key).setValue(null).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
dataStatus.DataIsDeleted();
}
});
}
}
Here's what I was thinking:
When a user creates a new order then a UserUID is added to a database and nested inside 'order' so now each order can be assigned to a user that created it.
Now the next step would be to display this order to a user that created it but only if cust_id (in order) matches UserUID of a logged in user. Would that be a good approach?
Yes, it is a good approach, now you need to add to your Firebase Realtime Database now branch with your users data based on userUID, like this:
Thanks to this you will be able to connect your users with their orders data and besides you can save here more specific user data like "how many orders user create", "how many orders are active" etc.
I have added a user_id to an 'order' in the Firebase database so each order can be assigned to its user.
I got the parameter for user_id by fetching a UserUID from an Authentication section of Firebase when a new user is logged/signed in.
Screenshot of UserUID in Authentication section of Firebase
I got this value in my code by adding the following:
private FirebaseAuth mAuth;
order.setUser_id(mAuth.getCurrentUser().getUid());
Once I got the user_id assigned to each order I've created a following if statement which is implemented in my readOrders function which you can see in my original post above:
public void readOrders(final DataStatus dataStatus){
mReferenceOrders.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
orders.clear();
List<String> keys = new ArrayList<>();
for(DataSnapshot keyNode : dataSnapshot.getChildren()) {
keys.add(keyNode.getKey());
Order order = keyNode.getValue(Order.class);
**if (order.getUser_id().equals(mAuth.getUid())) {
Log.d("FirebaseDatabaseHelper", "match");
orders.add(order);
}else {
Log.d("FirebaseDatabaseHelper", "error");
}**
}
dataStatus.DataIsLoaded(orders,keys);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
So basically now when the new user logs in, there will be nothing to show because the user_id won't match with any of the user_id's inside Order database.
I'm not sure how efficient this method will be when more users/orders will be added so I'll have to do some testing.
Please advise if this is the best approach!
In my application I want to retrieve a single value from a particular id. The below screenshot is my database structure:
I want to retrieve the count of likes from database.
This is what I have tried:
public String getLikesCount(String USER_ID){
mref = FirebaseDatabase.getInstance().getReference("user").child(USER_ID);
return currentLike;
}
I don't know what to do after this to get likes count. Can anyone help me please?
do the following:
mref = FirebaseDatabase.getInstance().getReference("user").child(USER_ID).child("likes");
mref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String likes = dataSnapshot.getValue(String.class);
//do what you want with the likes
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
When the user logon with your google account for the first time in the app, I made this activity to create the user in the database. It's working, but are creating more than one user in the database, and I don't know why.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account);
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() == null) {
goLogInScreen();
} else {
final String userGoogleEmail = firebaseAuth.getCurrentUser().getEmail();
databaseUser.orderByChild("userEmail").equalTo(userGoogleEmail).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
//User already exists
} else {
//Can create new user
String id = databaseUser.push().getKey();
User user = new User(id, userGoogleEmail, null);
databaseUser.child(id).setValue(user);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
};
This is happening because your are using as an identifier the key generated by the push() method and not another identifier and this is actually creating the user again, even if exists in your database.
What i'm recomending you to do, is to change a little bit the logic of saving the data in your database. So in order to solve your problem, i recomand you using in stead of that key, the email address as an identifier, because is also unique. Your database should look like this:
Firebase-database
|
--- Users
|
--- jon#email,com
| |
| --- //data
|
--- jack#email,com
|
--- //data
As you probably see, i have saved the email addreees in the Firebase database using , (comma) and not . (dot).
name#email.com -> name#email,com
This is because Firebase does not allow symbols like . in the key name. So to store the values like this, the encoded email is required. To achieve this, i recomand you using the following methods:
String encodeUserEmail(String userEmail) {
return userEmail.replace(".", ",");
}
String decodeUserEmail(String userEmail) {
return userEmail.replace(",", ".");
}
To verify if a user exists, simply put the a listeenr on the Users node and use exists() method on the dataSnapshot object like this:
DatabaseReference usersRef = usersDatabaseReference.child(userEmail);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.exists()) {
//create user
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
usersRef.addListenerForSingleValueEvent(valueEventListener);
Hope this solves your problem.
I am writing an Android app and I am trying to retrieve an object of the class User.java by ID from its Firebase pertinent table. I would like to know how to get it from Java side, as long as I tried the examples stated in Firebase Official docs but none of them is working for me.
Taking this SO question as example, I want a method with the following interface:
public User readUser(String userId);
In other words, I want to execute:
readUser(-lnnROTBVv6FznK81k3n)
and retrieve the associated User object
Thanks
--------------------------------------------------------------EDIT--------------------------------------------------------------:
I managed to get the value with this code:
public void retrieveUser(final String email){
firebaseUsersRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot messageSnapshot: dataSnapshot.getChildren()) {
if(messageSnapshot.getKey().equals(Email.encodeID(email))){
retrievedUser = messageSnapshot.getValue(User.class);
break;
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) { }
});
}
Please not retrievedUser is a class attribute, thus a field. I am accessing that field from the code, but even I see it takes the value on the debugger, it is being null on the calling code.
Any hint? CanĀ“t I just return it in the method itself, so it would be?:
public User retrieveUser(final String email);
Thanks
so here is the soultion, I didn't put it in a method though.
final String uid = "your Uid here";
// Get a reference to users
Firebase ref = new Firebase(Constants.FIREBASE_URL_USERS);
// Attach an listener to read our users
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot user: snapshot.getChildren()) {
//this is all you need to get a specific user by Uid
if (user.getKey().equals(uid)){
wantedUser = user.getValue(User.class);
}
//**********************************************
}
Log.i(TAG, "onDataChange: " + wantedUser.getName());
}
#Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});