Skip to content

Clarify or expose Android Activity lifecycle separately from AppState background #999

Description

@federicobartoli

Summary

React Native currently exposes Android AppState in a way that can make
Activity.onPause() indistinguishable from a real app background transition.

This is documented behavior today, but it can be surprising in Android system
flows such as autofill credential pickers and password managers.

Context

On Android, AppState background can be emitted when another Activity takes
focus, including temporary system activities such as autofill credential pickers.

This behavior was recently clarified in:

A related historical issue is:

Problem

For many app developers, AppState background -> active is treated as "the
user left the app and returned". Apps often use this transition to refetch data,
refresh auth state, or reset screens.

However, Android may pause the host Activity for temporary system flows where
the app is still visually part of the user flow. One concrete example is:

  1. A login screen has username/password TextInputs with Android autofill
    enabled.
  2. The user taps a saved credential from Google Password Manager / Autofill.
  3. React Native emits AppState active -> background -> active.
  4. App code listening for active refetches data and remounts the login form.
  5. Android loses the autofill target before credentials are filled.

The app can avoid this by not doing destructive work on every active event, but
the underlying API still collapses several Android lifecycle concepts into one
state.

Question / Proposal

Should React Native expose a more precise Android lifecycle signal, separate from
AppState?

Possible directions:

  • Keep AppState behavior unchanged, but expose an Android-only Activity/host
    lifecycle event such as resumed, paused, and possibly stopped.
  • Add a separate API, for example ActivityState, for apps that need Android
    Activity lifecycle semantics.
  • Reconsider whether Android AppState.background should be based on a lifecycle
    signal closer to "not visible" rather than "paused", while accounting for
    backwards compatibility.
  • Keep the current API and rely only on documentation.

The goal is not to special-case autofill or password managers. The broader issue
is that Android Activity pause and "app truly backgrounded" are different
concepts, but React Native currently exposes them through the same high-level
AppState transition.

Why this matters

A more precise signal would let apps distinguish:

  • user actually left the app;
  • temporary Android system UI / credential picker / permission flow;
  • loss of focus;
  • Activity pause without the same product meaning as a full app background.

This would help apps avoid fragile heuristics around AppState while preserving
the existing documented behavior for current users.

Contribution

If maintainers think one of these directions is appropriate, I would be happy to
help prototype and submit the implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions