I'm getting an error while offline.
I already set the Persistence to True and getting some cached data while offline, but there is one function that gives me this offline error. The logcat point me on task.getResult().exists().
I don't know what to do, can anyone help me?
ERROR: com.google.android.gms.tasks.RuntimeExecutionException: com.google.firebase.firestore.FirebaseFirestoreException: Failed to get document because the client is offline.
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if(!task.getResult().exists()){ //I GET ERROR HERE
Map<String, Object> likesMap = new HashMap<>();
likesMap.put("timestamp", FieldValue.serverTimestamp());
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).set(likesMap);
} else {
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).delete();
}
}
});
for me in flutter android app development process
Open android studio emulator and choose wipe data
and run again
note: I know only for android.
Related
I cannot get my Android device to receive a test variant during the AB experiment.
What i did
In Firebase admin panel, I created a variable with this value:
And created an AB test with three variants:
Then I got an instance token as per docs:
FirebaseInstallations.getInstance().getToken(/* forceRefresh */true)
.addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
#Override
public void onComplete(#NonNull Task<InstallationTokenResult> task) {
if (task.isSuccessful() && task.getResult() != null) {
Log.d("Installations", "Installation auth token: " + task.getResult().getToken());
promise.resolve(task.getResult().getToken());
} else {
Log.e("Installations", "Unable to get Installation auth token");
}
}
});
and added it to my test devices list:
What happened
However, after rebooting the app (I also cleaned the cache and force-stopped it just in case it cached something) it still receives the original default value:
...
Map<String, Object> responseMap = new HashMap<>(2);
responseMap.put("result", result);
responseMap.put("constants", module.getConstantsForApp(FirebaseApp.DEFAULT_APP_NAME));
Log.d("REMOTECONFIG", responseMap.toString());
...
in the logs:
10-04 10:25:12.886 16964 16964 D REMOTECONFIG: {result=true, constants={minimumFetchInterval=43200, fetchTimeout=60, values={testValue=Bundle[{source=remote, value=somedefault}]}, lastFetchTime=1601796312020, lastFetchStatus=success}}
Why is that? what am I missing? I doublechecked my token, verified it with jwt.io, it is valid and not expired.
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 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.
In my case, Firestore database looks like below, where each Android client will have one document mapped to his/her device Document_sdfljkhsdio ( specific to Android User 1 )
FireStoreCollection
Document_sdfljkhsdio ( specific to Android User 1 )
Collection_xyz
Document_xyz
Document_kjjkssefd ( specific to Android User 2 )
Collection_xyz
Document_xyz
Document_sqdfwdfsme ( specific to Android User 3 )
Collection_xyz
Document_xyz
I am not implementing Google Auth, but instead want to send document name Document_sdfljkhsdio as request data and match it with some rules at Firebase Console
service cloud.firestore {
match /databases/{database}/documents {
match /document/{document_sent_from_client}/ {
allow read, write: if request.document_sent_from_client == document_sent_from_client;
}
}
}
Am not sure if it is possible to send document name from Android device ,if yes, please suggest.
And also suggest if it is the correct approach, suggest if you have any better approach ?
Thanks for your help in advance.
Sounds totally feasible. To pass the document_sent_from_client from an Android client, just build a DocumentReference with a path to /document/document_sent_from_client. Modified from the documentation:
DocumentReference docRef = db.collection("document").document("document_sent_from_client");
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document != null) {
Log.d(TAG, "DocumentSnapshot data: " + task.getResult().getData());
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
But the security rules don't help here: if the client requests an existing document (i.e. if they know the path to a document), they will get a result. If they request a non-existing document (i.e. if they don't know the path to a document), the task will fail.
You're essentially depending on the key in document_sent_from_client to be reasonably unguessable. Such "security by obscurity" is fairly common in the absence of an authenticated user.