1

I'm messing around with Cloud Firestore.

I would like to simply get a callback when reading from DB fails, so I can show a dialog to the user about he has no internet connection. Of course, this would need sophisticated exception handling, but first things first, I would like to just simply get a callback when the app cannot reach the server.

HOWEVER, whenever I test my application with an emulator which has no internet connection, I still get successful callbacks.

This is the log:

Logging_: onSuccess
Logging_: onComplete
Logging_: Task was successful without an internet connection, how?

How is it possible? Am I thinking right that Cloud Firestore is simply not available for this use case since it was built to provide cached data and aggressive syncing in order to provide a seamless user experience even when there is no internet connection?

I would just need a way to just KNOW whether the DB is reachable. (a.k.a - Is there an internet connection problem?)


Code is really simple, it just tries to reach for the current account's characters.

  db.collection("users")
                .document(accountId)
                .collection("characters")
                .get()
                .addOnCanceledListener(new OnCanceledListener() {
                    @Override
                    public void onCanceled() {
                        Log.i("Logging_", "onCanceled");
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.i("Logging_", "onFailure");
                    }
                })
                .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                    @Override
                    public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                        Log.i("Logging_", "onSuccess");
                    }
                })
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {

                        Log.i("Logging_", "onComplete");

                        if (task.isSuccessful()) {
                            Log.i("Logging_", "Task was successful without internet connection, how?");
                        } else {
                            Log.i("Logging_", "Task wasn't successful.");
                        }
                    }
                });
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Adam Varhegyi
  • 11,307
  • 33
  • 124
  • 222

2 Answers2

2

I would like to simply get a callback when reading from DB fails, so I can show a dialog to the user about whether he has no internet connection.

The Firestore SDK doesn't throw an error when there is no internet connection, and it makes sense since Firestore is designed to work offline. Behind the scenes, Firestore SDK tries to reconnect until the devices regain connectivity. So not having an internet connection cannot be considered a failure. If you want to check for internet connectivity, the following answer might help:

Please notice that Firestore has a built-in mechanism that can help know when an error occurs. So the failure callback occurs when Firestore servers reject the request due to a security rule issue.

There is a solution in which you can force the retrieval of data only from the cache or from the server. Here is the official documentation regarding source options:

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Okay so as you say Cloud Firestore is ineligible for the task I would like to make? I'm not interested in showing a dialog when there is no internet, I'm interested in using an online database which pops an error whenever the real-time-writing was failed. (For connection reasons, or any other reasons) – Adam Varhegyi Aug 02 '22 at 07:58
  • No, you can achieve that with Cloud Firestore. But try to understand that when the user has no internet access, the user can continue to write data (to the cache). This is not considered a failure. When it regains connectivity, all data will be synced with the Firestore servers. – Alex Mamo Aug 02 '22 at 08:03
  • I'm trying to query whether a particular character name is already taken in a game by any of the users. I do want it to be only ONLINE query, this type of information is not available for caching since it can change in any point of time. (When a player creates a character) Is Cloud Firestore available for such thing? And if yes, how? – Adam Varhegyi Aug 02 '22 at 08:34
  • In that case, you have to constantly check for an internet connection, and perform the desired query **only** when the user is online. So you can continue using Firestore. – Alex Mamo Aug 02 '22 at 08:37
  • That is clearly not a solution. I need a callback from the endpoint whether the operation was successful or not, not a pre-run "prediction". Even if I predict in one point of time that there is actually internet connection available, in the very next moment internet connection can fail and my query would return with a false positive "onSuccess". – Adam Varhegyi Aug 02 '22 at 08:47
  • That's indeed what you'll get, a success callback when the read operation succeeds, or a failure callback when the read operation fails. It's one or the other. But it will fail **only** when the Firebase servers will reject the operation, due to improper rules, and not when the user doesn't have an internet connection. – Alex Mamo Aug 02 '22 at 09:00
  • Alright so can we say that Cloud Firestore is ineligible for making a query task that relies on real time connection? – Adam Varhegyi Aug 02 '22 at 09:17
  • Firestore can work in both situations, online and offline. So when offline, there is **no** way you can query Firebase servers. Without connectivity, you can wait until the device regains connectivity, or check for internet connection and display a message to the user. – Alex Mamo Aug 02 '22 at 09:26
  • As of right now I don't see a way that it can achieve what I want. Maybe it is possible but I yet to find a solution. The queries simply return onSuccess() as I stated in the question when there is no internet connection. Your last comment is kind of out of context. Checking internet connection in a pre rutine is not a solution. I need end-point certainty whether the query was successful or not. Right now it says it was successful even without internet connection. – Adam Varhegyi Aug 02 '22 at 09:38
  • Yes, that's the expected behavior to return success even if there is no internet connection. I repeat, losing the internet connection **cannot** be considered a failure. We have a failure only when Firebase servers reject the operation. That's the only way you can have it a failure. For other operations, you might also consider using [source options](https://firebase.google.com/docs/firestore/query-data/get-data#source_options). – Alex Mamo Aug 02 '22 at 10:10
  • That's what I needed. To force it only online mode. If you post this as an answer I accept. – Adam Varhegyi Aug 02 '22 at 10:13
  • Ok, I'll update the answer right away. – Alex Mamo Aug 02 '22 at 10:19
  • I just updated it. – Alex Mamo Aug 02 '22 at 10:21
0

Firestore has built in caching that is enabled by default for reading from a database on Apple and Android devices. If you want to disable being able to read the cached data, you can do something like this:

FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
    .setPersistenceEnabled(false)
    .build();
db.setFirestoreSettings(settings);

I think what you may want to do instead is listen to network events in Android which would allow you to update the user if they try to perform an action while there is no network available.

This might be a bug. I have logged the tracking info here on GitHub

Alexander N.
  • 1,458
  • 14
  • 25
  • Works the very same way even with persistence turned off. The call backs are telling me everything is okay even when there is no internet connection. Weird. – Adam Varhegyi Aug 01 '22 at 21:11
  • @AdamVarhegyi - You could use the isFromCache method to determine if the data is stale : https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/SnapshotMetadata#isFromCache() I think your best bet for determining network state is to listen to the network events in Android. I just tested one of my apps and I can see a failure happen for my code. – Alexander N. Aug 01 '22 at 21:37
  • @AdamVarhegyi - I take that back. I am seeing what you are seeing now. I am going to try to see if I can dig – Alexander N. Aug 01 '22 at 21:44