> ## Documentation Index
> Fetch the complete documentation index at: https://docs.liv.tv/llms.txt
> Use this file to discover all available pages before exploring further.

# Android Gallery

> How to save recorded videos and captured images to the Android device gallery using the LIV Camera Kit (LCK) SDK in Unreal Engine, including the SaveVideoToGallery and SaveImageToGallery functions, progress tracking, MediaStore integration, and required permissions.

<Info>
  **Module:** LCKAndroidGallery | **Version:** 1.0 | **Platforms:** Android only
</Info>

## Overview

LCKAndroidGallery provides functions to save recorded videos and captured photos to the Android device's media gallery. Files are published through the Android MediaStore API, making them visible in the device's gallery app and accessible to other applications.

Videos are saved to `Movies/<GameName>/` and images to `Pictures/<GameName>/`, where `<GameName>` is read from your LCK project settings (falling back to the Unreal project name).

## When to Use

Use these functions after:

* A recording completes via `StopRecording()` or `StopRecordingAsync()` to save the video to the user's gallery
* A photo is captured via `TakePhoto()` to save the image to the user's gallery

<Note>
  Files saved through LCKAndroidGallery appear immediately in the device gallery app. Without this step, recorded files remain in the app's internal storage and are not visible to the user.
</Note>

## Functions

### SaveVideoToGallery

Copies a video file to the Android MediaStore and reports copy progress via a callback.

```cpp theme={null}
LCKANDROIDGALLERY_API void SaveVideoToGallery(
    const FString& VideoPath,
    TFunction<void(float)> OnProgress
);
```

| Parameter    | Type                     | Description                                                             |
| ------------ | ------------------------ | ----------------------------------------------------------------------- |
| `VideoPath`  | `const FString&`         | Absolute path to the source video file (`.mp4`)                         |
| `OnProgress` | `TFunction<void(float)>` | Callback invoked during the file copy with progress from `0.0` to `1.0` |

The video is saved to `Movies/<GameName>/<GameName>_<timestamp>.mp4` in the device's shared storage.

### SaveImageToGallery

Copies an image file to the Android MediaStore.

```cpp theme={null}
LCKANDROIDGALLERY_API void SaveImageToGallery(const FString& ImagePath);
```

| Parameter   | Type             | Description                                     |
| ----------- | ---------------- | ----------------------------------------------- |
| `ImagePath` | `const FString&` | Absolute path to the source image file (`.png`) |

The image is saved to `Pictures/<GameName>/<GameName>_<timestamp>.png` in the device's shared storage.

## Usage Examples

### Save Video After Recording

<Note>
  On Android, the encoder's `Save()` method **automatically calls `SaveVideoToGallery()`** internally. You do not need to call it manually — the video is saved to the Android MediaStore (Gallery) as part of `ReleaseEncoder(bSaveFile = true)` or `StopRecordingAsync()`. The temp file is located at `FPaths::ProjectPersistentDownloadDir() / TEXT("lck.mp4")`.
</Note>

If you need to save a video file manually (e.g., from a custom location):

```cpp theme={null}
// The temp recording file location
FString TempVideoPath = FPaths::Combine(
    FPaths::ProjectPersistentDownloadDir(), TEXT("lck.mp4"));

// Save to Android gallery with progress tracking
SaveVideoToGallery(TempVideoPath,
    [](float Progress) {
        UE_LOG(LogTemp, Log, TEXT("Gallery save progress: %.0f%%"),
            Progress * 100.0f);
    }
);
```

### Save Photo After Capture

```cpp theme={null}
// After taking a photo, save it to the gallery
// Photos are saved to the platform-specific pictures directory
if (Recorder->TakePhoto())
{
    // The photo path follows the pattern: Pictures/<GameName>/<GameName>_<timestamp>.png
    FString ImagePath = FPaths::Combine(
        FPaths::ProjectPersistentDownloadDir(), TEXT("photo.png"));
    SaveImageToGallery(ImagePath);
}
```

## Platform Notes

<Warning>
  LCKAndroidGallery is **Android only**. These functions use JNI to interact with the Android MediaStore API and will not compile on other platforms. Guard calls with platform checks if your project targets multiple platforms.
</Warning>

```cpp theme={null}
#if PLATFORM_ANDROID
    SaveVideoToGallery(VideoPath, OnProgress);
#endif
```

## Permissions

LCKAndroidGallery uses the Android MediaStore `ContentResolver` API (available on Android 10 / API 29+), which does not require runtime storage permissions for writing to shared media directories.

For devices running Android 9 (API 28) or earlier, you need:

```xml theme={null}
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
```

<Tip>
  If your project targets API 29+, no additional permissions are needed. The MediaStore API handles scoped storage access automatically.
</Tip>

## File Naming

Saved files follow the naming convention:

```
<GameName>_<YYYY-MM-DD_HH-MM-SS>.<ext>
```

The game name is resolved from your LCK project settings (`GameName` in `LCKSettings`). If not configured, the Unreal project name is used as a fallback.

## Dependencies

```csharp theme={null}
// Add to your .Build.cs
PublicDependencyModuleNames.AddRange(new string[] {
    "LCKAndroidGallery"
});
```

## Log Category

```cpp theme={null}
DECLARE_LOG_CATEGORY_EXTERN(LogLCKGallery, Log, All);
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="File does not appear in gallery">
    1. Verify the source file path exists before calling the save function
    2. Check `LogLCKGallery` for error messages
    3. Ensure the device is running Android 10+ or that `WRITE_EXTERNAL_STORAGE` permission is granted
  </Accordion>

  <Accordion title="Save fails with JNI error">
    1. Confirm you are calling from the game thread
    2. Check that the Android activity is valid and not suspended
    3. Review logcat output for Java exceptions
  </Accordion>

  <Accordion title="Progress callback not firing">
    1. Verify the `OnProgress` callback is valid (not null)
    2. The callback fires per 4KB chunk — very small files may complete in a single call
  </Accordion>
</AccordionGroup>

## See Also

<CardGroup cols={2}>
  <Card title="Recording" icon="circle-dot" href="/unreal/core-sdk/recording">
    Recording subsystem and lifecycle
  </Card>

  <Card title="Core SDK Overview" icon="cube" href="/unreal/core-sdk/overview">
    SDK architecture and modules
  </Card>
</CardGroup>
