You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测两位用户同时打开聊天?Firebase代码功能异常排查

How to Detect if Two Users Are Simultaneously Opening a Chat in Firebase Firestore

Your current approach has a critical flaw: using a single chat opened boolean field can’t track the state of two separate users. When one user sets it to true and the other interacts with the field, you end up overwriting values incorrectly, leading to the false state you’re seeing. Here’s how to fix this properly:

The Core Issue

A single boolean can only represent one state (open/closed), but you need to track each user’s individual presence in the chat. Instead of a single field, use a map to store each user’s active status independently.

Step 1: Update Your Data Structure

Replace the chat opened field with a activeUsers map. This map will have user IDs as keys and boolean values indicating whether that user has the chat open. For example:

{
  "activeUsers": {
    "userID1": true,
    "userID2": false
  }
}

Step 2: Set User State When Opening/Closing the Chat

When the current user opens the chat, set their entry in the activeUsers map to true. When they close it, set it to false:

Opening the Chat

// Call this when the user opens the chat screen
firebaseFirestore.collection(getString(R.string.app_name))
    .document("App Collections")
    .collection("Users")
    .document(contactID)
    .collection("Chats With")
    .document(userID)
    .update("activeUsers." + userID, true);

Closing the Chat

// Call this when the user closes the chat screen (e.g., onDestroy)
firebaseFirestore.collection(getString(R.string.app_name))
    .document("App Collections")
    .collection("Users")
    .document(contactID)
    .collection("Chats With")
    .document(userID)
    .update("activeUsers." + userID, false);

Step 3: Listen for Both Users’ States

Modify your snapshot listener to check if both users have their activeUsers entries set to true:

firebaseFirestore.collection(getString(R.string.app_name))
    .document("App Collections")
    .collection("Users")
    .document(contactID)
    .collection("Chats With")
    .document(userID)
    .addSnapshotListener(new EventListener<DocumentSnapshot>() {
        @Override
        public void onEvent(@Nullable DocumentSnapshot documentSnapshot, @Nullable FirebaseFirestoreException e) {
            // Handle errors or missing documents
            if (e != null || documentSnapshot == null || !documentSnapshot.exists()) {
                Log.e("ChatState", "Error fetching chat state: " + (e != null ? e.getMessage() : "No document found"));
                return;
            }

            // Get the activeUsers map (default to empty if missing)
            Map<String, Boolean> activeUsers = (Map<String, Boolean>) documentSnapshot.getOrDefault("activeUsers", new HashMap<>());
            
            // Check if both users are active
            boolean currentUserIsActive = activeUsers.getOrDefault(userID, false);
            boolean contactIsActive = activeUsers.getOrDefault(contactID, false);
            boolean bothUsersAreInChat = currentUserIsActive && contactIsActive;

            // Use the result as needed
            if (bothUsersAreInChat) {
                // Both users have the chat open - do something (e.g., show "online" indicator)
                Log.d("ChatState", "Both users are in the chat!");
            } else {
                // At least one user has closed the chat
                Log.d("ChatState", "One or both users have left the chat");
            }
        }
    });

Key Notes

  • Avoid Redundant Writes: Your original listener was writing the same value back to Firestore, which served no purpose and could cause race conditions. The updated listener only reads state, not modifies it.
  • Initialize the Document: If the Chats With document doesn’t exist yet, Firestore will automatically create it when you call update() with the activeUsers map.
  • Handle Cleanup: Make sure to set the user’s state to false when they navigate away from the chat (e.g., in onPause() or onDestroy() of your activity/fragment) to avoid false "active" statuses.

内容的提问来源于stack exchange,提问作者fsdklfm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:55:25