Skip to content

Keep the activity alive across configuration changes - #117

Open
iflyhere wants to merge 1 commit into
OpenIPC:masterfrom
iflyhere:fix/survive-config-changes
Open

Keep the activity alive across configuration changes#117
iflyhere wants to merge 1 commit into
OpenIPC:masterfrom
iflyhere:fix/survive-config-changes

Conversation

@iflyhere

@iflyhere iflyhere commented Aug 27, 2026

Copy link
Copy Markdown

Manifest only, no code changes.

The problem

VideoActivity declares no android:configChanges, so any configuration change
destroys and recreates the activity. That is not cheap here: onPause() /
onStop() stop the video player, the wfb-ng adapters and the VPN service, and
onCreate() then re-runs the whole bring-up — USB open, wfb-ng start, decoder
wait for SPS/PPS. In practice a few seconds of black screen and a fresh USB
permission/enumeration cycle.

It fires more often than it looks:

  • window resize in multi-window, freeform or desktop mode
    (screenSize, smallestScreenSize, screenLayout) — this is also how the
    app is presented on Android XR headsets, where the panel is user-resizeable,
    so a nudge of the window edge drops the link mid flight
  • attaching or detaching a keyboard or a dock (keyboard, keyboardHidden,
    navigation)
  • rotation (orientation)

The change

android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation"
android:resizeableActivity="true"

Handling those in-process is enough — the layout is ConstraintLayout based and
re-measures itself, the activity keeps no configuration-dependent state, and none
of those qualifiers select alternative resources in this project (there is no
layout-land, no values-sw*dp), so no onConfigurationChanged() override is
needed. android:screenOrientation is left alone.

uiMode and density are deliberately not in the list: values-night/ and
the mipmap-*dpi buckets do depend on them, so those two still need a recreate
to pick up the right resources. Losing the link on a dark-mode switch is the
lesser evil compared to a half-themed UI.

android:resizeableActivity="true" is set explicitly rather than relying on the
target SDK default.

Plus one unrelated one-liner in the same file:

<uses-feature android:name="android.hardware.touchscreen" android:required="false" />

The implicit default is required="true", which marks the app as incompatible
with any ground station that is driven by a pointer or a gamepad instead of a
touchscreen (headsets, TV boxes, kiosk displays). Happy to split that out if you
would rather keep this PR to the config changes.


Part of a small series of independent fixes found while profiling the receive path.
Each one is standalone and mergeable on its own, in any order — no dependencies
between them, and no shared files except VideoActivity.java / VideoPlayer.*,
which touch different methods:

All five compile clean for arm64-v8a + armeabi-v7a.

VideoActivity declares no android:configChanges, so every configuration
change destroys and recreates it. onCreate() re-runs the whole bring-up and
onPause()/onStop() tear the link down first, which means a few seconds of
black screen and a fresh USB/wfb-ng/decoder init.

That fires more often than it looks:

- window resize in multi-window / freeform / desktop mode (screenSize,
  smallestScreenSize, screenLayout) - also how the app is presented on
  Android XR headsets, where the panel is user resizeable
- attaching a keyboard or a dock (keyboard, keyboardHidden, navigation)
- rotation (orientation)

Handling those in-process is enough: the layout is ConstraintLayout based
and re-measures itself, the activity keeps no configuration dependent
state, and none of those qualifiers select alternative resources in this
project, so no onConfigurationChanged() override is needed.

uiMode and density are deliberately not in the list: values-night/ and the
mipmap-*dpi buckets do depend on them, so those two still need a recreate
to pick up the right resources.

Also:
- android:resizeableActivity="true" - be explicit rather than relying on
  the target SDK default
- android.hardware.touchscreen android:required="false" - the implicit
  default is required=true, which marks the app incompatible with any
  ground station driven by a pointer or a gamepad instead of a touchscreen
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Preserve VideoActivity across configuration changes

🐞 Bug fix ⚙️ Configuration changes ✨ Enhancement 🕐 Less than 10 minutes

Grey Divider

AI Description

• Retains VideoActivity during resize, rotation, and input-device changes to preserve active links.
• Explicitly enables resizable windows across desktop, multi-window, and XR environments.
• Allows installation on pointer- or gamepad-driven devices without touchscreens.
Diagram

graph TD
  A["Configuration change"] --> B{"Manifest handled?"}
  B -->|Yes| C["Activity retained"] --> D["Link stays active"]
  B -->|No| E["Activity recreated"] --> F["Resources refreshed"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Move link ownership outside the activity
  • ➕ Survives every activity recreation, including UI mode and density changes.
  • ➕ Separates long-lived USB, video, and VPN state from the UI lifecycle.
  • ➖ Requires broad lifecycle and state-management changes.
  • ➖ Introduces more synchronization and reconnection complexity than this targeted fix.

Recommendation: Keep the manifest-based approach for this scoped fix because the handled qualifiers have no alternative resources and the layout can remeasure in place. Moving link ownership into a service or retained state holder would be more robust long term, but its complexity is disproportionate unless broader activity recreation support is required.

Files changed (1) +7 / -0

Other (1) +7 / -0
AndroidManifest.xmlRetain VideoActivity and broaden device compatibility +7/-0

Retain VideoActivity and broaden device compatibility

• Declares resize, orientation, screen-layout, keyboard, and navigation changes as handled by VideoActivity so Android does not recreate it and interrupt the active link. Explicitly enables activity resizing and makes touchscreen hardware optional for pointer- or gamepad-driven ground stations.

app/src/main/AndroidManifest.xml

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can ask Qodo to dismiss a finding you disagree with, with your reason on record

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant