Develop

Language Pack sample overview

Updated: May 7, 2026

Overview

This sample demonstrates how to initialize the Horizon Platform SDK Language Pack service in an Android app using Kotlin, Jetpack Compose, and MVVM architecture. It shows the required service connection setup and Language Pack instantiation pattern for Meta Quest developers building localized applications.

What you will learn

  • Establishing a Horizon service connection before using Language Pack APIs
  • Instantiating the Language Pack service in a ViewModel
  • Structuring a Compose UI with state management for Platform SDK services
  • Configuring Gradle dependencies for the Horizon Platform SDK
  • Implementing basic error handling for SDK initialization

Requirements

  • Development environment: Android Studio Ladybug or later (AGP 9.0+) with JDK 11+
  • Target device: Meta Quest device with Developer Mode enabled
  • Platform SDK setup: Complete the Horizon Platform SDK setup for Kotlin before running this sample

Get started

Clone the horizon-platform-sdk-samples repository and navigate to the languagepack directory. Open the project in Android Studio. Before building, replace the APPLICATION_ID placeholder in MainActivity.kt with your app’s registered Horizon application ID from the Meta Horizon developer dashboard. Build and deploy the sample to your Quest device using the standard Android deployment workflow.

Explore the sample

The project follows a single-module structure with MVVM architecture:
FileWhat it demonstratesKey concepts
MainActivity.kt
Activity entry point with SDK connection and Compose UI rendering
HorizonServiceConnection.connect(), lifecycle scope integration
LanguagePackViewModel.kt
Business logic for service verification and UI state management
LanguagePack instantiation, StateFlow-based reactive state, coroutine-based initialization
LanguagePackViewModelTest.kt
Unit tests for UI state data class behavior
Data class default values and copy() behavior verification
gradle/libs.versions.toml
Centralized dependency versions for SDK artifacts
Version catalog management
app/build.gradle.kts
Module configuration with Compose and Platform SDK dependencies
SDK artifact declaration

Runtime behavior

On launch, the app establishes a connection to the Horizon service, then displays a single-button interface. Tapping Check Initialization verifies the Language Pack service instantiation and displays the result. A successful initialization shows “LanguagePack service initialized successfully.” in a styled card. If initialization fails, the error details appear in a separate error card. The UI uses Material 3 cards with a loading indicator while the check is in progress.

Key concepts

Service connection before SDK use

The Horizon Platform SDK requires an active service connection before instantiating any service objects. The sample calls HorizonServiceConnection.connect() in the Activity’s onCreate() method, before rendering the Compose UI:
HorizonServiceConnection.connect(
    APPLICATION_ID, applicationContext, lifecycleScope
)
See MainActivity.kt for the complete implementation.

Language Pack instantiation

The ViewModel creates a Language Pack instance using the no-argument constructor. This establishes the service reference for localization queries:
private val languagePack = LanguagePack()
See LanguagePackViewModel.kt for the verification logic.

State-driven UI updates

The sample uses a data class LanguagePackUiState with three properties: isLoading, resultMessage, and errorMessage. The ViewModel exposes this state as a StateFlow, triggering recomposition when state changes:
data class LanguagePackUiState(
    val isLoading: Boolean = false,
    val resultMessage: String? = null,
    val errorMessage: String? = null,
)

Coroutine-based initialization check

The initialization check runs on a background dispatcher within the ViewModel’s lifecycle scope. Error handling uses a try-catch block that populates the error message property on failure:
viewModelScope.launch(Dispatchers.IO) {
    try { /* check logic */ }
    catch (e: Exception) { /* update error state */ }
}

Extend the sample

  • Query available language packs: Expand LanguagePackViewModel to call Language Pack API methods that retrieve available locales or download language resources after initialization succeeds.
  • Multi-service integration: Import additional Platform SDK services (such as Asset File) alongside Language Pack in LanguagePackViewModel to demonstrate coordinated initialization patterns.
  • Instrumented tests: Add Android instrumented tests alongside the existing unit tests to verify service connection behavior on a physical Quest device.