My project is to identify whether the client is online or offline. I use the code made available in the Android-Firebase documentation, which uses an EventListener in ".info / connected".
// since I can connect from multiple devices, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
final FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myConnectionsRef = database.getReference("users/joe/connections");
// stores the timestamp of my last disconnect (the last time I was seen online)
final DatabaseReference lastOnlineRef = database.getReference("/users/joe/lastOnline");
final DatabaseReference connectedRef = database.getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
DatabaseReference con = myConnectionsRef.push();
// when this device disconnects, remove it
con.onDisconnect().removeValue();
// when I disconnect, update the last time I was seen online
lastOnlineRef.onDisconnect().setValue(ServerValue.TIMESTAMP);
// add this device to my connections list
// this value could contain info about the device or a timestamp too
con.setValue(Boolean.TRUE);
}
}
@Override
public void onCancelled(DatabaseError error) {
System.err.println("Listener was cancelled at .info/connected");
}
});
This method correctly identifies when the user terminates or reopens the application or when minor disconnections occur on the internet. However, I did a test turn off the Wifi of the device for a time of 2 minutes, it is identified in the Firebase Database that is not connected, but when I turn on the Wifi, resuming the internet connection, Firebase does not recognize the active connection, appears as if the user still remained inactive.
This code snippet was inserted into the onCreate method of my MainActivity.
Can anyone tell me why this occurs?
EDIT: Attachments
Error log:
11-14 10:12:55.272 27901-27926/com.example.davi.projetofirebase D/PersistentConnection: pc_0 - Trying to fetch auth token
11-14 10:12:55.276 27901-27926/com.example.davi.projetofirebase D/PersistentConnection: pc_0 - Successfully fetched token, opening connection
11-14 10:12:55.281 27901-27926/com.example.davi.projetofirebase D/Connection: conn_14 - Opening a connection
11-14 10:12:55.293 27901-27926/com.example.davi.projetofirebase D/WebSocket: ws_14 - WebSocket error. bkx: unknown host: s-usc1c-nss-208.firebaseio.com at bku.d(:com.google.android.gms.DynamiteModulesC@11746448:102) at bkv.run(:com.google.android.gms.DynamiteModulesC@11746448:4) at java.lang.Thread.run(Thread.java:760) Caused by: java.net.UnknownHostException: s-usc1c-nss-208.firebaseio.com at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:174) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:356) at java.net.Socket.connect(Socket.java:586) at com.android.org.conscrypt.OpenSSLSocketImpl.connect(OpenSSLSocketImpl.java:265) at com.android.org.conscrypt.OpenSSLSocketImpl.connect(OpenSSLSocketImpl.java:252) at java.net.Socket.(Socket.java:427) at java.net.Socket.(Socket.java:210) at javax.net.ssl.SSLSocket.(SSLSocket.java:906) at com.android.org.conscrypt.OpenSSLSocketImpl.(OpenSSLSocketImpl.java:192) at com.android.org.conscrypt.OpenSSLSocketFactoryImpl.createSocket(OpenSSLSocketFactoryImpl.java:68) at bku.d(:com.google.android.gms.DynamiteModulesC@11746448:94) at bkv.run(:com.google.android.gms.DynamiteModulesC@11746448:4) at java.lang.Thread.run(Thread.java:760)
11-14 10:12:55.294 27901-27926/com.example.davi.projetofirebase D/WebSocket: ws_14 - closing itself
11-14 10:12:55.295 27901-27926/com.example.davi.projetofirebase D/Connection: conn_14 - Realtime connection failed
11-14 10:12:55.295 27901-27926/com.example.davi.projetofirebase D/Connection: conn_14 - closing realtime connection
11-14 10:12:55.295 27901-27926/com.example.davi.projetofirebase D/PersistentConnection: pc_0 - Got on disconnect due to OTHER
11-14 10:12:55.296 27901-27926/com.example.davi.projetofirebase D/PersistentConnection: pc_0 - Scheduling connection attempt
11-14 10:12:55.297 27901-27926/com.example.davi.projetofirebase D/ConnectionRetryHelper: Scheduling retry in 27403ms
11-14 10:12:55.304 27901-27926/com.example.davi.projetofirebase D/WebSocket: ws_14 - closed
11-14 10:13:02.947 27901-27926/com.example.davi.projetofirebase D/PersistentConnection: pc_0 - Connection interrupted for: connection_idle
11-14 10:13:02.960 27901-27926/com.example.davi.projetofirebase D/ConnectionRetryHelper: Cancelling existing retry attempt
getKey() returns the key (last part of the path) of the location of the Snapshot. getReference() returns the Reference for the location that generated this Snapshot. getValue() returns the data contained in this Snapshot. hasChild() returns true if the specified child path has (non-null) data.
Note: Offline persistence is supported only in Android, Apple, and web apps. To use offline persistence, you don't need to make any changes to the code that you use to access Cloud Firestore data.
You can use hasChildren() to determine if a DataSnapshot has any children. If it does, you can enumerate them using forEach() . If it doesn't, then either this snapshot contains a primitive value (which can be retrieved with val() ) or it is empty (in which case, val() will return null ).
Queries with limited sorting and filtering functionality can be performed with the firebase database. Cloud firestore assures automatic scaling and can handle 1 million concurrent connections and 10,000 writes/second.
I contacted the support team Firebase, they informed me a solution that apparently solved my problem:
Apparently the listener for .info / connected stops listening if there is no active action or listener for the database. I added another helper listener to any one node in my database, and it worked!
DatabaseReference myConnectionRef2 = database.getReference("/users/joe/lastOnline");
myConnectionRef2.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
System.out.println("FIREBASE: Aux connected");
} else {
System.out.println("FIREBASE: Aux not connected");
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
Every time I lose the network connection, the two listeners try to resume communication until the network is reconnected.
Thanks to everyone who helped me solve this problem.
As Franks says, if you enable debug logging
for the client, will be able for sure to see the state of the connection, whether the client is reestablishing its connection or not.
public synchronized void setLogLevel (Logger.Level logLevel)
By default, this is set to INFO. This includes any internal errors (ERROR) and any security debug messages (INFO) that the client receives. Set to DEBUG to turn on the diagnostic logging, and NONE to disable all logging.
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