In my app, I simply try to retrieve a reading passage from my Firebase
database by adding a ListenerForSingleValueEvent
in the following code:
Firebase separates the flow of data events (such as onDataChange()
) from other things that might happen. It will only call onCancelled
when there is a server-side reason to do so (currently only when the client doesn't have permission to access the data). There is no reason to cancel a listener, just because there is no network connection.
What you seem to be looking for is a way to detect whether there is a network connection (which is not a Firebase-specific task) or whether the user is connected to the Firebase Database back-end. The latter you can do by attaching a listener to .info/connected
, an implicit boolean value that is true
when you're connected to the Firebase Database back-end and is false
otherwise. See the section in the document on detecting connection state for full details.
Hope that my solution can help somebody else (I assume that you already did something else)
Besides to set the keepSynced
to true
in my database reference:
databaseRef.keepSynced(true)
And add to my Application class:
FirebaseDatabase.getInstance().setPersistenceEnabled(true)
I've added two listeners, one for offline mode and other one for online:
override fun create(data: BaseObject): Observable<String> {
return Observable.create { observer ->
val objectId = databaseRef.push().key
objectId?.let { it ->
data.id = it
val valueEvent = object : ValueEventListener {
override fun onCancelled(e: DatabaseError) {
observer.onError(e.toException())
}
override fun onDataChange(dataSnapshot: DataSnapshot) {
observer.onComplete()
}
}
// This listener will be triggered if we try to push data without an internet connection
databaseRef.addListenerForSingleValueEvent(valueEvent)
// The following listeners will be triggered if we try to push data with an internet connection
databaseRef.child(it)
.setValue(data)
.addOnCompleteListener {
observer.onComplete()
// If we are at this point we don't need the previous listener
databaseRef.removeEventListener(valueEvent)
}
.addOnFailureListener { e ->
if (!observer.isDisposed) {
observer.onError(e)
}
databaseRef.removeEventListener(valueEvent)
}
} ?: observer.onError(FirebaseApiNotAvailableException("Cannot create new $reference Id"))
}
}
To be honest, I don't like the idea to attach two listeners very much, if somebody else has a better and elegant solution, please let me know, I have this code temporarily until I find something better.