238 lines
8.0 KiB
Markdown
238 lines
8.0 KiB
Markdown
# Quest App Launcher — Documentation
|
||
|
||
## Table of Contents
|
||
|
||
1. [Overview](#overview)
|
||
2. [Architecture](#architecture)
|
||
3. [Configuration](#configuration)
|
||
4. [App Name Overrides](#app-name-overrides)
|
||
5. [Custom Icons](#custom-icons)
|
||
6. [Tab / Category System](#tab--category-system)
|
||
7. [Asset Auto-Update](#asset-auto-update)
|
||
8. [Managed Policies](#managed-policies)
|
||
9. [On-Device File Locations](#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 (A–Z 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
|
||
|
||
```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`)
|
||
|
||
```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:
|
||
|
||
```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`:
|
||
|
||
```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
|
||
|
||
```bash
|
||
# 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
|
||
```
|