我在我的应用中使用Firestore Beta,我想检查与Firestore数据库的在线连接是否正常。该文档说,目前还没有直接的查询连接状态的方法,但是可以使用Firebase连接状态作为一种解决方法。相应的代码段也可以在文档的这一部分中找到:Build presence in Cloud Firestore。
connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
connectionStateListener = connectedRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
Boolean connected = snapshot.getValue(Boolean.class);
if (connected == null) {
changeState(FirebaseConnectionState.error);
return;
}
if (connected) {
changeState(FirebaseConnectionState.connected);
} else {
changeState(FirebaseConnectionState.not_connected);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
L.i("FirebaseConnectionStateListener was cancelled");
}
});
ValueEventListener
本身正在工作,并且我得到了状态更新。但是由于某种原因,状态会在1分钟后从“已连接”切换为“未连接”。除了不正确之外,我无法将其恢复为“已连接”,除非重新启动应用程序。
以下是一些调试输出:
2018-11-15 13:38:20.340: [FirebaseHeartbeatConnector] FirebaseHeartbeatConnector() called with: firebaseApp = [FirebaseApp{name=development, options=FirebaseOptions{applicationId=1:xxxxx:android:xxxxx, apiKey=xxxxx, databaseUrl=null, gcmSenderId=null, storageBucket=xxxx.appspot.com, projectId=xxxxx}}]
2018-11-15 13:38:20.480: [FirebaseHeartbeatConnector] startConnecting() called
2018-11-15 13:38:20.482: [FirebaseHeartbeatConnector] doSendFirestoreHeartbeatRequest() called
2018-11-15 13:38:20.840: [FirebaseHeartbeatConnector] change State called
2018-11-15 13:38:20.840: [FirebaseHeartbeatConnector] State changed initial -> not_connected
2018-11-15 13:38:21.380: [FirebaseHeartbeatConnector] change State called
2018-11-15 13:38:21.381: [FirebaseHeartbeatConnector] State changed not_connected -> connected
2018-11-15 13:39:20.514: [FirebaseHeartbeatConnector] change State called
2018-11-15 13:39:20.515: [FirebaseHeartbeatConnector] State changed connected -> not_connected
为什么会这样,如何获得正确的状态更新?
答案 0 :(得分:2)
这可能是由于Firebase因不活动而关闭连接所致,这仅在Android上发生。从Detecting Connection State文档中:
在Android上,Firebase自动管理连接状态以减少带宽和电池消耗。如果客户端没有活动的侦听器,没有挂起的写操作或
onDisconnect
操作,并且没有通过goOffline
方法显式断开连接,则Firebase在闲置60秒后将关闭连接。
由于您的应用未真正使用实时数据库(而是使用Cloud Firestore),因此不会附加任何其他写入操作或其他侦听器,因此该连接会自动关闭。您可能会在logcat中看到类似以下的内容:
V/FA: Inactivity, disconnecting from the service
作为一种可能的解决方法,您可以尝试将侦听器附加到实时数据库中的任何节点上,以保持连接有效(即使实际上并不存在,也可以进行任何操作):
FirebaseDatabase.getInstance().getReference("keepalive").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
// Do nothing - this listener just keeps the connection alive
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Log.i("Keepalive listener was cancelled");
}
});
或者,按照Frank van Puffelen的建议,您可以通过在空引用上使用keepSynced()
来告诉Firebase保持整个实时数据库同步,从而诱使Firebase挂在连接上:
FirebaseDatabase.getInstance().getReference().keepSynced(true);
不过,当您实际上希望将用户的状态标记为已断开连接时,您需要记住删除keepalive侦听器或撤消keepSynced()
。
最后,在这两个示例中,您仍然需要附加并利用.info/connected
connection state listener来处理连接状态的更改:
对于许多与状态相关的功能,它有助于您的应用知道在线还是离线。 Firebase Realtime Database在
/.info/connected
处提供了一个特殊位置,该位置在Firebase Realtime Database客户端的连接状态每次更改时都会更新。这是一个示例:DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected"); connectedRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { boolean connected = snapshot.getValue(Boolean.class); if (connected) { System.out.println("connected"); } else { System.out.println("not connected"); } } @Override public void onCancelled(DatabaseError error) { System.err.println("Listener was cancelled"); } });