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!
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 get a specific user from the database but I can't, also I would like to check if there is already a node with the same name (uid). I don't want to get the whole list of users and then retrieve one from it because I don't think that's good for perfomance, my idea is to directly get the user from the database
I tried many ways but everything I try returns null, I can't get the values from dataSnapshot. I use an interface to make sure I execute the code after the reading is done
currentUser = FirebaseAuth.getInstance().getCurrentUser();
mUserReference = FirebaseDatabase.getInstance().getReference("users/"+currentUser.getUid());
mUserReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
user = dataSnapshot.getValue(User.class);
dataStatus.dataIsLoaded(user);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Here the interface
public interface DataStatus{
void dataIsLoaded(User user);
}
And when I try to get the user it shows NullPointerException
UserUtils userUtils = new UserUtils();
userUtils.getUser(new UserUtils.DataStatus() {
#Override
public void dataIsLoaded(User user) {
mUser = user;
}
});
User creation, when I call this method I do uid = currentUser.getUid()
public void createNewUser(String uid, String name, String email, DataStatus dataStatus) {
mUserReference = mDatabase.child("users").child(uid);
mUserReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
user = new User(name, email);
mDatabase.child("users").child(uid).setValue(user);
dataStatus.dataIsLoaded(user);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Here the rules
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
Here's how my data base is organized
SOLVED
The problem was a piece of code, which I didn't include here, that was trying to get access to the user outside the dataIsLoaded interface method, and as onDataChange is asynchronous the user hadn't been downloaded yet so it was conflicting with the code.
Welcome to SO community
Please use .child() method instead of cascading nodes with "/" as below
Also check if the value of the datasnapshot is not null using .exists() method
currentUser = FirebaseAuth.getInstance().getCurrentUser();
mUserReference = FirebaseDatabase.getInstance().getReference.child("users").child(currentUser.getUid());
mUserReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
user = dataSnapshot.getValue(User.class);
dataStatus.dataIsLoaded(user);
}
}
// rest of code
Feel free if you need further support
UPDATE
Please replace your listener with below
currentUser = FirebaseAuth.getInstance().getCurrentUser();
mUserReference = FirebaseDatabase.getInstance().getReference.child("users").child(currentUser.getUid());
Query query = FirebaseDatabase.getInstance().getReference.child("users").orderByKey()
.equalTo(currentUser.getUid());
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot singleSnapshot : dataSnapshot.getChildren()) { // dataSnapshot contains set of returned result of the query
User user = singleSnapshot.getValue(User.class);
if (user != null) {
dataStatus.dataIsLoaded(user);
}
}
}
}
Welcome to SO community.
When did you call your function to read the user content?
it might be an asynchronous problem.
To make sure, make a function where the user is the parameter and call it once you read something from the DB (onDataChange).
Plus, did you try to print out what is inside " user " when you read it? if it gives you null, the problem is within the path for sure. If so, use .child("users").child(currentUser.getUid())
I currently have a users collection in my Firebase real-time database that contains all my users and a collection that contains the name of books and the ratings(number of thumbs up and down). I am trying to make a application that will display book titles constantly(or the ones that are in my db) so that people can rate them, however I need to be able to check if a user has already viewed this book title or not(this is the part i need help with). Can someone help me with pulling the data from Firebase and comparing it to see if the user has viewed this book title or not. This is what my db setup looks like
Also if someone has a better way of doing this please explain!!!
First, change books_viewed into an array. Read this for arrays in Firebase Realtime Database
Now that it's an array, you can get that as a ArrayList<String> in your app.
public class User {
public ArrayList<String> booksViewed;
... // Other variables
}
Then just use the contains function to check if the book you need to find is in that list
DatabaseReference userRef = FirebaseDatabase.getInstance().getReference().child("Users").child("<UserID>")
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
String bookTitleYouAreChecking = "Twilight"
if (user.booksViewed.contains(bookTitleYouAreChecking)) {
// User has viewed
} else {
// User has not viewed
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// ...
}
})
To solve this, please use the following method that checks if a user had viewed a book or not:
private void checkBookTitle(String bookTitle) {
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = rootRef.child("Users").child(uid).child("books_viewed");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue().equals(bookTitle)) {
Log.d(TAG, "User has viewed this book");
} else {
Log.d(TAG, "User has not viewed this book");
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
};
ref.addListenerForSingleValueEvent(valueEventListener);
}
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) {
}
});
How Can I get ArrayList of Java Objects of all Childs from Firebase using updated firebase commands, currently I am using below approach but not able to get the list.
ValueEventListener postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get Post object and use the values to update the UI
if(dataSnapshot!=null){
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
UserDataClass post = postSnapshot.getValue(UserDataClass.class);
members.add(post);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
}
};
mDatabaseRef.addValueEventListener(postListener);
below is datasnapshot which is returning from firebase but I am not able to get the desired result out of it.
DataSnapshot { key = 12345, value = {Members={00000000={phoneNo=00000000, longitude=73.0703307, latitude=33.6396975, password=qwertyuiop, CName=00000000, admin=true, name=Anwar Kamal}, 03028084374={phoneNo=03028084374, longitude=73.0701292, latitude=33.6397129, password=qwerty, CName=00000000, admin=false, name=Nehal Khan}, 03028084516={phoneNo=03028084516, longitude=73.0702659, latitude=33.6397622, password=qwerty, CName=03035356317, admin=false, name=Jamal Khan}}} }
all i want is list of all members
and my java object is
public class UserDataClass {
public double latitude;
public double longitude;
public String Name="";
public String password="";
public String phoneNo="";
public String CircleName="";
public boolean isAdmin=false;
}
The ValueEventListener has another purpose.
You should use ChildEventListener and also dataSnapshop.getValue() to implement what you want, for example:
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
UserDataClass post = postSnapshot.getValue(UserDataClass.class);
members.add(post);
}
//...
Note:
You should use the listener with the current firebase_referance to the Users table. Hence you should replace
mDatabaseRef.addValueEventListener(postListener);
with
mDatabaseRef.child("Members").addChildEventListener(childEventListener);
notice that your full path of the Members table is colored and i couldn't figure the path.
You can find the whole documentation here
good luck