Android - База данных Firestore / Firebase Realtime ".info / connected" возвращает неверное состояние соединения - PullRequest
0 голосов
/ 15 ноября 2018

Я использую бета-версию Firestore в своем приложении и хочу проверить, есть ли работающее онлайн-соединение с базой данных Firestore. В документации говорится, что в настоящее время нет прямого способа запроса состояния соединения, но можно использовать состояние соединения Firebase в качестве обходного пути. Фрагмент кода для этого также можно найти в этой части документации: Создать присутствие в 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 голосов
/ 15 ноября 2018

Это может быть вызвано тем, что Firebase закрывает соединение из-за неактивности, что происходит только на Android.Из документации Обнаружение состояния соединения :

На 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");
    }
});

В качестве альтернативы, как предлагает Фрэнк ван Пуффелен , вы можете обмануть Firebase, повесив его на соединение, сказавэто позволяет синхронизировать всю базу данных реального времени, используя keepSynced() на пустой ссылке:

FirebaseDatabase.getInstance().getReference().keepSynced(true);

Вам нужно будет не забыть удалить обработчик keepalive или отменить keepSynced(), когдавы на самом деле хотите отметить присутствие пользователя как отключенное.

Наконец, в обоих этих примерах вам все еще нужно подключить и использовать .info/connected слушатель состояния соединения дляобрабатывать изменения в состоянии соединения:

Для многих функций, связанных с присутствием, вашему приложению полезно знать, когда оно подключено к сети или отключено.База данных Firebase Realtime предоставляет специальное местоположение в /.info/connected, которое обновляется каждый раз, когда изменяется состояние подключения клиента базы данных Firebase Realtime.Вот пример:

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");
  }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...