0

I have a chat app in which I am currently implementing a last seen/presence system. I store the online status in the Firebase Realtime Database. If user is online then the value of this key will be a boolean true else it will be the ServerValue.TIMESTAMP when the user closed the app.

I am using addValueEventListener() to listen to the value whenever it changes. The logic here is if that value isn't a boolean then the user is offline, in which case I invoke the getTimeAgo(long time) method. The problem is that for some reason the variable lastSeen will get a null value when the app is executing normally but the moment I use the debugger to catch exactly why is it returning null it is executed properly? I have spent very long trying to fix this and ultimately gave up. Any ideas?

public static String getTimeAgo(long time) {

    final int SECOND_MILLIS = 1000;
    final int MINUTE_MILLIS = 60 * SECOND_MILLIS;
    final int HOUR_MILLIS = 60 * MINUTE_MILLIS;
    final int DAY_MILLIS = 24 * HOUR_MILLIS;

    if (time < 1000000000000L) {
        // if timestamp given in seconds, convert to millis
        time *= 1000;
    }

    long now = System.currentTimeMillis();
    if (time > now || time <= 0) {
        return null;
    }

    final long diff = now - time;
    if (diff < MINUTE_MILLIS) {
        return "just now";
    } else if (diff < 2 * MINUTE_MILLIS) {
        return "a minute ago";
    } else if (diff < 50 * MINUTE_MILLIS) {
        return diff / MINUTE_MILLIS + " minutes ago";
    } else if (diff < 90 * MINUTE_MILLIS) {
        return "an hour ago";
    } else if (diff < 24 * HOUR_MILLIS) {
        return diff / HOUR_MILLIS + " hours ago";
    } else if (diff < 48 * HOUR_MILLIS) {
        return "yesterday";
    } else {
        return diff / DAY_MILLIS + " days ago";
    }
}

FirebaseDatabase.getInstance().getReference().child("users/" + bundle.getString("uid") + "/online").addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        String lastSeen;
        if (dataSnapshot.getValue() instanceof Boolean)
            lastSeen = "online";
        else
            lastSeen = getTimeAgo((long) dataSnapshot.getValue());
        nameAndStatus.setText(TextUtils.concat(name, "\n", lastSeen));
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Toast.makeText(PersonalChat.this, "Couldn't get latest online status", Toast.LENGTH_LONG).show();
        Log.w("Personal chat", databaseError.getMessage(), databaseError.toException());
    }
});
KENdi
  • 7,576
  • 2
  • 16
  • 31
Mihir Kandoi
  • 101
  • 1
  • 10
  • Are you handling the OnDisconnect event for firebase manually? – Karan Harsh Wardhan Jun 05 '19 at 09:58
  • What do you mean manually? I am actually using two methods here. I found that onDisconnect only worked properly when I lost internet connection so what I am doing here is using OnDisconnect AND manually changing the online status when the user exits the app. – Mihir Kandoi Jun 05 '19 at 10:00
  • https://firebase.google.com/docs/reference/android/com/google/firebase/database/OnDisconnect onDisconnect "queues" up a disconnect event which you can cancel out of. you need to use the setvalue polymorph that has the priority attribute in order to tell firebase that you've disconnected - https://firebase.google.com/docs/reference/android/com/google/firebase/database/OnDisconnect.html#setValue(java.lang.Object,%20java.util.Map,%20com.google.firebase.database.DatabaseReference.CompletionListener) – Karan Harsh Wardhan Jun 05 '19 at 10:03
  • This is the code I am using for that `FirebaseDatabase.getInstance().getReference().child("users").child(FirebaseAuth.getInstance().getUid()).child("online").onDisconnect().setValue(ServerValue.TIMESTAMP);` Not sure how can this cause this problem – Mihir Kandoi Jun 05 '19 at 10:06
  • yeah so instead use the setvalue in the second link i shared-with priority and listener so you know that the disconnect has happened successfully, setvalue with just timestamp will just "queue" up and may not be pushed to firebase instantly – Karan Harsh Wardhan Jun 05 '19 at 10:07
  • I am not sure what should I pass for the `priority` argument. – Mihir Kandoi Jun 05 '19 at 10:10
  • Check **[this](https://stackoverflow.com/a/51439860/5246885)** out. – Alex Mamo Jun 05 '19 at 10:28

0 Answers0