I would like to set up something like a groupchat in Firebase. If you have the correct group ID, you can join.
The problem is that Firebase references always exist. They are created dynamically. To allow some error checking in the joining process, I want to add the user who created the new database entry to a table of users.
public void createParty() {
// you need to be signed in to create a party
assertState(DBState.SignedIn);
// create a new party
ourPartyDatabaseReference = partiesDatabaseReference.push();
usersDatabaseReference = ourPartyDatabaseReference.child("users");
// write our user to the table of users, now the ourPartyReference actually exists
// and if you look for existing users, you will always find at least the original creator
Task initTask = usersDatabaseReference.child(user.getUid()).setValue(true);
After this has been done, I call a helper method connectToParty
to set up a few references and change the state of the database connection to DBState.Connected
. Now you can take the key of the party and transmit it to other users. With key I mean the name in firebase.
The problem is: Other users need to check whether they used a valid key to connect. They do this by checking if there is data under key/users
. So the party is only valid if the first user has been successfully written to the database.
Sometimes the write process takes very long, sometimes it seems to fail completely. So I've set up listeners:
Task initTask = usersDatabaseReference.child(user.getUid()).setValue(true);
initTask.addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(Object o) {
connectToParty();
}
});
initTask.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
changeState(DBState.SignedIn, DBTransition.Failure);
}
});
This is covered by a test. The test sets up a connection, signs in and creates a party. If the party is created within a specific timeout, the test passes.
9 out of 10 times this works without a problem. But sometimes the test fails.
This has nothing to do with the timeout being to short. The callbacks from the task are simply not called. I read that this callback only works if your connection is online.
So I added firebaseDatabase.goOnline();
to my code, just before the task. But that doesn't help.
I'm connected to the internet over LAN. All the other tests pass, and they need to access firebase, too. For example for the sign-in process.
What is the correct way to write a value to the database and wait for the write to complete ?
For the Kotlin users, you can use this
firebaeRef.setValue("your_value", { error, ref ->
//setValue operation is done, you'll get null in errror and ref is the path reference for firebase database
})
Here, firebaeRef
is the reference to the node/child who's value is set and your_value
is the value to be set.
As the offical documentation says:
If you'd like to know when your data has been committed, you can add a completion listener. Both setValue() and updateChildren() take an optional completion listener that is called when the write has been committed to the database.
This is a simple example:
ref.setValue("I'm writing data to a Firebase database", new Firebase.CompletionListener() {
@Override
public void onComplete(FirebaseError firebaseError, Firebase firebase) {
if (firebaseError != null) {
System.out.println("Data could not be saved. " + firebaseError.getMessage());
} else {
System.out.println("Data saved successfully.");
}
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With