3

I am trying firestore database on Android.

This is my code that inserts a document:

public Observable<Post> createPost(final Post post){


        return Observable.create(new Observable.OnSubscribe<Post>() {
            @Override
            public void call(final Subscriber<? super Post> subscriber) {

                try{

                    DocumentReference documentReference = getCollection().document();

                    post.setId(documentReference.getId());
                    documentReference.set(post).addOnSuccessListener(new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(Void aVoid) {

                            subscriber.onNext(post);
                            subscriber.onCompleted();

                        }
                    }).addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            subscriber.onError(e);
                            subscriber.onCompleted();
                        }
                    });


                }catch (Exception ex){

                    subscriber.onError(ex);

                    Log.e(LOG_TAG, ex.getMessage(), ex);

                }

            }
        });


    }

The document gets inserted into the database but neither of the onSuccess nor the onFailure callbacks are invoked.

Update 1


  1. The issue is not consistent sometimes it works, sometimes the callbacks are invoked after an hour, sometimes after 3 hours etc..

  2. This is happening when there is no internet connection.

Update 2

  1. The issue was reported here and it is closed. I am not sure how to guarantee the correctness of data created offline.
dsharew
  • 10,377
  • 6
  • 49
  • 75

3 Answers3

0

There does not seem to be anything wrong with your code, try perhaps the onCompleteListener callback. So add

.addOnCompleteListener((Task<Void> task) -> {
                    if(task.getException() != null) {
                        emitter.onError(task.getException());
                    }
                    if(task.isComplete()) { //try task.isSuccessful() if this is what you are looking for
                        emitter.onComplete();
                    }
                });

If this does not solve your issue perhaps, use an emitter like so:

Completable completable$ = Completable.create((CompletableEmitter emitter) -> {
    firebaseFirestore.collection(collection).document(document)
        .delete()
        .addOnSuccessListener((Void aVoid) -> emitter.onComplete())
        .addOnFailureListener((Exception e) -> emitter.onError(e))
        .addOnCompleteListener((Task<Void> task) -> {
            if(task.getException() != null) {
                emitter.onError(task.getException());
            }
            if(task.isComplete()) { //try task.isSuccessful()
                emitter.onComplete();
            }
        });
});
return completable$;
martinomburajr
  • 1,235
  • 14
  • 29
  • 1
    I tried adding ```addOnCompleteListener``` but still not working. Also I updated the question please check. Thanks – dsharew Dec 13 '17 at 06:07
0

Okay so I did a simple version of your question but instead of adding a post, it adds a User. The concept is the same.

Here is the method to add a user. It returns an Observable<DocumentReference> just to reference where the user was added.

public  Observable<DocumentReference> insertToFirebaseFirestore$() {
    UserEntity userEntity = new UserEntity();
    userEntity.setEmail("myemail@myemail.com");
    userEntity.setBio("I'm a cool cat!");
    userEntity.setDisplayName("KoolKat!");

//Notice here I am using an ObservableEmitter instead of Subscriber like you did
    return Observable.create((ObservableEmitter<DocumentReference> emitter) -> {
        this.firebaseFirestore.collection("tempUsers")
                .add(userEntity)
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        emitter.onError(e);
                    }
                })
                .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                    @Override
                    public void onSuccess(DocumentReference documentReference) {
//this gets triggered when I run
                        emitter.onNext(documentReference);
                    }
                })
                .addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
                    @Override
                    public void onComplete(@NonNull Task<DocumentReference> task) {
//this also gets triggered when I run
                        emitter.onNext(task.getResult());
                    }
                });
    });

}

When I run this, and place breakpoints inside onSuccess and onComplete. Both of them are triggered and I can see the output.

I call the method from the Activity as follows.

...onCreate method
insertToFirebaseFirestore$()
        .subscribeOn(Schedulers.io())
        .observeOn(Schedulers.io()) //observe on io thread cause I don't need it to updateUI.
        .subscribe((DocumentReference val) ->{
            Log.e("USERACTIVITY", "You have uploaded " + val.getId());
        });

The LogcatPrints

12-13 09:47:47.942 15007-15059/com.example.debug E/USERACTIVITY: You have uploaded sFBsF4ZmwGaDdxCEKuF6
12-13 09:47:57.563 15007-15059/com.example.debug E/USERACTIVITY: You have uploaded sFBsF4ZmwGaDdxCEKuF6.
  1. From what I have see with yours, perhaps use an emitter within your Observable.create.
  2. If that doesn't work try doing the firestore call without wrapping it in an observable
  3. If all else, might be a connection issue, since you say it happens intermittently
martinomburajr
  • 1,235
  • 14
  • 29
  • couldnt get ```ObservableEmitter``` class. Which lib are u using for rx? – dsharew Dec 13 '17 at 08:19
  • and it could not be connection issue because I have enabled offline persistency. – dsharew Dec 13 '17 at 08:21
  • I think you are right the issue is happening when the user is not connected to the internet. I have enabled offline perssistency but dont know what is causing the issue. – dsharew Dec 13 '17 at 10:58
  • Offline persistence is by default always enabled on Android and iOS. I am using //rxjava ` compile io.reactivex.rxjava2:rxjava:2.1.5` . The way I get the emitter is by typing in `Observable.create(emitter->{})` 2. inside the parentheses I press `alt+enter` to expand the lambda to the receive its type. At which point it automatically locates the correct class. I believe by default if you type in a parameter within the `create()` it will assume it is of type emitter. – martinomburajr Dec 13 '17 at 13:03
0

I came across this with react native.

For inserts the key is to create a new document.

example:

const userRef = firebase.firestore()
                  .collection("users")
                  .doc();
userRef.set({name: someName});

This will create the document offline and sync when you come back online.

Further calls such as this will work offline

userRef.collection("Locations").add({location: "Austin,TX"});
dnndeveloper
  • 1,631
  • 2
  • 19
  • 36