3

As explained in some answers:

On Android, Firebase automatically manages connection state to reduce bandwidth and battery usage. When a client has no active listeners, no pending write or onDisconnect operations, and is not explicitly disconnected by the goOffline method, Firebase closes the connection after 60 seconds of inactivity.

The problem is that after 60s, even after I go to an activity with a complete new reference, event listener, etc.. It still says it is disconnect, when in fact, it is not.

val connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected")
var connectListener : ValueEventListener? = null

fun checkConnection() {
    connectListener = connectedRef.addValueEventListener(object : ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            val connected = snapshot.getValue(Boolean::class.java)!!
            if (connected) {
                Log.d("FRAG", "CONNECTED")
            else{
                Log.d("FRAG", "DISCONNECTED")
            }
        }

        override
        fun onCancelled(error: DatabaseError) {
            System.err.println("Listener was cancelled")
        }
    })
}

override fun onDetach() {
    super.onDetach()
    if (connectListener != null){
        connectedRef.removeEventListener(connectListener)
    }
}

How can I make sure I maintain or create a new connection to Firebase? I call the checkConnection method every onAttach of a fragment and onStart of an activity.

rgoncalv
  • 5,825
  • 6
  • 34
  • 61
  • I you have an active listener on any data that is read from the server, the connection should remain open unless you've explicitly called `goOffline()` in your code. Note that `.info/connected` itself does not require reading from the server, so does not keep the connection open. This sounds a bit like an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem): I have a feeling the whole `.info/connected` and timeout are just red herrings. Can you describe what the actual root problem is? – Frank van Puffelen Mar 05 '18 at 16:39
  • @FrankvanPuffelen, I just want it to keep track of connection states. So, if I stay at a screen X, and I turn off wifi/ internet connection, screen X should show a "no internet connection" view. If I turn connection to be on again, it should fade out the "no internet connection" view. The problem relies on the point that after 60s it stops keeping track of the connection state. – rgoncalv Mar 05 '18 at 16:53
  • Let's not solely focus on the 60 second setting, since the behavior depends on multiple factors. If you turn off wifi/internet, after a while your listener on `connectedRef` should fire with a value of `false. Does that not happen? Or does it happen later than you expect? – Frank van Puffelen Mar 05 '18 at 17:33
  • Everything works fine inside 60 seconds. After that, it just disconnects and stays with a value of `false`. The strange behavior is that to solve this problem, I would remove the listener on the `onDetach` for frag and `onDestroy` activity and put it again on `onAttach`/`onStart` respectively and it would work for a while but even then sometimes it would just appears as disconnected. So, the whole problem is that when listening to the same listener, after 60 seconds it always points to disconnected (connected = `false`). When renewing the listener, sometimes it just stays at disconnected too. – rgoncalv Mar 05 '18 at 17:59
  • If you only have a listener on `.info/connected` that will **not** keep the connection to the server alive. That is by design. – Frank van Puffelen Mar 05 '18 at 19:44
  • I am using Firestore for all of my data. Doug told me that, pretty much, I could assume a connection to RTDB would mean a connection to Firestore, which I also believe to be so, and is the very reason I am listening to `.info/connected`. Given that only listening to `.info/connected` is not sufficient, do you recommend creating a dummy node in RTDB and listening to it as well to force the connection to stay open? – rgoncalv Mar 05 '18 at 19:53
  • Cloud Firestore uses a gRPC-based protocol to talk between client and server, while the Firebase Realtime Database uses web sockets. They're in no way compatible or even comparable. Keeping an active listener on data in Firestore does not keep a connection to RTDB open. That's why the [example in the Firestore documentation](https://firebase.google.com/docs/firestore/solutions/presence#using_presence_in_realtime_database) also writes an actual data node to the realtime database. – Frank van Puffelen Mar 06 '18 at 04:50

2 Answers2

2

If you have an active listener on any data that is read from the server, the connection should remain open unless you've explicitly called goOffline() in your code. Note that .info/connected itself does not require reading from the server, so does not keep the connection open.

It seems you're using the realtime database to build an presence system on an otherwise Firestore based app. In that case: Cloud Firestore uses a gRPC-based protocol to talk between client and server, while the Firebase Realtime Database uses web sockets. They're in no way compatible or even comparable. Keeping an active listener on data in Firestore does not keep a connection to RTDB open. That's why the example in the Firestore documentation also writes an actual data node to the realtime database.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
0
Stream<Event> checkInternetConectivity() {
    Stream<Event> connectivityCheck = _firebaseDatabase.reference().child('.info/connected').onValue;
    Stream<Event> randomCheck = _firebaseDatabase.reference().child('connected').onValue;
    return Rx.combineLatest2(connectivityCheck, randomCheck,(connectivityCheck, _) => connectivityCheck as Event);}
}

Firebase automatically disconnects from the realtime database in android after 60 seconds if there are no active listeners and listening to '.info/connected' isn't enough to keep the connection active. Creating another stream to listen to a random node in realtime database as a way around to this automatic disconnection.

This is my workaround to this problem in Dart/Flutter

Upakul
  • 21
  • 3