# FadCam Cloud and Local Streaming: Complete Android Implementation Guide

> Explore FadCam cloud and local streaming code examples in RemoteFragment.java and CloudStatusManager.java. Implement real-time video streaming on Android with this comprehensive guide.

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

---

**Code examples comparing FadCam cloud and local streaming are located in [`RemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteFragment.java) for the UI mode selector and [`CloudStatusManager.java`](https://github.com/anonfaded/FadCam/blob/main/CloudStatusManager.java) for the conditional cloud service logic.**

FadCam implements a dual-mode streaming architecture that allows users to toggle between local LAN streaming and FadSec Cloud upload within the same session. The implementation cleanly separates cloud-specific services from the local HTTP server, ensuring that cloud features only activate when explicitly enabled and properly authenticated.

## Architecture Overview

FadCam uses a **dual-mode streaming architecture** where `RemoteStreamService` always runs the local HTTP server, while cloud features are conditionally enabled based on user preferences and authentication state.

| Component | Role in mode handling | Key logic |
|-----------|----------------------|-----------|
| `RemoteFragment` | UI for mode selector and toggle | Stores mode in `FadCamCloudPrefs` using `KEY_STREAMING_MODE`. Defines `MODE_LOCAL` = 0 and `MODE_CLOUD` = 1. |
| `RemoteStreamService` | Runs the local HTTP video server | Server always active; cloud uploader enabled only in cloud mode. |
| `CloudAuthManager` | Manages device linking and tokens | Gates cloud features via `isLinked()` and `hasValidToken()`. |
| `CloudStatusManager` | Pushes status and polls commands | Starts only when `isCloudModeEnabled()` and `isCloudReady()` are true. |
| `CloudStreamUploader` | Uploads video fragments to cloud | Forwards MP4 chunks to `https://fadcam.fadseclab.com/stream/<deviceId>/` when cloud mode is active. |

## Mode Selection Implementation in RemoteFragment

The [`RemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteFragment.java) file contains the primary code examples for switching between FadCam cloud and local streaming modes.

### Defining Streaming Mode Constants

In [`RemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteFragment.java) (lines 1596-1599), the application defines constants that distinguish local from cloud operation:

```java
// RemoteFragment – mode constants
private static final String KEY_STREAMING_MODE = "streaming_mode";
private static final int MODE_LOCAL = 0;
private static final int MODE_CLOUD = 1;

```

*Source:* [`app/src/main/java/com/fadcam/ui/RemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/ui/RemoteFragment.java)

### Building the Mode Selection UI

The UI construction logic (lines 1625-1655) dynamically enables the cloud option based on `canUseCloud`, which checks authentication status:

```java
ArrayList<OptionItem> items = new ArrayList<>();

// Local network option
items.add(new OptionItem(
    "mode_local",
    getString(R.string.streaming_mode_local),
    getString(R.string.streaming_mode_local_desc),
    null, null, null, null, null,
    "wifi", null, null, null));

// Cloud option – enabled only if the device is linked and has a token
if (canUseCloud) {
    items.add(OptionItem.withLigatureBadge(
        "mode_cloud",
        getString(R.string.streaming_mode_cloud),
        "cloud",
        getString(R.string.streaming_mode_cloud_featured),
        R.drawable.featured_badge_bg,
        false,
        getString(R.string.streaming_mode_cloud_desc)));
} else {
    items.add(OptionItem.withLigatureBadge(
        "mode_cloud",
        getString(R.string.streaming_mode_cloud),
        "cloud",
        getString(R.string.streaming_mode_cloud_featured),
        R.drawable.featured_badge_bg,
        true,
        getString(R.string.streaming_mode_link_required)));
}

```

### Handling User Selection

When the user selects a mode, `RemoteFragment` validates cloud availability before switching (lines 1677-1689):

```java
if ("mode_cloud".equals(selected)) {
    // Double‑check cloud availability before switching
    boolean cloudAvailable = cloudAuthManager.isLinked() &&
        (cloudAuthManager.hasValidToken() || cloudAuthManager.getRefreshToken() != null);
    if (!cloudAvailable) {
        Toast.makeText(requireContext(),
            R.string.streaming_mode_link_required, Toast.LENGTH_SHORT).show();
        onCloudAccountClick();   // Prompt user to link
        return;
    }
    setStreamingMode(MODE_CLOUD);
} else {
    setStreamingMode(MODE_LOCAL);
}

```

### Persisting the Selected Mode

The `setStreamingMode()` method (lines 1699-1706) saves the choice to `SharedPreferences` and notifies the streaming manager:

```java
private void setStreamingMode(int mode) {
    android.content.SharedPreferences prefs =
        requireContext().getSharedPreferences("FadCamCloudPrefs",
        Context.MODE_PRIVATE);
    prefs.edit().putInt(KEY_STREAMING_MODE, mode).apply();
    updateStreamingModeDisplay();    // Refresh UI
    RemoteStreamManager.getInstance().setStreamingMode(mode);
}

```

## Conditional Cloud Service Activation

[`CloudStatusManager.java`](https://github.com/anonfaded/FadCam/blob/main/CloudStatusManager.java) provides the implementation for conditionally starting cloud-specific services only when FadCam cloud streaming is enabled.

### Checking Cloud Mode Status

The manager verifies both mode preference and authentication state (lines 152-162):

```java
private boolean isCloudModeEnabled() {
    SharedPreferences prefs = context.getSharedPreferences(
        "FadCamCloudPrefs", Context.MODE_PRIVATE);
    int mode = prefs.getInt("streaming_mode", 0);
    return mode == 1;   // MODE_CLOUD = 1
}

private boolean isCloudReady() {
    boolean hasToken = authManager.getJwtToken() != null;
    boolean hasRefresh = authManager.getRefreshToken() != null;
    boolean hasUuid = authManager.getUserId() != null;
    boolean hasStreamToken = authManager.getStreamToken() != null;
    return ((hasToken || hasRefresh) || hasStreamToken) && hasUuid;
}

```

### Starting Cloud-Only Services

The `start()` method (lines 184-191) enforces strict preconditions before activating cloud features:

```java
public void start() {
    if (isRunning) return;
    if (!isCloudModeEnabled()) return;
    if (!isCloudReady()) return;

    // Begin periodic status pushes and command polling
    handler.post(statusRunnable);
    handler.post(commandRunnable);
    isRunning = true;
}

```

When these checks pass, `CloudStatusManager` begins periodic status pushes (`STATUS_PUSH_INTERVAL_MS`) and command polling (`COMMAND_POLL_INTERVAL_MS`), while `CloudStreamUploader` forwards video fragments to the cloud endpoint.

## Summary

- **Mode constants** (`MODE_LOCAL` = 0, `MODE_CLOUD` = 1) are defined in [`RemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteFragment.java) and persisted to `FadCamCloudPrefs` under the key `streaming_mode`.
- **UI validation** ensures `cloudAuthManager.isLinked()` and token validity are verified before allowing switches to cloud mode.
- **Service isolation** guarantees that `CloudStatusManager` and `CloudStreamUploader` only activate when `isCloudModeEnabled()` returns true and `isCloudReady()` confirms valid credentials.
- **Local server persistence** means `RemoteStreamService` runs the HTTP video server continuously, ensuring local LAN streaming remains available regardless of cloud mode state.

## Frequently Asked Questions

### Where are the mode selection constants defined in FadCam?

The constants are defined in [`RemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteFragment.java) at lines 1596-1599: `MODE_LOCAL` is set to 0 and `MODE_CLOUD` to 1, with the preference key `streaming_mode` used to persist the selection in `FadCamCloudPrefs`.

### How does FadCam prevent cloud streaming without authentication?

Before enabling cloud mode, `RemoteFragment` checks `cloudAuthManager.isLinked()` and `hasValidToken()` (or refresh token availability). Additionally, `CloudStatusManager.start()` verifies `isCloudReady()`, which requires valid JWT or stream tokens plus a device UUID.

### What happens to the local HTTP server when cloud mode is enabled?

The local HTTP server in `RemoteStreamService` continues running in both modes. Cloud mode only enables the `CloudStreamUploader` to forward fragments to `https://fadcam.fadseclab.com/stream/<deviceId>/`, while local viewers can still connect via LAN.

### Which files contain the core streaming logic for both modes?

The key files are [`RemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteFragment.java) (UI and mode persistence), [`CloudStatusManager.java`](https://github.com/anonfaded/FadCam/blob/main/CloudStatusManager.java) (conditional cloud activation), [`CloudAuthManager.java`](https://github.com/anonfaded/FadCam/blob/main/CloudAuthManager.java) (authentication gating), and [`RemoteStreamService.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteStreamService.java) (local HTTP server).