Develop
Develop
Select your platform

Media View showcase - Overview and local media handling

Updated: Sep 29, 2025

Overview

Media View is a mixed reality Quest application that shows developers how to build a spatialized media viewing app using the Spatial SDK. One of the key use cases of mixed reality on Quest is the ability to take full advantage of the space around you for content, instead of being confined to a screen or monitor. Additionally, Quest devices excel at viewing media formats that might be difficult to fully enjoy on mobile or desktop, such as panoramic or 360 content. The Media View app demonstrates the concepts and code required to visually organize media content, display various formats of content in space at the same time, and how to integrate with a cloud hosting solution to easily transfer more media content to the headset for viewing.
Additionally, new developers using the Meta Spatial SDK should explore the underlying design guidelines (covered in Cloud Integration and Design Guidelines) after reviewing this showcase. This exploration will deepen your understanding of creating immersive user experiences and expanding your app’s audience reach.

Loading and handling local media files

Loading and handling local media files
In a media viewing application, visually organizing the list of files on a device, loading local files, and displaying local media are all essential functions.
Media View provides robust media handling capabilities, leveraging the Android MediaStore for accessing, managing, and storing media files on the device. This document dives into the details of how Media View interacts with the MediaStore, detects different media types, and manages sample media assets.

MediaStore interaction

Media View uses the Android MediaStore to access and manage media files on the user’s device. The data/gallery module encapsulates the logic for MediaStore interaction, providing a clean separation of concerns.

Querying media

  • The MediaStoreQueryBuilder class constructs queries for retrieving media files based on specified filters (MediaFilter) and sort options (MediaSortBy).
  • The buildSelection method dynamically generates selection clauses for the MediaStore query, allowing for flexible filtering based on media types and other criteria.
  • The buildSortOrder method constructs the sort order clause based on the selected MediaSortBy option, allowing users to organize their media by date, size, or name.

Media type detection

  • The MediaStoreFileDto class represents a media file retrieved from the MediaStore. It includes logic to determine the type of media based on file properties like mime type, aspect ratio, dimensions, and bit rate.
  • Methods like isPanorama, isRayban, is360, and isSpatial use heuristics to categorize media files. For example, panoramas are identified based on their aspect ratio exceeding a certain threshold, while 360-degree media are detected based on a 2:1 aspect ratio.
  • Based on these detection methods, the mediaType and mediaFilter properties of MediaStoreFileDto are set, facilitating filtering and presentation in the UI.

Saving media

  • The DeviceGalleryService class handles the process of saving new media files to the device. The saveMediaFile method utilizes ContentValues to create a new entry in the MediaStore, specifying properties like display name, mime type, and relative path.
  • The method also opens a file descriptor for the new MediaStore entry, allowing data to be written to the associated file using a FileOutputStream. The IS_PENDING flag is used to indicate that the file is still being written. Once the write is complete, the flag is cleared, signifying that the file is available.

Sample media management

Media View includes sample media assets that can be saved to the user’s device, providing an initial set of content to explore. The data/user module is responsible for managing user preferences, including the tracking of whether sample media has been saved.

User preferences

  • The UserRepository class provides a centralized way to access and modify user preferences.
  • The UserPreferencesService interacts with SharedPreferences to store and retrieve preferences. The isSampleMediaSaved method checks whether the user has previously saved the sample media.

Loading sample assets

  • The PermissionViewModel handles the process of loading sample assets from the assets folder. This occurs after the user grants storage permissions.
  • Before saving assets, the code checks if a sample media folder exists from a previous installation. If found, it is deleted to avoid conflicts or duplicates.
  • The saveAssetDirectory and saveAssetFile methods recursively iterate through the sample assets in the assets folder, saving each file to the device using the DeviceGalleryService. The setSampleMediaSaved method in UserRepository is called after successful asset saving to update the user’s preference.

Code examples

MediaStore query builder (MediaStoreQueryBuilder)

fun buildSelection(filter: MediaFilter?): Pair<String?, Array<String>?> {
    return Pair(
        "${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?",
        arrayOf(
            "${MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE}",
            "${MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO}"
        ),
    ) // ... Add support for other MediaFilters
}

Media type detection (MediaStoreFileDto)

private fun isPanorama(): Boolean {
    return aspectRatio?.let { it > MediaType.panoramaAspectRatioMin } ?: false
}

Saving media (DeviceGalleryService)

suspend fun saveMediaFile(
    displayFileName: String?,
    mimeType: String?,
    relativeSubPath: String?,
    onWrite: (FileOutputStream) -> Unit
): Boolean {
    // ... ContentValues setup and MediaStore insertion
    contentResolver.openFileDescriptor(mediaUri, "w", null).use { file ->
        // ... Writing data to the FileOutputStream
    }
    // ... Update MediaStore entry to clear IS_PENDING flag
}

Checking for sample media (UserRepository)

fun isSampleMediaSaved(): Boolean {
    return userPreferencesService.isSampleMediaSaved()
}
By combining the robust capabilities of the Android MediaStore with custom logic for media type detection and sample asset management, Media View delivers a comprehensive media handling experience. This approach ensures a seamless workflow for accessing, managing, and presenting diverse media content within the immersive mixed reality environment.
Did you find this page helpful?
Thumbs up icon
Thumbs down icon