Its a very weird issue with Firebase. I am calling setValue() on a Firebase node and then expecting OnComplete callback function to be called, which is never being called on a particular internet connection. Other firebase queries are also not working on that particular WiFi,
individualUserNode.setValue(user, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
EventBus.getDefault().post(new MyEvents.UserSaved(true));
} else {
EventBus.getDefault().post(new MyEvents.UserSaved(false));
}
}
});
That's expected. The listener only fires once the server acknowledges the request:
This interface is used as a method of being notified when an operation
has been acknowledged by the Database servers and can be considered
complete
Related
I have this strange thing where OnSuccessListener or OnFailureListener stopped being called. Everything works ok but when I turn of mobile data and Wifi non of the OnSuccessListener or OnFailureListener is being called.
If I put a breakpoints on the below code ref.set(update)..... the breakpoints are indeed hit but non of the OnSuccessListener or OnFailureListener fires
Map<String, String> update = new HashMap<>();
update.put(ByteData.DATA, data);
DocumentReference ref = firestore
.collection(DEVICE_DATA)
.document(FirestoreManager.getInstance().getUserId())
.collection(DEVICE_DATA_STREAM)
.document(batteryEntity.getEntityId());
ref.set(update).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// do some stuff
}
}).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// do some stuff
}
});
when I turn of mobile data and Wifi [neither] the OnSuccessListener or OnFailureListener is being called
That is the expected behavior. The completion listeners are only called once the data has been written on (or rejected by) the server.
The listener doesn't fire for local write operation. If the local write operation were to fail, the client will raise a regular exception.
I'm facing an issue regarding the Firebase Realtime database and in particular the value event listener which fires more than once .Seems that when the Internet state changes from on to off several times and the device finally has stable connection the onDataChange(DataSnapshot dataSnapshot) callback method of the listener is invoked with dataSnapshot of null content.Seems that the Realtime Database refers to the app's local cache and in that case I do not have any data stored in it. I am attaching the listener inside the Activity onStart() or when the device has established some connection ; I am detaching the listener inside the Activity onStop() method or when the device looses internet connection .Only one instance of a given listener exists at a time and every attach has corresponding detach action executed when needed. I have tried to wait a while between the change of the connection states before attaching the listener and to reattach the listener if the datasnapshot returns null .None of those worked.Please advice for a solution.
Some example code inside an Activity :
private ValueEventListener listener;
private Query query;
private boolean hasAttachedListener;
private Query getDatabaseReference() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
return reference.child(“some child ref”)
.child(“other child ref 2 ”);
}
private ValueEventListener getDatabaseListener() {
return new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(“firebase”, dataSnapshot.toString());
//issue here datasnapshot is null sometimes
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(“firebase”, databaseError.getDetails());
}
};
}
/**
* Attaches listener
*/
public void addListener() {
if (!hasAttachedListener) {
query = getDatabaseReference();
listener = getDatabaseListener();
query.addValueEventListener(listener);
hasAttachedListener = true;
}
}
/**
* Detaches the attached listener
*/
public void removeListener() {
if (hasAttachedListener) {
query.removeEventListener(listener);
query = null;
listener = null;
hasAttachedListener = false;
}
}
#Override
protected void onStart() {
super.onStart();
addListener();
}
#Override
protected void onStop() {
super.onStop();
removeListener();
}
#Override
protected void onNetworkDisconnected() {
super.onNetworkDisconnected();
// invoked when internet connection is lost
removeListener();
}
#Override
protected void onNetworkReconnected() {
super.onNetworkReconnected();
// invoked when internet connection is restored
addListener();
}
With firebase offline capabilities you are not needed to use those two method to listen if there is no connection to the database
so your onNetworkDisconnected and onNetworkReconnected are not necesary
check the firebase docs here : https://firebase.google.com/docs/database/android/offline-capabilities
Keeping Data Fresh
The Firebase Realtime Database synchronizes and stores a local copy of the data for active listeners. In addition, you can keep specific locations in sync.
DatabaseReference scoresRef = FirebaseDatabase.getInstance().getReference("scores");
scoresRef.keepSynced(true);
The Firebase Realtime Database client automatically downloads the data at these locations and keeps it in sync even if the reference has no active listeners. You can turn synchronization back off with the following line of code.
The new data should have unique name to prevent replacement of existed
I have nodejs server and an android client. Both are connected to my firebase database. When the server sets the "RefNode" to null, the onDataChanged Callback, that is set on that "RefNode" on the andriod side, gets called.
Is there any way to avoid it being called in the special case when the "RefNode" was set to null while for all other cases it should get called.
I have a listener on a node "RefNode" in my android application as given below:
The OnDataChanged() callback is getting called even when the "RefNode" was set to null by the nodejs server.
FirbaseDatabase.getInstance().getReference().child("RefNode").addValueEventListener( new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
if(dataSnapshot.getValue()!=null) {
Log.v(TAG, "got here even when the Refnode was set to null");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// The listener got cancelled
}
});
I have found the problem I had attached the event listener twice. I had made the ValueEventListener a field of the class the and attached it twice.
Is there any way to know data which is not uploaded on firebase and is persisting on disk? I have enabled offline capability by using-
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
By doing this my all data remains cached. I want to know which data is uploaded and which isnt.
There is no method in the API that returns an indication of which write operations have not yet been committed to the Firebase server. If you need that status, you can manage it yourself. The setValue() and updateChildren() methods provide two options for getting a callback when the value is committed to the Firebase server. One option is to provide a CompletionListener parameter:
FirebaseDatabase.getInstance().getReference("test")
.setValue("SomeValue", new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
// the data was successfully committed to the server
} else {
// the operation failed, for example permission failure
}
}
});
The other option is to add a listener to the returned Task:
FirebaseDatabase.getInstance().getReference("test")
.setValue("SomeValue").addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
// the data was successfully committed to the server
} else {
// the operation failed, for example permission failure
}
}
});
For both cases, the update is in the local cache immediately after the call to setValue() or updateChildren(), but is not in the server database until the callback fires.
I am using the new Firebase console. I am trying to save an object to the database but its not getting saved. Following is the code.
DatabaseReference mFirebaseRef = FirebaseDatabase.getInstance().getReference();
mFirebaseRef.push().setValue(object, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference reference) {
if (databaseError != null) {
Log.e(TAG, "Failed to write message", databaseError.toException());
}
}
});
the 'object' is created properly. There is no error I am getting and I have checked in debugging that the onComplete method is not getting triggered.
Security Rule is also true for write.
Note that DatabaseReference.CompletionListener fires "when an operation has been acknowledged by the Database servers". Is it possible you did not have a network connection at the time you ran your test? I copied your code and ran it successfully on a phone with object defined like this:
Object object = new String("Test");
I then enabled airplane mode, re-ran the code and observed the behavior you describe. The completion listener did not fire until I disabled airplane mode and a network connection was established.
Example code for checking the status of your network connection is provided in this documentation.
use the below code:
mFirebaseRef.push().setValue(object).addOnCompleteListener(new OnCompleteListener<Void>()
{
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
// write code for successfull operation
}
}
});
}
.push will generate a random key on which your data will stored if you do not use .push it will overwrite on previous stored data.