Files
QuestAppLauncher/docs.md
oxmc7769 77799c1182
Some checks failed
Build / Build launcher (push) Has been cancelled
Move to JSON only, add examples
2026-03-18 09:30:23 -07:00

8.0 KiB
Raw Permalink Blame History

Quest App Launcher — Documentation

Table of Contents

  1. Overview
  2. Architecture
  3. Configuration
  4. App Name Overrides
  5. Custom Icons
  6. Tab / Category System
  7. Asset Auto-Update
  8. Managed Policies
  9. On-Device File Locations

Overview

Quest App Launcher is a VR home-screen replacement for Meta Quest 2. It lists all installed non-system apps in a scrollable grid, organized into tabs. Apps can be launched by pointing and clicking with the controller.


Architecture

Data Flow

  1. AppInfo.java (Android plugin) — queries the Android package manager for installed apps, decodes icons as bitmaps, and reads usage statistics via UsageStatsManager.
  2. AppProcessor.cs — calls the Java plugin over JNI, applies name overrides from appnames*.json, filters excluded packages, assigns apps to auto tabs (Quest / 2D), and returns a ProcessedApp dictionary.
  3. GridPopulation.cs — takes the processed app list, sorts it (AZ or most-recently-used), builds tab containers, and instantiates AppEntry prefab tiles in the grid.
  4. AppEntry.cs — represents a single icon tile. Lazy-loads and unloads its texture based on scroll position to keep memory use bounded.

Key Scripts

File Role
Assets/Scripts/AppProcessor.cs App discovery, name overrides, exclusion lists, icon loading
Assets/Scripts/GridPopulation.cs Grid layout, tab assignment, sort order
Assets/Scripts/AppEntry.cs Per-tile icon loading / unloading
Assets/Scripts/Config.cs Settings model and JSON persistence
Assets/Scripts/AssetsDownloader.cs Downloads icon packs and app name files from GitHub
Assets/Scripts/SkyboxHandler.cs Background skybox selection and loading
Assets/Scripts/SettingsHandler.cs Settings UI wiring
Assets/Scripts/GlobalState.cs Cross-scene singleton (DontDestroyOnLoad)
Assets/Plugins/Android/AppInfo.java Android interop layer

Configuration

Settings are stored in config.json in the app's persistent data path on-device. The file is created with defaults on first run. You can push a custom config.json via adb:

adb push config.json /sdcard/Android/data/dev.oxmc.QuestAppLauncher/files/

config.json fields

Field Type Default Description
gridSize.rows int 3 Number of rows in the grid
gridSize.cols int 3 Number of columns in the grid
sortMode string "az" Sort order: "az" (alphabetical) or "mostRecent"
show2D bool true Whether to show 2D (non-VR) apps
autoCategory string "top" Where auto tabs appear: "top", "left", "right", or "off"
customCategory string "right" Where custom tabs appear: same options as above
autoUpdate bool true Automatically check for and download asset updates
background string "default" Background image path, or "default" for the built-in skybox
downloadRepos array GitHub default List of repos to pull icon packs and app names from
managedPolicyEndpoint string "" URL to fetch managed policy JSON from (IT/MDM use)

Example config.json

{
  "gridSize": { "rows": 3, "cols": 4 },
  "sortMode": "az",
  "show2D": true,
  "autoCategory": "top",
  "customCategory": "right",
  "autoUpdate": true,
  "background": "default",
  "downloadRepos": [
    { "repoUri": "hooverhigh/QuestAppLauncher_Assets/releases/latest", "type": "github" }
  ]
}

App Name Overrides

Place appnames.json (or any appnames*.json file) in the persistent data path to rename apps and assign them to custom tabs.

Format (appnames.json)

{
  "com.example.myapp": {
    "Name": "My App",
    "Category": "Games",
    "Category2": "Favorites"
  }
}
  • Name — display name override (leave blank to keep the original name)
  • Category / Category2 — optional tab names (up to two per app)

Pushing to the device

adb push appnames.json /sdcard/Android/data/dev.oxmc.QuestAppLauncher/files/

Custom Icons

Place .jpg files named <packageName>.jpg in the persistent data path, or bundle them into a zip file named iconpack*.zip.

Individual icons

adb push com.example.myapp.jpg /sdcard/Android/data/dev.oxmc.QuestAppLauncher/files/

Icon packs (zip)

Create a zip containing <packageName>.jpg files at the root level:

iconpack_custom.zip
  com.example.myapp.jpg
  com.example.otherapp.jpg
adb push iconpack_custom.zip /sdcard/Android/data/dev.oxmc.QuestAppLauncher/files/

The launcher extracts icon packs automatically on startup. Multiple icon packs are supported and applied in alphabetical order (later packs override earlier ones).


Tab / Category System

Auto tabs

Apps are automatically assigned to one of two built-in tabs based on their package metadata:

Tab Criteria
Quest App declares the android.hardware.vr.headtracking feature, or any other VR app
2D App has no VR features

The All tab always shows every app regardless of category.

Auto tabs can be placed at the top, left, or right of the panel, or disabled entirely via autoCategory in config.json.

Custom tabs

Assign apps to custom tabs using the Category / Category2 fields in appnames.json. Custom tabs appear sorted alphabetically. Their position is controlled by customCategory in config.json.


Asset Auto-Update

When autoUpdate is true, the launcher checks configured repos for updated icon packs and app name files on startup (rate-limited to once every 5 minutes). If updates are found, they are downloaded to the download_cache folder inside the persistent data path and the scene is reloaded.

Adding a custom HTTP repo

In addition to GitHub releases, you can host assets on any plain HTTP server by providing a manifest JSON:

{
  "files": [
    { "name": "iconpack_school.zip", "url": "https://yourserver.com/iconpack_school.zip", "updatedAt": "2025-01-01T00:00:00Z" },
    { "name": "appnames.json",       "url": "https://yourserver.com/appnames.json",       "updatedAt": "2025-01-01T00:00:00Z" }
  ]
}

Add it to downloadRepos in config.json:

{ "repoUri": "https://yourserver.com/manifest.json", "type": "http" }

Managed Policies

For IT/MDM deployments, the launcher can fetch a policy JSON from a URL on every startup. Set managedPolicyEndpoint in config.json (or define DEV_ENDPOINT at compile time).

Supported policy fields:

Field Type Description
hiddenApps string[] Package names to hide from the launcher
appNames object Same format as appnames.json — name/category overrides
disableSettings bool Hides the settings button
wallpaper string URL to a background image (overrides user setting)

On-Device File Locations

All user-editable files live in the app's persistent data path:

/sdcard/Android/data/dev.oxmc.QuestAppLauncher/files/
File / Folder Purpose
config.json App settings
appnames*.json App name and category overrides
iconpack*.zip Custom icon packs
*.jpg Individual icon overrides (<packageName>.jpg)
excludedpackages.txt One package name per line — these apps are hidden
download_cache/ Downloaded icon packs and app name files (managed automatically)

Useful adb commands

# View Unity logs live
adb logcat -s Unity

# List files in persistent data path
adb shell ls /sdcard/Android/data/dev.oxmc.QuestAppLauncher/files/

# Push a config file
adb push config.json /sdcard/Android/data/dev.oxmc.QuestAppLauncher/files/

# Pull all app data (for debugging)
adb pull /sdcard/Android/data/dev.oxmc.QuestAppLauncher/files/ ./device_files