# FadCam Background Recording: Complete Android Implementation Guide with Code Examples

> Learn how to implement FadCam background recording. Discover code examples for this Android foreground service that writes camera frames to disk even when the UI is hidden. Get the complete guide.

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

---

**FadCam records video in the background by running a foreground Android Service that maintains the encoder EGL surface while releasing preview resources, using GLWatermarkRenderer.renderToEncoder() to continuously write camera frames to disk even when the UI is not visible.**

FadCam is an open-source Android camera application that supports continuous video recording even when the app is minimized or the device screen is locked. This guide provides production-ready code examples for implementing the FadCam background recording feature, detailing the foreground service architecture, OpenGL pipeline management, and EGL surface handling that enable seamless background capture.

## Understanding the Background Recording Architecture

FadCam’s background recording relies on a **foreground Service** that outlives the Activity lifecycle. The architecture separates preview rendering from encoder rendering, allowing the camera to continue capturing frames even when the app’s UI surface is destroyed.

### RecordingService as the Foreground Orchestrator

The **RecordingService** class runs as a foreground Android Service, displaying a persistent notification to prevent the system from killing the process when the app moves to the background. Located in [`app/src/main/java/com/fadcam/services/RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/services/RecordingService.java), this service owns the camera instance and coordinates with the OpenGL pipeline to manage EGL contexts.

When the service receives background/foreground intents, it selectively releases or reinitializes only the preview EGL resources while keeping the encoder surface alive. This separation is crucial—releasing the encoder surface would stop recording, while releasing only the preview surface allows background operation to continue.

### GLRecordingPipeline and EGL Resource Management

The **GLRecordingPipeline** ([`app/src/main/java/com/fadcam/opengl/GLRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/opengl/GLRecordingPipeline.java)) manages two distinct EGL surfaces: one for the camera preview displayed in the UI, and one for the video encoder that writes to the output file. When the app backgrounds, the pipeline calls **releasePreviewResources()** to destroy the preview surface and context, but preserves the encoder EGL surface and its associated OpenGL context.

