tags: [vr-ar]
Build signing and assembly for Meta Quest Store
Building for Meta Quest is not just Build And Run from Unity with Android target selected. Meta has own chain of requirements: build signature, entitlements, manifest settings, manifest.json parameters for Horizon Store, target API level requirements and bunch of nuances revealed at submission stage, not earlier.
Where exactly the signing chain breaks
Most frequent problem — keystore mismatch between debug and release builds. Developer tested app for months with debug keystore, all worked. Transitioning to release keystore with different SHA-1 entitlements tied to app in Horizon Developer Dashboard stop working. User installs app, opens — gets authorization error in Platform SDK because OVRPlatform.Initialize() returns INVALID_CREDENTIALS.
Second problem class — AndroidManifest.xml. Meta requires specific permission set and intent-filter: com.oculus.permission.HAND_TRACKING, com.oculus.permission.EYE_TRACKING, com.oculus.intent.category.VR. If app uses passthrough, explicitly write com.oculus.permission.USE_SCENE and horizonos.permission.USE_ANCHOR_API for spatial anchors. Miss one — feature silently doesn't work, no log errors, only if enable verbose in adb logcat.
Separately stands quest_categories in Horizon Store package manifest.json. Wrong category or missing supported_input_devices — app fails auto-check. Meta verifies manifest matches declared app functions.
Release build process
Work via Oculus Developer Hub or directly via command line with adb and apksigner from Android SDK Build Tools. For Unity projects — Gradle wrapper, settings in launcherTemplate.gradle and mainTemplate.gradle.
Key steps for correct release build:
Keystore generated via keytool with -keyalg RSA -keysize 2048 -validity 10000. Store separately from repository, SHA-1 and SHA-256 saved in protected project storage. In Unity — Player Settings → Publishing Settings → Use Custom Keystore.
target-api-level as of 2024–2025 should be 32 or higher for new submissions. Meta periodically raises minimum threshold, need check in current Horizon OS documentation.
To check signature before submission: apksigner verify --verbose --print-certs app-release.apk. Ensure certificate chain correct and fingerprint matches registered in Dashboard.
Test signed build on device — via adb install -r app-release.apk. Before testing remove debug version completely, else system might pick old credentials.
Specifics for different distribution channels
Meta Quest Store has several channels: App Lab (early testers without full review), Horizon Store (public release with full review), and Side Quest / sideloading for internal testing.
For App Lab and Horizon Store signature requirements identical — difference only in review process. For sideloading can use debug keystore, but only for internal tests — not release flow.
If project uses Passthrough API or Mixed Reality Utility Kit (MRUK), add to manifest.json required_feature section with PASSTHROUGH. Without this app won't run on devices with passthrough disabled.
| Build type | Keystore | Target API | Check entitlements |
|---|---|---|---|
| Debug / Dev Mode | Debug keystore | Any | Optional |
| App Lab | Release keystore | ≥ 32 | Mandatory |
| Horizon Store | Release keystore | ≥ 32 | Mandatory + Meta review |
Work process organization
Get Horizon Developer Dashboard access or work through provided app ID. Audit current manifest and Gradle config. Setup keystore infrastructure if missing. Build, sign, test on device, prepare package for submission.
If project already published and needs update — check keystore version compatibility and versionCode (Meta won't accept package with versionCode ≤ previous).
Timeline: setup from scratch — 1–2 working days. For existing project with manifest needing only fixing and submission — few hours. Iteration on Meta rejection — depends on reason.
Cost determined after current project state analysis.





