0

I am building a multiplayer game in Flutter using Firestore to handle real-time updates. One of the cases I need to address is when a player fully terminates the app. In this case, Firestore should be updated to remove the player from the active party.

I'm attempting to achieve this by using a Firebase Cloud Function that listens to the player’s presence status in Firebase Realtime Database. When the player’s presence changes to {online: false}, the Cloud Function updates Firestore and removes the player from the party.

The issue I’m facing is that I’m unable to reliably change the player’s status in Firebase Realtime Database when the app is fully terminated. I have the following method that I call whenever the app’s lifecycle state changes:

 void updatePresenceOnAppState(
    AppLifecycleState state,
    String partyId,
    String playerId,
  ) {

    print(state);
    final presenceRef = _database
        .ref()
        .child('party-presence')
        .child(partyId)
        .child(playerId);


  if (state == AppLifecycleState.paused || state == AppLifecycleState.inactive) {
    presenceRef.set({'online': true, 'state': 'background'});
  } else if (state == AppLifecycleState.detached) {
    presenceRef.set({'online': false, 'state': 'terminated'});
  } else if (state == AppLifecycleState.resumed) {
    presenceRef.set({'online': true, 'state': 'active'});
  }
  }

However, AppLifecycleState.detached does not seem to reliably set the online status to false upon app termination. This results in the player’s status remaining as "online" even after the app is closed.

Is there a reliable way to detect full app termination in Flutter to update the player’s presence status in Firebase Realtime Database? Or is there a recommended approach to handle player termination events to trigger the necessary Firestore updates?

I tried using AppLifecycleState.detached to detect when the app is fully terminated. My expectation was that setting {online: false, state: 'terminated'} in Firebase Realtime Database within AppLifecycleState.detached would reliably mark the player as offline, which would then trigger my Cloud Function to remove the player from the party in Firestore.

What actually happened:

Instead, AppLifecycleState.detached doesn’t seem to update the Firebase Realtime Database consistently when the app is terminated, leaving the player's status as "online" even after they close the app. This means the Cloud Function doesn’t run, and the player isn’t removed from the party as expected.

1 Answer 1

0

I’m unable to reliably change the player’s status in Firebase Realtime Database when the app is fully terminated

That is expected. There is no guaranteed way to run code inside your application when that app terminates. A simple example of why this isn't possible is when the app crashes: as there's no way for your code to still run when that happens.


The solution for this is to use Firebase Realtime Database's built-in connection detection mechanism. This uses a combination of client-side and server-side code to detect when a client disconnects. The documentation even has an example of a complete, battle-tested presence system.

If you implement this in your app, the write/delete operation that happens when the client has disconnected will be executed on the server and then from there also be reflected in your Firestore database.

2
  • Thank you Frank for your answer, but the onDisconnect method, which is triggered when the connection between Firebase and the client is lost, activates when the app enters the background state. However, I only need it to trigger when the app is terminated. The connection should remain active when the app is running in the background. Commented Nov 12, 2024 at 9:43
  • The onDisconnect triggers when the connection is lost, which may happen when the app is backgrounded (depending on the OS/version) and the OS closes the web socket to save battery. There is no mechanism that does directly what you want, so if onDisconnect isn't close enough, you'll have to come up with somehting yourself. E.g. you could think of a heartbeat message: en.wikipedia.org/wiki/Heartbeat_(computing) Commented Nov 12, 2024 at 14:07

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.