# FadCam Android APIs for Background Screen Recording: A Complete Technical Guide

> Learn how FadCam uses Android MediaProjection API, VirtualDisplay, and MediaCodec for background screen recording. Explore this technical guide for full details.

- Repository: [Faded/FadCam](https://github.com/anonfaded/FadCam)
- Tags: how-to-guide
- Published: 2026-05-13

---

**FadCam captures device screens in the background using the MediaProjection API, VirtualDisplay, and MediaCodec encoders, orchestrated through a foreground Service with OpenGL-based watermark rendering.**

FadCam is an open-source Android screen recording application that demonstrates advanced implementation of low-level media APIs. This article examines the specific Android APIs for background screen recording utilized in the `anonfaded/FadCam` repository, analyzing how the app maintains capture sessions while backgrounded through precise API orchestration.

## MediaProjection API: The Foundation of Screen Capture

The **MediaProjection API** serves as the entry point for FadCam's recording capability. This system service grants applications the ability to capture screen contents or record system audio through user-consented tokens.

In [`MediaProjectionHelper.java`](https://github.com/anonfaded/FadCam/blob/main/MediaProjectionHelper.java), the permission flow begins with `MediaProjectionManager`:

```java
Intent captureIntent = mediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, REQUEST_CODE_SCREEN_CAPTURE);

```

Upon user approval, the resulting `Intent` data propagates to [`ScreenRecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/ScreenRecordingService.java), where the actual `MediaProjection` instance is created:

```java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE_SCREEN_CAPTURE) {
        Intent startIntent = new Intent(this, ScreenRecordingService.class);
        startIntent.setAction(Constants.INTENT_ACTION_START_SCREEN_RECORDING);
        startIntent.putExtra("resultCode", resultCode);
        startIntent.putExtra("permissionData", data);
        ContextCompat.startForegroundService(this, startIntent);
    }
}

```

The `MediaProjection` object persists throughout the recording session, enabling continuous frame capture even when the app enters the background.

## VirtualDisplay: Bridging Screen Content to Encoders

Once permission is granted, FadCam creates a **VirtualDisplay** to project the physical screen contents into a renderable surface. This Android API creates a virtual display whose buffers are rendered to a `Surface` provided by the application.

In [`ScreenRecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/ScreenRecordingService.java), the implementation calls `mediaProjection.createVirtualDisplay()`:

```java
virtualDisplay = mediaProjection.createVirtualDisplay(
    "ScreenRecording",
    screenWidth,
    screenHeight,
    screenDensity,
    DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
    encoderInputSurface,   // Surface from MediaCodec
    null,
    null);

```

FadCam maintains two virtual displays: one for preview-only mode and another for the full recording pipeline. The `encoderInputSurface` parameter connects directly to the video encoder, creating a zero-copy pipeline from screen to compressed video.

## MediaCodec: Video and Audio Encoding Pipeline

The **MediaCodec API** handles hardware-accelerated encoding of both video and audio streams. FadCam implements separate encoder instances for video and audio processing within [`ScreenRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/ScreenRecordingPipeline.java).

### Video Encoder Configuration

The video encoder utilizes `MediaCodec.createEncoderByType()` with AVC or HEVC formats:

```java
MediaFormat format = MediaFormat.createVideoFormat(
        MediaFormat.MIMETYPE_VIDEO_AVC, // or HEVC depending on device
        videoWidth,
        videoHeight);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
        MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, targetBitrate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, fps);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);

MediaCodec videoEncoder = MediaCodec.createEncoderByType(
        MediaFormat.MIMETYPE_VIDEO_AVC);
videoEncoder.configure(format, null, null,
        MediaCodec.CONFIGURE_FLAG_ENCODE);
Surface inputSurface = videoEncoder.createInputSurface();
videoEncoder.start();

