【问题标题】:Android chat app Checking online/offline users firebaseAndroid 聊天应用程序检查在线/离线用户 firebase
【发布时间】:2021-04-04 17:00:55
【问题描述】:

我正在尝试使用 .info/connected 路径在我的 android 聊天应用程序中添加在线/离线功能 我在 onCreate() 方法中编写了以下代码

studentref = FirebaseDatabase.getInstance().getReference("student").child(user.getUid());
    connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");

connectedRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            boolean connected = snapshot.getValue(Boolean.class);
            if (connected) {
                studentref.child("status").onDisconnect().setValue("offline");
                studentref.child("status").setValue("Online");
            } else {
                studentref.child("status").setValue("offline");
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
        }
    });

但是当我最小化应用程序超过 60 秒时,else 部分不会执行 它仅在我关闭应用程序或关闭互联网超过 60 秒时才有效

如何使它工作,当应用程序在前台时,它应该设置值“在线”,当应用程序在后台或被杀死时,它应该设置值“离线”

【问题讨论】:

    标签: java android firebase firebase-realtime-database


    【解决方案1】:

    我用两种方法解决了这个问题 首先,我们需要检测应用程序何时进入后台并返回前台,因此当应用程序进入前台时,将用户状态更新为“在线” 当应用程序进入后台时,将用户状态更新为“离线”

    我们可以通过实现 LifecycleObserver 类并编写以下 2 个方法来实现这一点

        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        public void onAppBackgrounded() {
            //App in background
            // here update user state as offline 
            
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        public void onAppForegrounded() {
            // App in foreground
            // here update user state as online
              
        }
    

    但这在没有网络连接的情况下不起作用,例如:当用户在前台关闭应用程序时关闭互联网并关闭应用程序时,即使应用程序关闭,用户状态仍将保持在线,解决这我们还需要检查与 .info/connected 路径的连接

    connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
            listenerCon = new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {
                    boolean connected = snapshot.getValue(Boolean.class);
                    if (connected) {
                        user= FirebaseDatabase.getInstance().getReference("users").child(FirebaseAuth.getInstance().getCurrentUser().getUid());
                        user.child("state").setValue("Online");
                        user.child("state").onDisconnect().setValue(ServerValue.TIMESTAMP);
                    }
                }
    
                @Override
                public void onCancelled(@NonNull DatabaseError error) {
    
                }
            };
            connectedRef.addValueEventListener(listenerCon);
    

    所以当超过 60 sc 没有连接时,用户状态将更新为离线

    【讨论】:

      【解决方案2】:

      .info/connected 反映了您的应用程序与 Firebase 实时数据库后端服务器的连接。虽然这可能与用户是否在积极使用应用程序有关,但它不是 1:1 映射。

      如果要检测应用程序是否后台,有更好的方法(与Firebase无关),例如How to detect when an Android app goes to the background and come back to the foregroundthese search results的其他方法。

      【讨论】:

      • 感谢@Frank van Puffelen,但为什么其他部分没有在我的代码中执行。我在 firebase Doc“Firebase 在 60 秒不活动后关闭连接”中读到了这个。所以 else 部分应该在 60 不活动后执行
      • 当客户端断开连接时,您正在调用studentref.child("status").setValue("offline");,这意味着它会立即重新连接。有关经过充分测试的存在系统,请参阅:firebase.google.com/docs/database/android/…
      【解决方案3】:

      在 onCreate 中使用我的代码

      FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
              String id = user.getUid();
              DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Users").child(id).child("stateOnline");
              
              if (user != null){
                  reference.setValue(true);
                  reference.onDisconnect().setValue(false);
      
                  reference.addValueEventListener(new ValueEventListener() {
                      @Override
                      public void onDataChange(DataSnapshot snapshot) {
                          boolean connected = snapshot.getValue(Boolean.class);
                          if (connected) {
                              // CONNECTED
                          } else {
                              // NOT CONNECTED
                          }
                      }
                      @Override
                      public void onCancelled(DatabaseError error) {
                          System.err.println("Listener was cancelled");
                      }
                  });
                  reference.keepSynced(true);
              }
      

      【讨论】:

        猜你喜欢
        • 2017-12-06
        • 2017-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-12
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多