| Feature | What to do |
|---|---|
Avatar Selfie camera | Show the user’s avatar through the front camera, using CameraNDK, Camera1, Camera2, or CameraX. Select the front camera with CameraCharacteristics.LENS_FACING_FRONT or CameraSelector.LENS_FACING_FRONT. Requires either android.permission.CAMERA or horizonos.permission.AVATAR_CAMERA, which grants the avatar camera alone. The avatar camera keeps working when an organization turns off the cameras on the device. |
Passthrough camera | Read the forward-facing RGB cameras on Quest 3 and Quest 3S for computer vision and machine learning, on Horizon OS v74 or later. Built on the Camera2 API, with the com.meta.extra_metadata.camera_source and com.meta.extra_metadata.position vendor tags to identify the passthrough cameras. Requires either android.permission.CAMERA or horizonos.permission.HEADSET_CAMERA, and passthrough must be enabled. Camera image data is Device User Data under the Developer Data Use Policy. For supported resolutions, known issues, and performance characteristics, see Passthrough Camera. For working code, see the Meta Passthrough Camera API Samples. |
Back navigation | The B and Y buttons on the controllers act as the Android back button. There is no hand tracking gesture for back navigation, and users may not know about the controller buttons, so supply a back button in your app when back navigation matters. |
Input | Controllers, hands, mouse, and stylus are targeted inputs: they send standard Android motion events to your app when they hover over your panel or perform a selection action, such as a controller trigger pull or a thumb-and-index pinch. Keyboard and gamepad are untargeted: they send standard Android input events to whichever panel holds input focus. |
Joystick input | By default, joystick input scrolls scrollable Views. To handle it yourself, override the View’s onGenericMotionEvent() and read the AXIS_HSCROLL and AXIS_VSCROLL axes. Two limits apply: one controller at a time, and only while that controller’s ray hovers over your app. |
Background audio and media controls | Keep audio playing while your app is in the background, and get system media controls for play, pause, skip, and volume. Use Media3 MediaSession with a MediaSessionService foreground service and MediaStyle notifications. Request audio focus with AudioFocusRequest before playback starts: AUDIOFOCUS_GAIN for exclusive playback, or AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK to let other audio continue at reduced volume. ExoPlayer requests and abandons focus for you when you build it with setAudioAttributes(audioAttributes, /* handleAudioFocus= */ true). See Background audio playback. |
Dolby Atmos and surround audio | Horizon OS supports Dolby Digital ( audio/ac3, 2D only), Dolby Digital Plus (audio/eac3), and Dolby Atmos (audio/eac3-joc). Dolby AC-4 (audio/ac4) is not supported. Detect support by querying MediaCodecList, and prefer Atmos by setting setPreferredAudioMimeTypes on ExoPlayer’s DefaultTrackSelector. |
Default panel size | Set the size your app launches at with the <layout> element in AndroidManifest.xml, using android:defaultWidth and android:defaultHeight. |
Multi-panel activities | Run several activities at once in separate panels. Start the second activity with FLAG_ACTIVITY_LAUNCH_ADJACENT, FLAG_ACTIVITY_NEW_TASK, and FLAG_ACTIVITY_MULTIPLE_TASK. No additional SDK is needed. |
Device code sign-in | Streaming and media apps must offer device code login (RFC 8628) or another flow built for devices without a keyboard, such as QR code login or a mobile companion app. See Media app requirements. |
OAuth 2.0 sign-in | Horizon OS supports any provider that uses Private-Use URI Scheme Redirection. Implement the flow with the AppAuth for Android library, and add an intent filter with the BROWSABLE category and your app’s custom URI scheme so the system routes redirects back to your activity. |
DRM | Horizon OS supports Widevine L1 and L3 video playback. 2D apps can use the standard android.media.MediaDrm APIs for secure playback. Immersive apps can block screen capture through OpenXR APIs, or by turning off Video Recording in the Developer Dashboard under Settings > Sharing. |
Media Projection API | Capture the user’s whole view or a single panel as a media stream to play back, record, or cast. Use the android.media.projection APIs. App screen sharing (API level 34) shares one app window and excludes system UI. See MediaProjection API on Meta Quest. |
Share sheet | Register for SEND_INTENT to receive shares, which adds your app to the Horizon OS share sheet and the Android native share sheet. To share out, launch the Android native share sheet — the Horizon OS share sheet cannot be launched by third-party apps. Direct share targets appear only on the Android native sheet. |
USB networking (NCM) | Open a direct network link to a connected host computer over USB. Request the network through the standard ConnectivityManager with TRANSPORT_USB, removing the NET_CAPABILITY_INTERNET and NET_CAPABILITY_TRUSTED capabilities. Declare android.permission.CHANGE_NETWORK_STATE and android.permission.ACCESS_NETWORK_STATE in your manifest, plus android.permission.INTERNET if you open sockets over the link and android.permission.CHANGE_WIFI_MULTICAST_STATE if you discover the peer with NsdManager. The link is IPv6 link-local and carries no internet routing, so bind sockets to the returned Network and find the peer over mDNS. No Meta permission is required, but the user must approve a system consent dialog, which the system shows only while the requesting app is in the foreground; a background request is dropped after 30 seconds and your callback receives onUnavailable(), at which point the callback is already unregistered and the request released, so reset your UI and call requestNetwork() again rather than unregisterNetworkCallback() if the user retries. Read getLinkDownstreamBandwidthKbps() in onCapabilitiesChanged() to tell a USB 2 cable (about 480,000 Kbps) from USB 3 (about 5,120,000 Kbps). Call unregisterNetworkCallback() when you are done, because holding the request preempts other USB networking. |