```

The `COLOR_FormatSurface` configuration allows the encoder to consume buffers directly from the VirtualDisplay without intermediate memory copies.

### Audio Capture and Encoding

For audio, FadCam supports both microphone and internal audio sources, selected via `SharedPreferencesManager`. The audio pipeline uses `AudioRecord` to capture PCM data, feeding it into a separate `MediaCodec` instance configured for AAC encoding. The `ScreenRecordingPipeline.Builder` wires both encoders into a unified output stream.

## OpenGL Watermark Rendering Pipeline

Before frames reach the video encoder, FadCam processes them through **GLWatermarkRenderer** to overlay timestamps or custom watermarks. This OpenGL ES pipeline intercepts the surface stream between the VirtualDisplay and MediaCodec.

The rendering flow follows this path: VirtualDisplay → Surface → `GLRecordingPipeline` → Watermark overlay → Encoder input surface. This architecture allows real-time compositing without breaking the background recording session.

## Foreground Service Architecture for Background Execution

To maintain recording while the app is not in the foreground, FadCam implements `ScreenRecordingService` as a **foreground Service**. This Android API component requires a persistent notification to keep the process alive under Doze mode and app standby restrictions.

The service initialization follows this pattern in [`ScreenRecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/ScreenRecordingService.java):

```java
ScreenRecordingPipeline.Builder builder = new ScreenRecordingPipeline.Builder(this)
        .setScreenDimensions(screenWidth, screenHeight, screenDensity)
        .setVideoConfig(fps, bitrate)
        .setEnableAudio(enableAudio)
        .setMediaProjection(mediaProjection)
        .setWatermarkInfoProvider(createWatermarkInfoProvider());

if (safRecordingPfd != null) {
    builder.setOutputFileDescriptor(safRecordingPfd.getFileDescriptor());
} else {
    builder.setOutputFile(outputFile.getAbsolutePath());
}
recordingPipeline = builder.build();
recordingPipeline.startRecording();

```

The `startForeground()` method pairs with `NotificationChannel` and `NotificationCompat` APIs to display a persistent recording indicator, satisfying Android's background execution requirements while maintaining the MediaProjection session.

## Summary

- **MediaProjection API** (`MediaProjectionManager`, `MediaProjection`) provides the permission token and capture mechanism for screen contents in [`MediaProjectionHelper.java`](https://github.com/anonfaded/FadCam/blob/main/MediaProjectionHelper.java) and [`ScreenRecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/ScreenRecordingService.java).
- **VirtualDisplay** creates a virtual screen buffer rendered to the encoder's input surface, configured in `ScreenRecordingService.refreshPreviewOnlyVirtualDisplay()`.
- **MediaCodec** encoders (video and audio) compress raw frames and PCM audio into MP4 containers, built via `ScreenRecordingPipeline.Builder`.
- **OpenGL ES** pipeline (`GLWatermarkRenderer`, `GLRecordingPipeline`) composites watermarks onto frames before encoding.
- **Foreground Service** (`ScreenRecordingService` with `startForeground`) maintains the recording session during background operation using notification APIs.

## Frequently Asked Questions

### What specific Android API does FadCam use to capture the screen?

FadCam uses the **MediaProjection API**, specifically `MediaProjectionManager` to request permission and `MediaProjection` to create the capture token. This API is implemented in [`MediaProjectionHelper.java`](https://github.com/anonfaded/FadCam/blob/main/MediaProjectionHelper.java) for the permission flow and [`ScreenRecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/ScreenRecordingService.java) for session management.

### How does FadCam record audio during screen recording?

FadCam utilizes **MediaCodec** for audio encoding alongside `AudioRecord` for PCM capture. The audio source (microphone or internal audio) is selected through `SharedPreferencesManager`, and the audio encoder is configured in [`ScreenRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/ScreenRecordingPipeline.java) to mux with the video stream.

### Why does FadCam require a foreground service for background recording?

Android mandates **foreground services** for ongoing operations like screen capture to prevent process termination. FadCam's `ScreenRecordingService` calls `startForeground()` with a notification channel, ensuring the MediaProjection session remains active when the user switches apps or locks the device.

### How does FadCam add watermarks to recordings without performance impact?

FadCam implements an **OpenGL ES** pipeline through `GLWatermarkRenderer` and [`GLRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/GLRecordingPipeline.java). This GPU-accelerated approach composites watermarks onto the VirtualDisplay surface before frames reach the MediaCodec encoder, maintaining real-time performance without CPU-intensive bitmap operations.