Skip to content

✨ Separate MediaProjection consent from recording to support deferred recording on Android 14+ #22

@ananjaemin

Description

@ananjaemin

Feature Description

Current behavior

On Android 14+ (API 34), the system requires fresh user consent for every MediaProjection capture session. The current implementation couples consent and recording into a single flow — calling startGlobalRecording() shows the system dialog and immediately begins recording. This means the consent popup must appear at the exact moment recording starts, making it impossible to request consent on one screen and record on another.

Why this is a problem

Apps that need to guide users through a setup flow before recording (e.g., onboarding → specific screen → start recording) are forced to interrupt the user with a system popup right when recording begins. There's no way to "pre-authorize" the session and start recording later at the right moment.

Proposed solution

Android 14 prohibits reusing the cached Intent for getMediaProjection() and calling createVirtualDisplay() more than once on the same MediaProjection instance. However, it does allow calling VirtualDisplay.setSurface() to swap the target surface — this is even documented as the official approach for handling configuration changes.

We can leverage this by separating the flow into two phases:

  1. Consent phase — Show the system dialog, start a foreground service, obtain MediaProjection, and create a VirtualDisplay with a null surface. The session is alive but nothing is being recorded. With a null surface, SurfaceFlinger skips frame delivery entirely, so there is zero performance overhead.
  2. Recording phase — Create a MediaRecorder, attach its surface via setSurface(), and start recording. When done, detach the surface (back to null). The session remains alive for subsequent recordings without re-prompting.

Or is there a specific reason why you chose the current flow?

Proposed API (optional)

Confirmation

  • I searched for similar feature requests and found none

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions