I'm currently building a to-do app on Android Studio. I'm facing an issue with my Firebase database. What I'm trying to do is, each user to have a unique id based on their google sign in, in order to see only their own data. Currently, on my app, everyone can see anyone's' tasks. On Firebase I'm using the Realtime Database, specifying it by one child of "Users" and another one of Task + a random number. Also, I've already added the google sign in button on the launch of my app.
Current Database:
enter image description here
Example of how my hierarchy wants to be:
enter image description here
According to your comments, to get only the Task objects the correspond to a particular user, please use the following lines of code:
String userId = "User-13294";
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference tasksRef = rootRef.child("Users").child(userId).child("Tasks");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot taskSnapshot : dataSnapshot.getChildren()) {
String title = taskSnapshot.child("title").getValue(String.class);
Log.d("TAG", title);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore potential errors!
}
};
tasksRef.addListenerForSingleValueEvent(valueEventListener);
Because User-13294 has only one Task, the result in the logcat will be only one title:
Swimming
Related
I am studying Android and Firebase by myself.
I'm have a problem with storing user information and creating login and user registration functions by linking Android and Firebase.
When saving user information in Firebase, is only one key possible? I want to save more keys.
I tried changing main key, but it's failed.
Sorry. I can't speak English. I'm using a translator now.
enter image description here
I saved user information like in the picture, but there was a problem during the production of the ID search function.
private FirebaseDatabase database = FirebaseDatabase.getInstance(); //파이어베이스 데이터베이스 연동
DatabaseReference databaseReference = database.getReference();
DatabaseReference conditionRef = databaseReference.child("User");
conditionRef.child(userID).child("userID").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String userid = snapshot.getValue().toString();
if(snapshot.exists()){
Toast.makeText(getApplicationContext(), "아이디: " + userid, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "등록되지 않은 회원입니다.", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
The code is as above.
However, because "conditionRef.child(userID)" does not have a userID value, the information cannot be retrieved from Firebase.
I have a root node named 'Posts'. Then each node inside Posts has a unique postID generated by push(). Now each post has several children. One such child is "saves" in which I have stored the userIDs of those users who have saved this particular post. What I want to do is that I want to create and display a list of all those posts which a particular user has saved.
This means that I have to write a code that will scroll through all posts in 'Posts' node, check for 'saves' child in each post,
if it exists, then check for userID of a particular user in 'saves',
if it exists, then that post should be added to a list called 'mySavedPosts'.
Please click here to see the structure of my 'Posts' node.
I have tried many different ways to achieve this but I am just getting an empty list or app crashes. I cannot post all the different ways that I have tried since that would make this question very lengthy and clumsy, but all my ways revolve somewhere around this approach:
FirebaseDatabase.getInstance().getReference()
.child("Posts")
.child("saves")
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
mySavedPosts.clear();
if (snapshot.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).exists()){
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
Post post = dataSnapshot.getValue(Post.class);
mySavedPosts.add(post);
}
}
Collections.reverse(mySavedPosts);
postAdapterSaves.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
I have also tried entering .child(post.getPostID()) after .child("Posts") but that generates a null Pointer Exception.
I have also tried entering .child(auth.getUid()) after .child("saves"), that didn't work too!
I have tried 10s of other modifications but none of them have worked.
According to your comment:
I just need to see if the auth.getUid() is there in the children of "saves".
To check if the UID of the authenticated user exists in the "saves" node, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference postsRef = rootRef.child("Posts");
Query query = postsRef.orderByChild("saves/" + uid).equalTo(true);
query.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot postSnapshot : task.getResult().getChildren()) {
Post post = postSnapshot.getValue(Post.class);
mySavedPosts.add(post);
}
Collections.reverse(mySavedPosts);
postAdapterSaves.notifyDataSetChanged();
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
So I am working on the memories Firebase app and there is a stage where the user can upload photos to his memory. Each photo has uniq name "ImgLink0","ImgLink1",etc..
The function I am working on is to delete a specific photo when I am pressing a long click, but I can't reach the image in Firebase.
I tried like below but I got stuck because I can't identify the image key:
mDatabase.child(userUID).child("Memories").child(memoryName).child("Images").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot imageSnapshot : dataSnapshot.getChildren()) {
String imagesKey = imageSnapshot.getKey();
String imagesValue = (String) imageSnapshot.getValue();
Log.e("Test","" + imagesKey + "" + imagesValue);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
And this is the data structure:
I tried using query too but with no success because I don't have the image key.
Thank you for any help :)
To delete a node from the database, you need to know the completely path to that node.
Assuming you do know the URL of the image to delete, but not the key (ImgLink1 or ImgLink2) that is stored under, you're going to have to use a query to look up that key.
Something like:
DatabaseReference ref = mDatabase.child(userUID).child("Memories").child(memoryName).child("Images");
Query query = ref.orderByValue().equalTo("URL of the image")
query..addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot imageSnapshot : dataSnapshot.getChildren()) {
imageSnapshot.getRef().removeValue();
}
}
...
Also see these related answer:
deleting specific post in database(by post node) but it deletes entire database_table
How can i remove all fields and values by using key value or a field key from firebase realtime database?
To remove the second URL for example, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference imageToDeleteRef = rootRef
.child(uid)
.child("Memories")
.child("TestMem")
.child("Images")
.child("ImgLink1");
imageToDeleteRef.removeValue().addOnCompleteListener(/* ... */);
So I have created a reference that points exactly to ImgLink1 node and then I called .removeValue() on reference in order to delete it. So there is no need to read the value in order to perform a delete operation.
If you want to read the URL, please use these lines:
imageToDeleteRef.addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
String url1 = task.getResult().child("ImgLink1").getValue(String.class);
Log.d("TAG", url1);
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
The result in the logcat will be:
https://firebasestorage.googleapis.com...
I want to reach projectImageUrl but the problem is in between Projects and project Image URL there is a random key for each project so that each project should have a unique name, So how can I reach to projectImageUrl?
How can I access to a node in Firebase who has a random key?
That's not actually random. As I see in your database schema, you are using as the key for the User object, the value of the UID which is concatenated with the date and time. Both date and time, are already apart of the User object. Adding them along with the UID is really not necessary because the UIDs are already unique. There is no need to add anything else to make it "more" unique. My recommendation is to only use the UID and nothing more. In that case, to get the URLs that exist under the projectImageUrl node, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference projectImageUrlRef = rootRef.child("Projects").child(uid).child("projectImageUrl");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String url = ds.getValue(String.class);
Log.d("TAG", url);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore potential errors!
}
};
projectImageUrlRef.addListenerForSingleValueEvent(valueEventListener);
The result in the logcat will be the URLs that exist under projectImageUrl node. If you need to keep the date and time, please change the projectImageUrlRef to:
DatabaseReference projectImageUrlRef = rootRef.child("Projects").child(uid + date + time).child("projectImageUrl");
Where that date should hold the value of "06-Oct-2020" and the time "16:37:9".
I use the firebase realtime database to store user information.
Here is a picture of the database:
screenshot of the database
For example, how can I get the value "nombre_dons" according to the connected user to display it in the application ? I use android studio in java.
Thank you in advance for your help
Those parent strings of the user data in Users node in your database look like the uids. If they indeed are, then all you need to do is to retrieve data from those uids for the particular user.
What I am saying looks something like this in code:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users");
FirebaseAuth mAuth = FirebaseAuth.getInstance();
ref.child(mAuth.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String data = dataSnapshot.child("nombre_dons").getValue(String.class);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "onCancelled", databaseError.toException());
}
});
One flaw I can see in your database image is that nombre_dons child in second user in your Users node has capital N, which would be a problem, because Firebase is case sensitive. I'd advise you to keep it same as others.
Assuming the keys inside 'Users' in your database are Firebase Authentication UserId(s), you can follow these steps-
1. Get UID of the current user.
2. Fetch data for the same.
Using Javascript -
var uid = firebase.auth().currentUser.uid;
firebase.database().ref('/Users/' + uid).once('value').then(function(snapshot){
var nombre_dons = snapshot.val().nombre_dons;
});