Skip to content

Commit 5dc72d7

Browse files
Document Service and boot_completed intent filter
1 parent eb456b2 commit 5dc72d7

6 files changed

Lines changed: 394 additions & 3 deletions

File tree

docs/apps/app-lifecycle.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,45 @@ class NetworkAwareActivity(Activity):
413413
❌ Don't assume the activity is still visible after async operations
414414
❌ Don't store references to LVGL objects after `onDestroy()`
415415

416+
## Services — Background Components
417+
418+
Alongside Activities, MicroPythonOS provides **Services** for background work that runs without a user interface. Unlike Activities, Services have no screen lifecycle — they are created, started, and destroyed by intent actions (e.g., `boot_completed`).
419+
420+
### Service Lifecycle
421+
422+
```
423+
┌────────────┐
424+
│ onCreate │ ← One-time initialization
425+
└─────┬──────┘
426+
427+
428+
┌────────────┐
429+
│ onStart │ ← Receive intent, begin work
430+
└─────┬──────┘
431+
432+
433+
┌────────────┐
434+
│ onDestroy │ ← Cleanup
435+
└────────────┘
436+
```
437+
438+
### Service vs. Activity Comparison
439+
440+
| Method | Activity | Service |
441+
|--------|----------|---------|
442+
| `onCreate()` | Build UI, set up screen | Initialize resources |
443+
| `onStart()` | Screen about to become visible | Start background work (receives Intent) |
444+
| `onDestroy()` | Activity removed from stack | Stop threads, cancel tasks |
445+
446+
### When to Use a Service
447+
448+
- Starting WiFi auto-connect at boot
449+
- Launching a background web server
450+
- Running a periodic update check
451+
- Starting an async REPL task
452+
453+
Services are declared either programmatically (system services) or via `"services"` in the app's `MANIFEST.JSON`. See the [Service documentation](../frameworks/service.md) for a complete reference.
454+
416455
## Lifecycle Comparison with Android
417456

