I am working on an application where anyone can list their products. I am storing data in Firebase Firestore in nested collection Now I want to retrieve that data and show that on my home screen. Now the data is showing but the problem is that it is showing only when I am login in with that same number through that I list that data into Firebase but when I try to log in with another number the data doesn't show. I want that to show to everyone who logged in to the app. Basically My app is just like OLX where anyone can list anything which shows to everyone.
MY CODE TO RETRIEVE THE DATA
//CODE TO GET CURRENT ID OR USER
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
//CODE TO GET THE DATA FROM FIREBASE
DocumentReference uidRef = firebaseFirestore.collection("listing_details").document(uid);
CollectionReference roomDetailsRef = uidRef.collection("room_details");
String doc_id = roomDetailsRef.document().getId();
roomDetailsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
if (document != null) {
RoomsDetails obj = document.toObject(RoomsDetails.class);
roomsDetails.add(obj);
}
}
roomsAdapter.notifyDataSetChanged();
} else {
Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
}
}
});
You have .document(uid) in your path where UID is User ID of user currently logged in. When you use another phone number, that's a different user.
If you want to fetch room_details documents from all listing_details documents then you can use Collection Group queries like this:
db.collectionGroup("room_details").get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
// ... iterate over all docs and render
}
});
Related
hey I try to check if the phone number that the user is insert is exist in my firebase auth
(LoginActivity)
I try this way
String phoneNumber = "+1234567890";
mAuth.fetchSignInMethodsForEmail(phoneNumber)
.addOnCompleteListener(new OnCompleteListener<SignInMethodQueryResult>() {
#Override
public void onComplete(#NonNull Task<SignInMethodQueryResult> task) {
if (task.isSuccessful()) {
SignInMethodQueryResult result = task.getResult();
List<String> signInMethods = result.getSignInMethods();
if (signInMethods.contains("phone")) {
// Phone number is already in use in Firebase Auth
} else {
// Phone number is not in use in Firebase Auth
}
} else {
// An error occurred
}
}
});
and when it comes to this function the debugger jump for it and don't doing anything
.addOnCompleteListener(new OnCompleteListener() {
I try with firebase SDK admin and it also doesn't work
can anyone know how to solve this?
There are three ways in which you can solve this problem. Two options are on the client, using Java code, and another one using Admin SDK.
Solution 1
When a user signs in for the first time into your app, then save user data in Firestore using a schema that looks like this:
db
|
--- users (collection)
|
--- $uid (document)
|
--- phoneNumber: "+1234567890"
To check if a user with the +1234567890 already exists, then you have to perform a query that looks like this in Java:
FirebaseFirestore db = FirebaseFirestore.getInstance();
Query queryPhoneNumber = db.collection("users").whereEqualTo("phoneNumber", "+1234567890");
queryPhoneNumber.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
if (document.exists()) {
Log.d(TAG, "User already exists.");
} else {
Log.d(TAG, "User doesn't exist.");
}
}
} else {
Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
}
}
});
Solution 2
Another more elegant and easy solution would be to use Query#count() method:
queryPhoneNumber.count();
If the result is > 0 then it means that the user already exists, otherwise it doesn't exist.
Solution 3
The last solution would be to use a Callable Cloud Function that can be called from your app. Because we use the Admin SDK in Cloud Functions you can call the getUserByPhoneNumber() method. In code it will look like this:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.checkPhoneNumberExists = functions.https.onCall((data, context) => {
return admin.auth()
.getUserByPhoneNumber(data.phoneNumber)
.then((userRecord) => {
return { phoneNumber: true }
})
.catch((error) => {
throw new functions.https.HttpsError('invalid-argument', "phoneNumber doesn't exist");
});
});
Using this approach, there is no need to save user data in Firestore. The Admin SDK will directly query the FirebaseAuth service.
I am facing a weird issue when trying to fetch the all documents under the collection.
Below is code to fetch the data from the firestore collection: "UserDetail"
db.enableNetwork();
db.collection("UserDetail")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
private static final String TAG = "UserDetail";
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful())
{
for (QueryDocumentSnapshot document : task.getResult())
{
String userEmail = document.getData().get("email").toString();
if (userEmail != null && !userEmail.equalsIgnoreCase(current_user_email))
{
<Performing some operation here.>
}
}
}
}
});
On new user registration, I am pushing User detail in this collection.
So here is what actually happening: when I register a user User1 on device1, then this code is returning the User1 in the result, but when I am trying to run the code from another device2 then User1 is not being fetched...
Can someone please help me here, not sure what is happening here.
UserDetail collection: this is how the data is getting stored under this collection. In screen shows there are 3 documents under UserDetail collection:
enter image description here
enter image description here
What I want is: to check if the user input value is available in the database. I have an EditText in my app, the user enters a phone number. When he clicks the button, the button requests to see in the database to see if the user input matches any record of a phone number in the database.
I haven't done anything um lost, but I have a screenshot of my database structure.
To check for example, if "+263782876566" already exists in the database, please use the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference officeRef = rootRef.child("Users").child("Office");
Query queryByPhone = officeRef.orderByChild("phone").equalTo("+263782876566");
officeRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot ds : task.getResult().getChildren()) {
String type = ds.child("type").getValue(String.class);
Log.d(TAG, type);
}
} else {
Log.d(TAG, task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
So we are using a reference that points to Users -> Office and then we create a Query object to actually check within all children if the "phone" property holds a specific value. If we find some results, we simply log the type. In your particular example, the result in the logcat will be:
Office member
I am trying to find the mobile number of a user from the Firestore database which has all the user details after checking a condition which says if the flat and the block number of the user matches with the entry in flat and block than retrieve his mobile number.
The image shows the screenshot of database.
If i understand you correctly, try something like this:
FirebaseFirestore fireStore = FirebaseFirestore.getInstance();
final String[] requiredMobile = {""}; //this is up to how you want to use the mobile number acquired
fireStore.collection("users").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshot) {
for (DocumentSnapshot document: documentSnapshot.getDocuments()
) {
if(document.getString("flat")== ("desired Flat") && document.getString("block") =="desired blockNumber"){
requiredMobile[0] = document.getString("mobile"); //do something with phone number
}
}
}
});
How should I fetch the document fields from one collection and combine them to add a new document to another collection? I have attached picture of the database how does it looks, I want to fetch the fields from the collection show and want to update it to the new collection along with some other data:
private void savePost(String mPostTitle, String mPostContent, String mlistSpinnerC) {
final DocumentReference docRef = FirebaseFirestore.getInstance().collection("users").document(mauth.getCurrentUser().getUid());
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document != null) {
String username = (String)
document.get("username");
String email= (String) document.get(email);
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
postMap.put(Constants.POSTTTITLE, mPostTitle);
postMap.put(Constants.POSTCATEGORY, mlistSpinnerC);
postMap.put(Constants.POSTCONTENT, mPostContent);
postMap.put(Constants.TIMESTAMP, (System.currentTimeMillis()/1000));
postMap.put(Constants.USER_ID,mauth.getCurrentUser().getUid());
postMap.put("username", username);
PostsRef.document().set(postMap).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
Intent toHomeActivity = new Intent(AddPostActivity.this, MainActivity.class);
startActivity(toHomeActivity);
}
}
});
I am just not able to map the fields from one collection to another collection, please guide me the correct method to that.
By the time you are trying to add the username to your postMap using the following line of code:
postMap.put("username", username);
The data has not finished loading yet from the database and this is because the listener you have added to your get() call is being invoked some unknown amount of time later after your query finishes. You don't know how long it's going to take, it may take from a few hundred milliseconds to a few seconds before that data is available. The onComplete() method has an asynchronous behavior, that's why you cannot get that username in such a way.
A quick solve for this problem would be to move all that block of code related to adding data to the postMap, inside the onComplete() method. In this you are waiting for the callback and username your will be available. Otherwise I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.