add local app discovery: scan apps folder, render on home screen
This commit is contained in:
184
docs/APP-DISCOVERY.md
Normal file
184
docs/APP-DISCOVERY.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# App Discovery System
|
||||
|
||||
Local app discovery without requiring a backend server.
|
||||
|
||||
## Status
|
||||
|
||||
| Feature | Status |
|
||||
|---------|--------|
|
||||
| Directory scanning | ✅ Implemented |
|
||||
| Manifest parsing | ✅ Implemented |
|
||||
| Home screen rendering | ✅ Implemented |
|
||||
| App launching | 🔄 In Progress |
|
||||
| Package installation | ⏳ Planned |
|
||||
|
||||
## Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Home Screen │
|
||||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ Dialer │ │ Messages│ │ TestApp │ │ MyApp │ ← scanned │
|
||||
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ from │
|
||||
│ apps/ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ /data/data/com.omixlab.mosis/files/ │
|
||||
│ ├── apps/ ← Installed third-party apps │
|
||||
│ │ ├── com.mosis.testapp/ │
|
||||
│ │ │ ├── manifest.json ← App metadata │
|
||||
│ │ │ ├── main.rml ← Entry point │
|
||||
│ │ │ ├── app.lua │
|
||||
│ │ │ └── icon.tga │
|
||||
│ │ └── com.example.myapp/ │
|
||||
│ │ └── ... │
|
||||
│ ├── downloads/ ← Pending .mosis packages │
|
||||
│ └── config/ │
|
||||
│ └── apps.json ← App registry (optional cache) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Discovery Flow
|
||||
|
||||
### Phase 1: Direct Folder Discovery (MVP) ✅
|
||||
|
||||
1. **On boot**: Home screen calls `mosis.apps.getInstalled()`
|
||||
2. **AppManager** scans `/files/apps/` for folders containing `manifest.json`
|
||||
3. **For each app**: Read manifest, extract name/icon/entry point
|
||||
4. **Home screen**: Render app grid with icons
|
||||
5. **On tap**: Launch app via `mosis.apps.launch(package_id)`
|
||||
|
||||
### Phase 2: Package Installation (Future)
|
||||
|
||||
1. User copies `.mosis` file to `/files/downloads/`
|
||||
2. Store app or file manager shows pending packages
|
||||
3. User taps "Install" → `mosis.apps.install(path)`
|
||||
4. Package extracted to `/files/apps/{package_id}/`
|
||||
5. Home screen refreshes to show new app
|
||||
|
||||
## Implementation
|
||||
|
||||
### AppManager (C++)
|
||||
|
||||
The `AppManager::ScanAppsDirectory()` method scans for installed apps:
|
||||
|
||||
```cpp
|
||||
// app_manager.cpp
|
||||
void AppManager::ScanAppsDirectory() {
|
||||
std::string apps_dir = m_data_root + "/apps";
|
||||
for (const auto& entry : fs::directory_iterator(apps_dir)) {
|
||||
if (!entry.is_directory()) continue;
|
||||
|
||||
// Look for manifest.json
|
||||
std::string manifest_path = entry.path().string() + "/manifest.json";
|
||||
// Parse and register app...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Lua API
|
||||
|
||||
```lua
|
||||
-- Get all installed apps (system + third-party)
|
||||
local apps = mosis.apps.getInstalled()
|
||||
-- Returns: [{package_id, name, icon_path, entry, version, is_system_app}, ...]
|
||||
|
||||
-- Launch an app
|
||||
mosis.apps.launch("com.mosis.testapp")
|
||||
|
||||
-- Check if app is running
|
||||
local running = mosis.apps.isRunning("com.mosis.testapp")
|
||||
```
|
||||
|
||||
### Home Screen (home.lua)
|
||||
|
||||
The home screen dynamically renders third-party apps:
|
||||
|
||||
```lua
|
||||
function initHome(doc)
|
||||
-- Get installed apps, filter to third-party only
|
||||
local apps = mosis.apps.getInstalled()
|
||||
for _, app in ipairs(apps) do
|
||||
if not app.is_system_app then
|
||||
-- Render app icon
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function launchThirdPartyApp(package_id)
|
||||
mosis.apps.launch(package_id)
|
||||
end
|
||||
```
|
||||
|
||||
## Test App Deployment
|
||||
|
||||
To deploy a test app manually:
|
||||
|
||||
```bash
|
||||
# 1. Push to temp location (avoid permission issues)
|
||||
adb push test-apps/com.mosis.sandbox-test/ //data/local/tmp/com.mosis.sandbox-test/
|
||||
|
||||
# 2. Copy to app's private storage
|
||||
adb shell "run-as com.omixlab.mosis cp -r /data/local/tmp/com.mosis.sandbox-test /data/data/com.omixlab.mosis/files/apps/"
|
||||
|
||||
# 3. Verify
|
||||
adb shell "run-as com.omixlab.mosis ls /data/data/com.omixlab.mosis/files/apps/com.mosis.sandbox-test/"
|
||||
```
|
||||
|
||||
For Desktop Designer:
|
||||
```bash
|
||||
# Copy to designer's sandbox_data folder
|
||||
cp -r test-apps/com.mosis.sandbox-test/ designer/build/Debug/sandbox_data/apps/
|
||||
```
|
||||
|
||||
## App Manifest Format
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "com.mosis.testapp",
|
||||
"name": "Test App",
|
||||
"version": "1.0.0",
|
||||
"version_code": 1,
|
||||
"entry": "main.rml",
|
||||
"icon": "icon.tga",
|
||||
"description": "A test application",
|
||||
"permissions": ["storage", "network"]
|
||||
}
|
||||
```
|
||||
|
||||
## Directory Structure
|
||||
|
||||
### System Apps (bundled in APK assets)
|
||||
```
|
||||
assets/apps/
|
||||
├── home/ # Home screen (always loaded)
|
||||
├── dialer/
|
||||
├── messages/
|
||||
├── contacts/
|
||||
├── settings/
|
||||
├── browser/
|
||||
└── store/
|
||||
```
|
||||
|
||||
### Third-Party Apps (in private storage)
|
||||
```
|
||||
/data/data/com.omixlab.mosis/files/apps/
|
||||
├── com.mosis.testapp/
|
||||
│ ├── manifest.json
|
||||
│ ├── main.rml
|
||||
│ ├── app.lua
|
||||
│ ├── styles.rcss
|
||||
│ └── icon.tga
|
||||
└── com.example.game/
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Package signature verification** before installation
|
||||
2. **Version tracking** in apps.json registry
|
||||
3. **Update detection** by comparing version_code
|
||||
4. **Uninstall** with data cleanup option
|
||||
5. **Store integration** for HTTP-based discovery
|
||||
Reference in New Issue
Block a user