418457
| MicroPythonOS | Android | Notes |
@@ -435,3 +474,4 @@ class NetworkAwareActivity(Activity):
435474
- [AppManager](../frameworks/app-manager.md) - App management and launching
436475
- [Intent System](../frameworks/app-manager.md#intent-resolution) - Intent-based navigation
437476
- [TaskManager](../frameworks/task-manager.md) - Async task management
477+
- [Service](../frameworks/service.md) - Background services for boot-time and long-running tasks

docs/apps/creating-apps.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,34 @@ In `MANIFEST.JSON`, put:
6969
}
7070
```
7171

72+
### Services
73+
74+
Apps can also declare **services** — background components that run at boot time with no user interface. Services are defined in the `"services"` array of the manifest:
75+
76+
```json
77+
"services": [
78+
{
79+
"entrypoint": "assets/my_boot_service.py",
80+
"classname": "MyBootService",
81+
"intent_filters": [
82+
{
83+
"action": "boot_completed"
84+
}
85+
]
86+
}
87+
]
88+
```
89+
90+
Each service entry has:
91+
92+
| Field | Description |
93+
|-------|-------------|
94+
| `entrypoint` | Path to the Python file (relative to the app root) |
95+
| `classname` | Name of the `Service` subclass in that file |
96+
| `intent_filters` | Array of `{ "action": "..." }` objects. Use `"boot_completed"` to run at startup |
97+
98+
Services that subscribe to `"boot_completed"` are started automatically during system boot, after the launcher is displayed. See the [Service documentation](../frameworks/service.md) for details on writing and using services.
99+
72100
## Icon
73101

74102
The icon is a [simple 64x64 pixel PNG image](https://github.com/MicroPythonOS/MicroPythonOS/blob/main/internal_filesystem/builtin/apps/com.micropythonos.launcher/res/mipmap-mdpi/icon_64x64.png), which you can create with any tool, such as GIMP.

docs/architecture/boot-sequence.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,16 @@ MicroPythonOS consists of several core components that initialize and manage the
1212
- Mounts the freezefs into /builtin/
1313
- Loads the com.micropythonos.settings
1414
- Initializes the user interface.
15-
- Starts the WiFi autoconnect thread
1615
- Launches the `launcher` app that shows the icons
17-
- Starts the asyncio REPL
16+
- Runs auto-start apps (`auto_start_app_early`, `auto_start_app`)
17+
- Starts **boot services** — all services that subscribe to the `boot_completed` intent are instantiated and receive `onStart()`:
18+
- `WifiBootService` — auto-connects WiFi in a background thread
19+
- `WebServerBootService` — starts the HTTP web server
20+
- `AIOReplService` — starts the asyncio REPL task
21+
- App-specific services (e.g., `OSUpdateService`)
1822
- Marks the current boot as successful (cancel rollback)
19-
- Starts the TaskManager
23+
- Starts the TaskManager (asyncio event loop)
2024

2125
See [Filesystem Layout](filesystem.md) for where apps and data are stored.
2226

27+
See [Service](../frameworks/service.md) for details on writing boot services.

docs/frameworks/app-manager.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ AppManager provides:
1414
- **Version management** - Compares versions and detects available updates
1515
- **Intent resolution** - Resolves activities that handle specific intents (Android-inspired)
1616
- **Launcher management** - Finds and restarts the system launcher
17+
- **Service management** - Registers, resolves, and starts boot services
1718

1819
## Quick Start
1920

@@ -606,6 +607,54 @@ Stop all activities and restart launcher.
606607
2. Starts launcher app
607608
3. Useful for returning to home screen
608609

610+
### Service Management
611+
612+
**`register_service(action, service_cls, fullname=None)`**
613+
614+
Register a service class to handle an intent action (programmatic registration, used by system services).
615+
616+
- **Parameters:**
617+
- `action` (str): Intent action (e.g., `"boot_completed"`)
618+
- `service_cls` (type): Service subclass
619+
- `fullname` (str, optional): App fullname to associate with the service
620+
621+
- **Example:**
622+
```python
623+
from mpos.content.app_manager import AppManager
624+
from mpos import Service
625+
626+
class MyBootService(Service):
627+
def onStart(self, intent):
628+
print("Boot service started")
629+
630+
AppManager.register_service("boot_completed", MyBootService, fullname="com.example.myapp")
631+
```
632+
633+
**`get_services_for_action(action)`**
634+
635+
Resolve all services (manifest-declared and programmatically registered) that handle a given intent action.
636+
637+
- **Parameters:**
638+
- `action` (str): Intent action (e.g., `"boot_completed"`)
639+
640+
- **Returns:** `list[(str, type)]` - List of `(app_fullname, ServiceClass)` tuples
641+
642+
- **Behavior:**
643+
1. Scans all installed apps' manifests for matching service entries
644+
2. Imports each service module and extracts the class
645+
3. Merges with programmatically registered services from `_service_registry`
646+
647+
**`start_boot_services()`**
648+
649+
Start all services that subscribe to the `boot_completed` intent. Called once during system boot after the launcher is displayed.
650+
651+
- **Behavior:**
652+
1. Calls `get_services_for_action("boot_completed")` to discover all boot services
653+
2. For each service: instantiate, set `appFullName`, call `onCreate()`, then `onStart(boot_intent)`
654+
3. Handles errors per-service so one failing service does not block others
655+
656+
- **Called by:** `main.py` during system boot sequence
657+
609658
## Best Practices
610659

611660
### Do's
@@ -731,3 +780,4 @@ if app:
731780
- [Activity Framework](../apps/app-lifecycle.md) - Activity lifecycle and management
732781
- [Intent System](../architecture/intents.md) - Intent-based app communication
733782
- [Frameworks Overview](../architecture/frameworks.md) - All available frameworks
783+
- [Service](../frameworks/service.md) - Background services and boot-time execution

0 commit comments

Comments
 (0)