Android-Firestore / Firebase实时数据库“ .info / connected”返回错误的连接状态

时间:2018-11-15 13:23:41

标签: android firebase firebase-realtime-database google-cloud-firestore

我在我的应用中使用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

为什么会这样,如何获得正确的状态更新?

1 个答案:

答案 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");
  }
});