0

I am trying to add online/offline feature in my android chat app using .info/connected path I wrote the following code inside onCreate() method

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) {
        }
    });

But the else part does not execute when i minimized the app for more than 60 seconds It only works when i killed the app or when i switch off the internet for more than 60 seconds

How to make it works , when the app is in foreground it should set the value "online" and when the app is in background or killed it should set the value to "offline"

3 Answers3

1

I solved this issue using 2 ways First we need to detect when the app goes to the background and come back to the foreground , so when the app goes to foreground update the user state as "Online" when the app goes to background update the user state as "Offline"

We can achieve this by implementing LifecycleObserver class and writing the following 2 methods

    @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
          
    }

But this will not work when there is no internet connection , Eg: when the user switch off the internet while the app in foreground and close the app in this case the user state will remain online even the app is closed , To solve this we need also to check the connection to .info/connected path

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);

So when there is no connection for more than 60 sc the user state will be updated to offline

0

The .info/connected reflects the connection of your application to the backend servers of the Firebase Realtime Database. While this may have some relation to whether the user is actively using the app, it is not a 1:1 mapping.

If you want to detect whether the app is backgrounded, there are better ways (unrelated to Firebase) such as How to detect when an Android app goes to the background and come back to the foreground and others from these search results.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks @Frank van Puffelen but why else part did not execute in my code . I read this in firebase Doc "Firebase closes the connection after 60 seconds of inactivity." so the else part should be executed after 60 of inactivity – Ahmed Basalib Jan 30 '21 at 17:54
  • You're calling `studentref.child("status").setValue("offline");` when the client disconnect, which means it immediately reconnect. For a well-tested presence system, see: https://firebase.google.com/docs/database/android/offline-capabilities#section-sample – Frank van Puffelen Jan 30 '21 at 21:14
0

Use my code, in 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);
        }
BartGraphics.
  • 63
  • 1
  • 9