My Firestore structure looks something like this:
-(coll)users
-(doc)uniqueID
name
email
(coll)clients
-(doc)uniqueID
clientName
clientEmail
What I am trying to achieve is the following:
The user signs in through FirebaseUI Auth flow
If the user (uid recovered from Auth) doesn't exist in firestore db I create a document named by his uid
Once I have the uid I run a query to load clients collection in order to display them into a list using a RecyclerView (if the collection is empty hence the user hasn't created any clients yet I display an empty list screen)
I tried to make a query using the code below as per the documentation:
clientsCollection = db.collection(FIRESTORE_COLLECTION_USERS)
.document(mUid)
.collection(FIRESTORE_COLLECTION_CLIENTS);
clientsCollection
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (DocumentSnapshot document: task.getResult()){
Log.d(LOG_TAG, document.getId() + " => " + document.getData());
}
} else {
Log.d(LOG_TAG, "error getting documents: ", task.getException());
}
}
});
I get the following RuntimeException:
java.lang.NullPointerException: Provided document path must not be null.
I get this even if the clients collection exits with some documents in it named by unique uid.
Thanks for any clue you could give me! :)
The error message indicates that mUid is null when you run the first statement. Most likely this means that you run this code before the user is signed in.
Make sure that you only call this code after the user has signed in, e.g. from an AuthStateListener.onAuthStateChanged():
FirebaseAuth.getInstance().addAuthStateListener(new AuthStateListener() {
public void onAuthStateChanged(FirebaseAuth auth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
clientsCollection = db.collection(FIRESTORE_COLLECTION_USERS)
.document(user.getUid())
.collection(FIRESTORE_COLLECTION_CLIENTS);
clientsCollection
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (DocumentSnapshot document: task.getResult()){
Log.d(LOG_TAG, document.getId() + " => " + document.getData());
}
} else {
Log.d(LOG_TAG, "error getting documents: ", task.getException());
}
}
}
}
})
Related
I'm trying to add data to a document to Firebase Firestore. I've added a collection named users to it. Also the read/write permissions are open for now. I'm following this doc. And I'm not able to add data to document.
Here is what I'm trying to do:
private void getNewUserSnapShot() {
FirebaseFirestore db = FirebaseFirestore.getInstance();
FirebaseUser user = firebaseAuth.getCurrentUser();
Log.d(TAG, "getNewUserSnapShot: user_uid: " + user.getUid());
DocumentReference user_doc_ref = db.collection("users").document();
Log.d(TAG, "getNewUserSnapShot: document ref: " + user_doc_ref.getId());
Map<String, Object> user_data = new HashMap<>();
user_data.put("name", user.getDisplayName());
user_data.put("email", user.getEmail());
user_data.put("profile_url", user.getPhotoUrl());
Log.d(TAG, "getNewUserSnapShot: user_data: " + user_data.toString());
user_doc_ref
.set(user_data)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(LoginActivity.this, task.toString(), Toast.LENGTH_LONG).show();
if (task.isSuccessful()) {
Log.d(TAG, "getNewUserSnapShot: success");
} else {
Log.d(TAG, "getNewUserSnapShot: failed");
}
}
});
}
In Logs I see only these (neither the log for failure nor for success):
2020-03-04 19:48:47.489 30744-30744/com.example.expenditure D/LoginActivity: getNewUserSnapShot: user_uid: iXOzfju6kORnhuUND8zFCPTzxY93
2020-03-04 19:48:47.499 30744-30744/com.example.expenditure D/LoginActivity: getNewUserSnapShot: document ref: 7AluPzcYMLzDKLh8YtBt
2020-03-04 19:48:47.499 30744-30744/com.example.expenditure D/LoginActivity: getNewUserSnapShot: user_data: {profile_url=https://someurl/security/reasons, name=Nikhil Wagh, email=null}
And when I see firebase console, I can't find the document with ID 7AluPzcYMLzDKLh8YtBt, according to logs which should have been created.
There is a similar question: Unable to add information to Cloud Firestore But it doesn't have right answers.
Can someone help. What am I doing wrong?
The issue was user.getPhotoUrl() returns url, but Firestore doesn't support urls. The url needs to be casted as a string, and then it works.
Cast your urls to string before adding data to Firestore.
I wrote the rules for my firestore database that is only authenticated users can read and write the data into documents. The rule is:
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to access documents in the "cities" collection
// only if they are authenticated.
match /PhoneAuthUsers/{phoneid=**} {
allow read, write: if request.auth.uid != null;
}
}
}
and i published the rule whenever i run the app i got the error line
"Missing Insufficient Permissions"
My authentication method is Phoneauthentication and i have the auth id in authentication tab. This is my db structure :
**- PhoneAuthUsers(Collection)
- Phonenumber(documents)
- Accounts(Collection)
-autoid(Document)**
Client side code :
db.collection("PhoneAuthUsers")
.whereEqualTo("PhoneNumber", mobile)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
System.out.println("hello user");
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
Log.d(TAG, document.getId() + " => " + document.getData());
AuthID = document.getId();
System.out.print("AuthIDPhonenumber" + AuthID);
System.out.println("PhoneNumber");
String phone = document.getString("PhoneNumber");
Log.d(TAG, "onSuccess: " + phone);
if (phone.equals(mobile)) {
count = count + 1;
System.out.println("count" + count);
}
}
When trying to execute the query it shows missing insufficient permissions.
For example :
PhoneAuthUsers/+911234567890/Accounts/autoid/Field Values. when getting the documents from the phoneauthusers i am getting the missing insufficient permissions. How to solve the issue.
I'm trying to retrieve all my documents from a collection name Items and i'm just pasting the code given by google to retrieve all documents from a collection.But Every time i run it always produce java.lang.NullPointerException. Can u tell me why
I used the code that is given by goggle to retrieve all collections from fire store.But unfortunately it didnt work
db.collection("Items")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Log.d(TAG, document.getId() + " => " + document.getData());
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
Every time i run it shows this Error
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.firestore.CollectionReference com.google.firebase.firestore.FirebaseFirestore.collection(java.lang.String)' on a null object reference
I am using Cloud Firestore in my Android app. It's a quiz application where I randomly get documents from Firestore. When the internet connection is good, the app works fine. When the network gets disconnected and then again gets connected, I am unable to read the documents. When I debug, I find that my get() method is not getting executed at all.
Iterator iterator = randomIds.iterator();
while (iterator.hasNext()) {
String documentId = (String) iterator.next();
DocumentReference documentReference = db.collection(categoryName).document(documentId);
if (documentReference!=null) {
documentReference.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
System.out.println("Task successful");
DocumentSnapshot document = task.getResult();
questionDetailsObj = new QuestionDetails();
questionDetailsObj = document.toObject(QuestionDetails.class);
if (questionDetailsObj != null) {
System.out.println("Question details: " + questionDetailsObj.getQuestion_text());
// Adding the questions to a list
questionsList.add(questionDetailsObj);
}
} else {
Log.d("MainActivity", "get() failed with " + task.getException());
}
}
});
}
}
I want to retrieve 10 documents. Sometimes, few documents are retrieved successfully and for the others I get the exception
get() failed with com.google.firebase.firestore.FirebaseFirestoreException:
Failed to get document because the client is offline.
I don't understand why would some documents come successfully and some fail to get retrieved. Please help me understand if any code changes are required.
Ok I am a running into a weird problem with firestore
I have the following structure
collection1 -> document1- >collection2
I am adding a new document to collection2 with on complete listener( I tried the success listener as well). No errors are shown. The new document is not shown on the console. The listener is not being called. However, when I query, I get ALL the added documents including the new ones. What's going on here?
Map<String, Object> data = new HashMap<>();
data.put("completed", true;
data.put("date_completed", new Date());
data.put("location", "123 main st");
data.put("notes", "");
data.put("work", "");
db.collection("collection1").document(document1).collection("collection2")
.add(data)
.addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
#Override
public void onComplete(#NonNull Task<DocumentReference> task) {
if (task.isSuccessful()) {
DocumentReference documentReference = task.getResult();
Log.d(TAG, "DocumentSnapshot written with ID: " + documentReference.getId());
det.setDocId(documentReference.getId());
addr_arr.add(det);
} else {
Log.w(TAG, "Error adding document", task.getException());
Toast.makeText(EditListActivity.this, "Failed operation - " + task.getException().getMessage(),
Toast.LENGTH_SHORT).show();
hideProgressDialog();
}
}
});
Here is the query I do
CollectionReference collecRef = db.collection("collection1").document(document1).collection("collection2");
collecRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
// here I do document.get on all the fields, add them to object and add object to array
}
adapter.notifyDataSetChanged();
} else {
Log.d(TAG, "get failed with ", task.getException());
Toast.makeText(EditListActivity.this, "Failed operation - " + task.getException(),
Toast.LENGTH_SHORT).show();
hideProgressDialog();
}
}
});
Your app is acting like it's offline or somehow lacking a working internet connection.
When there is no network connection, the Firestore SDK won't fail on writes. It will store the write locally, and eventually sync that to the server. In the meantime, the local write becomes part of any queries, just like if the data was available on the server. So probably what you're seeing is the result of your local write.
(This is the same behavior you would see with Realtime Database.)
As far why the Firestore SDK doesn't have a connection, I don't know. You might have to troubleshoot that on your own.