Develop

Application Lifecycle sample overview

Updated: May 8, 2026

Overview

This sample demonstrates the Application Lifecycle API from the Meta Horizon Platform SDK for Android. It shows how to retrieve launch details (including launch type, deeplink message, and tracking ID), log deeplink results back to the platform, and listen for launch intent changes using Kotlin Flow. View the sample source code on GitHub.

What you will learn

  • Initializing the Horizon Platform SDK service connection in an Android activity
  • Retrieving launch details using getLaunchDetails(), including launch type and deeplink information
  • Logging deeplink results back to the platform using logDeeplinkResult()
  • Monitoring launch intent changes reactively using launchIntentChanged() Flow
  • Structuring a Platform SDK app using MVVM architecture with Jetpack Compose and coroutines

Requirements

  • Meta Quest device (API level 34 or higher)
  • Android development environment with Android Studio
  • Meta Horizon Platform developer account with an application ID
For detailed setup instructions, see the Platform SDK setup guide.

Get started

Clone the Horizon Platform SDK samples repository and open the applicationlifecycle project in Android Studio. Before running the sample, replace the APPLICATION_ID property in MainActivity.kt with your application ID from the Meta Developer Portal. Build and deploy to your Quest device. For detailed build instructions and dependency setup, see the sample README.

Explore the sample

FileWhat it demonstratesKey concepts
MainActivity.kt
SDK service connection and Compose UI host
HorizonServiceConnection.connect() called in onCreate() with application ID, context, and lifecycle scope
ApplicationLifecycleViewModel.kt
Business logic and SDK API calls
Three methods demonstrating getLaunchDetails(), logDeeplinkResult(), and launchIntentChanged() Flow; all SDK calls on Dispatchers.IO
ApplicationLifecycleUiState
Immutable UI state container
StateFlow pattern with loading, result, and error states

Runtime behavior

When you run this sample, you see a single screen with the title Application Lifecycle Sample and three buttons. Tap Get Launch Details to retrieve the launch type, deeplink message, and tracking ID for the current launch. Tap Log Deeplink Result to fetch the tracking ID and log an Unknown result back to the platform. Tap Listen for Launch Intent Changed to await the next launch intent change event via the launchIntentChanged() Flow. Success results appear in a white card below the buttons; errors appear in a red error card. A loading spinner displays while SDK calls are in progress.

Key concepts

Service connection before API calls

The Platform SDK requires service connection before any API calls. The sample calls HorizonServiceConnection.connect() in onCreate() before setting up the Compose UI:
HorizonServiceConnection.connect(
    APPLICATION_ID,
    this@MainActivity.applicationContext,
    lifecycleScope,
)
See the onCreate() method in MainActivity.kt.

Direct instantiation of ApplicationLifecycle

The ApplicationLifecycle API object requires no factory or dependency injection. The ViewModel creates it directly with a no-arg constructor:
private val applicationLifecycle = ApplicationLifecycle()
Logging a deeplink result requires a tracking ID from the launch details. The sample retrieves launch details first, checks for a null tracking ID, then logs the result:
val launchDetails = applicationLifecycle.getLaunchDetails()
val trackingId = launchDetails.trackingId
if (trackingId == null) { /* update error state */ return@launch }
applicationLifecycle.logDeeplinkResult(trackingId, LaunchResult.Unknown)
Production apps would pass the appropriate LaunchResult enum value based on the actual outcome. See ApplicationLifecycleViewModel.kt.

Flow-based launch intent monitoring

Unlike getLaunchDetails(), which returns a single value, launchIntentChanged() returns a Flow for continuous monitoring. The sample uses .first() to await only the next emission, but production apps would typically collect the Flow continuously.

Extend the sample

  • Modify logDeeplinkResult() to pass different LaunchResult enum values based on your app’s actual deeplink handling logic.
  • Replace the .first() call in listenForLaunchIntentChanged() with continuous Flow collection to handle multiple launch intent changes.
  • Add logging or analytics around launch details to understand how users enter your app.