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

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, the permission flow begins with MediaProjectionManager:

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

Upon user approval, the resulting Intent data propagates to ScreenRecordingService.java, where the actual MediaProjection instance is created:

@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, the implementation calls mediaProjection.createVirtualDisplay():

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.

Video Encoder Configuration

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

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:

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 and 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 for the permission flow and 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 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →