Skip to content

feat: let a fresh js context resync with an ongoing native recording - #1235

Closed
mdydek wants to merge 14 commits into
feat/android-fgs-survive-task-removalfrom
feat/android-fgs-survive-task-removal2
Closed

feat: let a fresh js context resync with an ongoing native recording#1235
mdydek wants to merge 14 commits into
feat/android-fgs-survive-task-removalfrom
feat/android-fgs-survive-task-removal2

Conversation

@mdydek

@mdydek mdydek commented Aug 17, 2026

Copy link
Copy Markdown
Member

With stopWithTask=false a recording outlives the app UI, but a remounted screen (or relaunched app) had no way to learn about it — recorder state was only reachable through the instance that started it:

  • new JSI globals backed by ActiveRecorderHandle, surfaced as statics: AudioRecorder.isRecordingOngoing() and the consume-once AudioRecorder.takeLastRecordingResult() for files finalized by the notification stop action (mock parity + jest coverage included)
  • Record demo mounts directly in the live recorder's state, picks up natively stopped files, keeps the recording alive across screen exits and only enables file output when no session is ongoing (re-enabling mid-recording replaces the writer and resets the duration)
  • deep-link routing for the notification tap (react-navigation linking), duration displays seeded from the recorder instead of assuming a fresh session, and RecordingTime rewritten to plain state — the animated-prop binding went stale on the frozen value while paused and showed zeros

Closes #

⚠️ Breaking changes ⚠️

Introduced changes

Checklist

  • Linked relevant issue
  • Updated relevant documentation
  • Added/Conducted relevant tests
  • Performed self-review of the code
  • Updated Web Audio API coverage
  • Added support for web
  • Updated old arch android spec file

michalsek and others added 4 commits August 11, 2026 12:42
The recording notification's pause, resume and stop actions now act on the
recorder natively, so they keep working after the app task is removed while
the foreground service (stopWithTask=false) keeps the recording alive:

- ActiveRecorderHandle: process-global one-slot handle to the live recorder
  (registered by AudioRecorderHostObject), with a consume-once stash of the
  file info produced by a native stop
- NativeRecorderControl: static-JNI entry points callable from Kotlin without
  a React context; the notification receiver stops/pauses/resumes through it
  on an executor and still emits the matching AudioEvent so a live app can
  sync its UI (new event: RECORDING_NOTIFICATION_STOP)
- RecordingNotification rewritten to standard NotificationCompat actions
  (RemoteViews layouts removed), rebuilt on every show(); adds stop action,
  action titles, deepLinkUri tap routing (ACTION_VIEW) and a chronometer that
  excludes paused spans; native pause/resume re-post the notification so the
  action button flips without JS
- onErrorAfterClose now restores the pre-teardown state after a stream
  reclaim instead of force-resuming a paused recording

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
With stopWithTask=false a recording outlives the app UI, but a remounted
screen (or relaunched app) had no way to learn about it — recorder state was
only reachable through the instance that started it:

- new JSI globals backed by ActiveRecorderHandle, surfaced as statics:
  AudioRecorder.isRecordingOngoing() and the consume-once
  AudioRecorder.takeLastRecordingResult() for files finalized by the
  notification stop action (mock parity + jest coverage included)
- Record demo mounts directly in the live recorder's state, picks up
  natively stopped files, keeps the recording alive across screen exits and
  only enables file output when no session is ongoing (re-enabling
  mid-recording replaces the writer and resets the duration)
- deep-link routing for the notification tap (react-navigation linking),
  duration displays seeded from the recorder instead of assuming a fresh
  session, and RecordingTime rewritten to plain state — the animated-prop
  binding went stale on the frozen value while paused and showed zeros

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown

WPT non-regression comparison

ERROR — the comparison did not produce a report; the test run itself likely failed.

Workflow run · this comment is updated on every push.

@mdydek
mdydek marked this pull request as ready for review August 20, 2026 11:38
@michalsek
michalsek force-pushed the feat/android-fgs-survive-task-removal branch from a16212c to 6dd83cf Compare August 27, 2026 19:45
@michalsek michalsek closed this Aug 27, 2026
@michalsek
michalsek deleted the feat/android-fgs-survive-task-removal2 branch August 27, 2026 19:46
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.

2 participants