3

I'm using Firestore in my app and I can't figure out how to handle at user level the exceptions thrown by that. (I mean what to display to the user when such exceptions occur).

For example, to perform any CRUD operation on Firestore (DocumentReference#get, DocumentReference#set, DocumentReference#update) a Task is returned, which might contain an exception, but in the documentation I can't find why this exception might be thrown by Firestore.

Is there something better that we can do, rather than simply log the exception and show a generic message like "an error occurred, please try again later"?

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Clyky
  • 247
  • 4
  • 14

2 Answers2

3

As in the official documentation regarding getting data, you can get the exception from the task object like this:

docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
    @Override
    public void onComplete(@NonNull Task<DocumentSnapshot> task) {
        if (task.isSuccessful()) {
            DocumentSnapshot document = task.getResult();
            if (document.exists()) {
                Log.d(TAG, "DocumentSnapshot data: " + document.getData());
            } else {
                Log.d(TAG, "No such document");
            }
        } else {
            //Log the error if the task is not successful
            Log.d(TAG, "get failed with ", task.getException());
        }
    }
});

And remember, a Task is complete when the work represented by the Task is finished, regardless of its success or failure. There may or may not have been an error, and you have to check for that. On the orter side, a Task is "successful" when the work represented by the task is finished, as expected, with no errors.

As @Raj mentioned in his answer, you can also use addOnFailureListener but note, if there is a loss of network connectivity (there is no network connection on user device), neither onSuccess() nor onFailure() are triggered. This behavior makes sense, since the task is only considered completed when the data has been committed (or rejected) on the Firebase server. onComplete(Task<T> task) method is called also only when the Task completes. So in case of no internet connection, neither onComplete is triggered.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • I've checked better the docs for `DocumentReference#get` method, and it says that the task can fail if the document cannot be retrieved neither from server nor from local cache. So, I've understood that if there is a loss of network connectivity and the document is not cached, the `onFailureListener`/`onCompleteListener` will be called anyway, am I right? – Clyky Aug 22 '18 at 19:21
  • No! Let's take an example. [OnSuccessListener](https://developers.google.com/android/reference/com/google/android/gms/tasks/OnSuccessListener) is an interface. An interface cannot be called. What can be called instead, is the method that exists in this interface, in this case `onSuccess()` method. But in case of no network connection on user device, neither `onSuccess()` nor `onFailure()` are triggered. One or the other will be called, only when the data has been committed (or rejected) by the Firebase servers, ok? – Alex Mamo Aug 22 '18 at 19:39
  • Is there everything alright, can I help you with other informations? – Alex Mamo Aug 23 '18 at 08:10
  • so if those callbacks (`onSuccess()` and `onFailure()`) are not called in that case, do I need to perform a check for network connectivity every time I need to read/write data in firestore? – Clyky Aug 23 '18 at 11:06
  • No, there is no need for that. Every time you don't have internet connection, the data is read from the cache. There is a workaround for this, so please check my answer from this **[post](https://stackoverflow.com/questions/46894118/cant-disable-offline-data-in-firestore)**, to see how you can use `documentSnapshot.getMetadata().isFromCache()`., to see if you are reading data from or Firebase servers. – Alex Mamo Aug 23 '18 at 11:39
2

You can use onFailureListener() method of Firestore and get the errors while getting, setting or updating the data. In this example I have used it in setting data:-

firestore.collection("User").document(uid).set(user).addOnSuccessListener(this, new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid)
        {
          //Data Saved Successfully
        }
    })
            .addOnFailureListener(this, new OnFailureListener() {
                @Override
                public void onFailure(Exception e)
                {
                    //Toast error using method -> e.getMessage()

                }
            });

If you want to catch exceptions in firebase authentication module then refer:- How to catch a Firebase Auth specific exceptions

Raj
  • 2,997
  • 2
  • 12
  • 30