The **GLWatermarkRenderer** ([`app/src/main/java/com/fadcam/opengl/GLWatermarkRenderer.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/opengl/GLWatermarkRenderer.java)) handles the actual frame drawing. Its **renderToEncoder()** method draws incoming camera frames directly to the encoder surface, bypassing the preview surface entirely when the app is not visible.

## Implementing Background Recording

### Starting a Recording That Survives Backgrounding

To begin recording that persists when the user leaves the app, start the foreground service with the appropriate action intent. This example from `RecordingControlIntents` initializes the service with torch state settings:

```java
Intent start = new Intent(this, RecordingService.class);
start.setAction(RecordingControlIntents.ACTION_START_RECORDING);
start.putExtra(Constants.INTENT_EXTRA_INITIAL_TORCH_STATE, false);
ContextCompat.startForegroundService(this, start);

```

The service immediately promotes itself to foreground status using `startForeground()`, which displays a notification and grants the process higher memory priority. This prevents Android's low-memory killer from terminating your recording session when the app is no longer in the foreground.

### Handling ACTION_APP_BACKGROUND Events

When the user navigates away from the app, send the background action intent to signal the service to release preview resources. In [`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java) (lines 107-119), the `onStartCommand()` method handles **ACTION_APP_BACKGROUND** by releasing only the preview EGL surface:

```java
Intent background = new Intent(this, RecordingService.class);
background.setAction(RecordingControlIntents.ACTION_APP_BACKGROUND);
startService(background);

```

Inside `RecordingService`, this intent triggers the resource release:

```java
if (glRecordingPipeline != null) {
    glRecordingPipeline.releasePreviewResources(); // releases preview EGL only
}

```

This call destroys the SurfaceTexture and EGLSurface used for the camera preview, freeing GPU memory while maintaining the encoder EGL context that writes to the MP4 file.

### Rendering Frames to the Encoder Surface

While backgrounded, frames must be drawn exclusively to the encoder surface. The **GLWatermarkRenderer.renderToEncoder()** method handles this by executing the OpenGL draw loop without attaching to any preview framebuffer:

```java
/**
 * Renders only to the encoder surface for recording.
 * This method should be used for background recording when the app is not
 * visible.
 */
public void renderToEncoder() {
    renderToEncoderInternal(false);
}

```

In the camera frame callback, `RecordingService` routes frames through the pipeline:

```java
// In RecordingService, when a new camera frame arrives:
glRecordingPipeline.getRenderer().renderToEncoder();   // → GLWatermarkRenderer.renderToEncoder()

```

Because the preview EGL surface has been released, the GL pipeline only draws to the encoder surface, ensuring the video file continues growing even though the Activity’s SurfaceView or TextureView is no longer available.

### Restoring Preview When Returning to Foreground

When the user reopens the app, restore the preview surface by sending the foreground action intent. In [`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java) (lines 175-183), the **ACTION_APP_FOREGROUND** intent triggers **reinitializePreviewIfNeeded()**:

```java
Intent foreground = new Intent(this, RecordingService.class);
foreground.setAction(RecordingControlIntents.ACTION_APP_FOREGROUND);
startService(foreground);

```

The service then reinitializes the preview EGL resources:

```java
if (glRecordingPipeline != null) {
    glRecordingPipeline.reinitializePreviewIfNeeded();
}

```

This recreates the preview EGL surface and reattaches the camera preview output, allowing the user to see the camera feed again while recording continues uninterrupted.

## Key Source Files and Method Reference

The complete background recording implementation spans four primary files in the FadCam repository:

| File | Purpose | Key Methods |
|------|---------|-------------|
| **[`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java)** | Foreground service orchestrating camera and lifecycle | `onStartCommand()`, handles `ACTION_APP_BACKGROUND` (lines 107-119) and `ACTION_APP_FOREGROUND` (lines 175-183) |
| **[`GLRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/GLRecordingPipeline.java)** | EGL context and surface management | `releasePreviewResources()`, `reinitializePreviewIfNeeded()` |
| **[`GLWatermarkRenderer.java`](https://github.com/anonfaded/FadCam/blob/main/GLWatermarkRenderer.java)** | OpenGL rendering to surfaces | `renderToEncoder()` |
| **[`RecordingControlIntents.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingControlIntents.java)** | Action constant definitions | `ACTION_APP_BACKGROUND`, `ACTION_APP_FOREGROUND`, `ACTION_START_RECORDING` |

All paths reside under `app/src/main/java/com/fadcam/` with the exact package structure detailed above.

## Summary

- **FadCam background recording** requires a foreground Service to prevent Android from killing the process when the UI is hidden.
- The **GLRecordingPipeline** maintains separate EGL surfaces for preview and encoding, allowing release of the preview surface via **releasePreviewResources()** while recording continues.
- **GLWatermarkRenderer.renderToEncoder()** writes frames directly to the video encoder surface, bypassing the preview when the app is backgrounded.
- Use **RecordingControlIntents.ACTION_APP_BACKGROUND** and **ACTION_APP_FOREGROUND** to signal state changes to the **RecordingService**.
- Reinitialize the preview surface with **reinitializePreviewIfNeeded()** when the user returns to the app to restore the camera view.

## Frequently Asked Questions

### How does FadCam prevent Android from killing the recording when the app is backgrounded?

FadCam runs **RecordingService** as a foreground service using `startForeground()`, which displays a persistent notification and grants the service higher priority in Android’s process ranking. According to the source code in [`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java), this status prevents the system from terminating the camera recording process even when the Activity is destroyed or the user switches applications.

### What is the difference between the preview surface and encoder surface in FadCam?

The **preview surface** renders camera frames to the visible UI for user feedback, while the **encoder surface** receives frames for hardware-accelerated video compression and file writing. As implemented in [`GLRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/GLRecordingPipeline.java), the preview surface can be released via **releasePreviewResources()** to save GPU memory when the app is hidden, but the encoder surface must remain active to continue writing the video file. The **renderToEncoder()** method specifically targets only the encoder surface during background recording.

### Why does FadCam use OpenGL for background recording instead of the standard Camera2 API?

FadCam uses an **OpenGL ES pipeline** through **GLRecordingPipeline** and **GLWatermarkRenderer** to support real-time watermarking and hardware-accelerated color space conversion. The OpenGL approach allows the app to render to multiple surfaces (preview and encoder) simultaneously from a single camera frame, and provides the fine-grained control necessary to release just the preview EGL context while keeping the encoder context alive when backgrounding the application.

### Can I adapt FadCam's background recording implementation for my own Android app?

Yes, the FadCam background recording pattern is reusable in any Android project requiring camera capture without a visible preview. You must implement a **foreground Service** that manages the camera session lifecycle, separate your preview and encoder EGL contexts as shown in [`GLRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/GLRecordingPipeline.java), and handle **ACTION_APP_BACKGROUND** events to release preview resources while maintaining the MediaCodec encoder surface. Ensure your app declares the `FOREGROUND_SERVICE` permission and handles runtime permissions for camera and microphone access.