# StreamVault Plugin API StreamVault plugins are companion Android APKs. They do not inject code into the main application. Instead, StreamVault discovers installed APKs that expose a bound service with the action `com.streamvault.plugin.API` and talks to them through Android `Messenger` IPC. This keeps the plugin boundary installable, removable, and compatible with Android package isolation while still allowing plugins to add provider, playback, Cast, and configuration capabilities. Configuration can be rendered by StreamVault from a declarative schema, or opened as a native plugin Activity when the plugin needs a richer UI. ## Package Discovery The host queries services for: ```xml ``` The host app must declare the same action in ``. Plugin APKs should declare an exported service: ```xml ``` Plugins can be installed from: - A direct HTTP/HTTPS APK URL. - A local APK selected with the system file picker. - Any manual Android package install. StreamVault detects it after refreshing the Plugins screen. ## Manifest StreamVault first asks the plugin service for its manifest. As a fallback, it reads `com.streamvault.plugin.MANIFEST_JSON` service metadata, then individual metadata fields if the JSON is missing or invalid. Example manifest for host-rendered configuration: ```json { "schemaVersion": 1, "id": "com.example.plugin", "name": "Example Plugin", "versionName": "1.0.0", "versionCode": 1, "description": "Adds external capabilities to StreamVault.", "providerName": "Example Provider", "configurationMode": "host.schema", "configurationActivityAction": "", "capabilities": [ "provider.m3u", "playback.prepare", "cast.rewriteUrl", "configuration.schema" ] } ``` Example manifest for native Activity configuration: ```json { "schemaVersion": 1, "id": "com.example.richplugin", "name": "Example Rich Plugin", "versionName": "1.0.0", "versionCode": 1, "description": "Adds a rich native configuration surface.", "providerName": "Example Provider", "configurationMode": "activity", "configurationActivityAction": "com.example.richplugin.CONFIGURE", "capabilities": [ "provider.m3u", "configuration.activity" ] } ``` Recommended fallback metadata: ```xml ``` For Activity configuration, set `CONFIGURATION_MODE` to `activity`, set `CONFIGURATION_ACTIVITY_ACTION`, and advertise `configuration.activity`. Capability names: - `provider.m3u`: the plugin can expose an M3U URL that StreamVault imports as a provider when enabled. - `playback.prepare`: the plugin can prepare a stream URL before playback starts. - `cast.rewriteUrl`: the plugin can rewrite a playback URL before Google Cast loads it. - `configuration.schema`: the plugin exposes a declarative configuration schema that StreamVault renders with its own UI. - `configuration.activity`: the plugin exposes a native Android Activity that StreamVault opens for configuration. ## IPC Messages Every request includes: - `api_version`: current value is `1`. - `request_id`: opaque ID copied back by the plugin response. Every response should include: - `api_version` - `request_id` - `success` - Optional `message` Messages: | ID | Name | Purpose | | --- | --- | --- | | 1 | `MSG_GET_MANIFEST` | Return `manifest_json`. | | 2 | `MSG_SET_ENABLED` | Start or stop plugin functionality using `enabled`. | | 3 | `MSG_GET_STATUS` | Return a short `status_label` and optional `message`. | | 4 | `MSG_GET_PROVIDER_URL` | Return `url` and optional `provider_name`. | | 5 | `MSG_PREPARE_PLAYBACK` | Prepare `input_url`; set `handled` when relevant. | | 6 | `MSG_REWRITE_CAST_URL` | Rewrite `input_url`; return `output_url` when relevant. | | 7 | `MSG_GET_CONFIGURATION_SCHEMA` | Return `configuration_schema_json`. | | 8 | `MSG_GET_CONFIGURATION_VALUES` | Return `configuration_values_json`. | | 9 | `MSG_SET_CONFIGURATION_VALUES` | Persist `configuration_values_json`. | | 10 | `MSG_RUN_CONFIGURATION_ACTION` | Run `configuration_action_id`. | For `playback.prepare` and `cast.rewriteUrl`, plugins should set `handled=false` when the URL is not theirs. StreamVault then continues with other enabled plugins or the original URL. `MSG_PREPARE_PLAYBACK` may also enrich the stream that StreamVault sends to the player. When `handled=true` and `success=true`, the plugin can return: - `output_url`: final playable URL. If omitted, StreamVault keeps `input_url`. - `stream_type`: optional playback hint. Supported values are `DASH`, `HLS`, `SMOOTH_STREAMING`, `MPEG_TS`, `PROGRESSIVE`, and `RTSP`. - `headers_json`: JSON object with HTTP request headers for the media request. - `user_agent`: optional user agent applied to the media request. - `drm_json`: JSON object with DRM information: ```json { "scheme": "clearkey", "licenseUrl": "http://127.0.0.1:39077/license/clearkey/channel-id", "headers": { "Authorization": "Bearer token" }, "multiSession": false, "forceDefaultLicenseUrl": true, "playClearContentWithoutKey": true } ``` `scheme` accepts `widevine`, `playready`, `clearkey`, or their platform UUID aliases (`com.widevine.alpha`, `com.microsoft.playready`, `org.w3.clearkey`). For `SMOOTH_STREAMING` + `clearkey`, StreamVault normalizes the ISML `ProtectionHeader` into ClearKey PSSH v1 init data before creating the Android MediaDrm session. ## Choosing a Configuration Mode Plugins should choose one primary configuration mode. Use `host.schema` when the configuration is mostly fields, switches, selects, and simple actions. StreamVault owns the visual shell, validation placement, focus behavior, typography, controls, and feedback. Use `activity` when the plugin needs a custom or highly interactive configuration surface, for example: - Runtime dashboards with live state. - Source managers with add/edit/delete flows. - Channel testing workflows. - Embedded logs. - Native pairing, sign-in, or device setup. - Custom layouts that must look the same when opened directly and from StreamVault. Do not advertise `configuration.schema` for a partial or stale schema. If `configurationMode` is `activity`, StreamVault treats the Activity as the active configuration path and opens `configurationActivityAction` instead of loading a host-rendered schema. For backward compatibility, a plugin that omits `configurationMode` but advertises `configuration.schema` is treated as host-rendered. New plugins should set `configurationMode` explicitly. ## Host-Rendered Configuration Host-rendered configuration lets a plugin describe fields and actions while StreamVault owns the visual implementation. A plugin opts in with: - Manifest field `configurationMode: "host.schema"`. - Capability `configuration.schema`. - IPC handlers for messages 7 through 10. Schema response: ```json { "schemaVersion": 1, "title": "Example Plugin", "description": "Settings rendered by StreamVault.", "sections": [ { "id": "connection", "title": "Connection", "description": "Endpoint used by this plugin.", "fields": [ { "key": "serverUrl", "type": "url", "label": "Server URL", "placeholder": "http://192.168.1.20:8080", "required": true }, { "key": "token", "type": "password", "label": "Token", "secret": true }, { "key": "lanMode", "type": "boolean", "label": "LAN mode", "description": "Expose local URLs to other devices." }, { "key": "quality", "type": "select", "label": "Preferred quality", "options": [ { "value": "auto", "label": "Auto" }, { "value": "1080p", "label": "1080p" } ] }, { "key": "status", "type": "info", "label": "Status", "readOnly": true } ] } ], "actions": [ { "id": "testConnection", "label": "Test connection", "description": "Ask the plugin to validate its current settings.", "refreshAfterRun": true } ] } ``` Supported field types: - `info`: read-only text rendered by StreamVault. - `text`: single-line text. - `password`: single-line secret text. - `url`: URL text field. - `number`: numeric text field. - `boolean`: switch. - `select`: one value from `options`. - `textarea`: multi-line text. Values response: ```json { "serverUrl": "http://192.168.1.20:8080", "token": "", "lanMode": true, "quality": "auto", "status": "Ready" } ``` For `MSG_SET_CONFIGURATION_VALUES`, StreamVault sends the same JSON object in `configuration_values_json`. Plugins should persist supported writable keys, ignore unknown or read-only keys, and return `success=false` with `message` when validation fails. For `MSG_RUN_CONFIGURATION_ACTION`, StreamVault sends `configuration_action_id`. Plugins should execute the action, return a user-facing `message`, and refresh their values when `refreshAfterRun` is true. ## Configuration Activity Mode Activity configuration lets the plugin own the complete configuration UI. StreamVault starts `configurationActivityAction` with the plugin package set explicitly, so the action does not resolve to another app. A plugin opts in with: - Manifest field `configurationMode: "activity"`. - Capability `configuration.activity`. - Manifest field `configurationActivityAction`. - An exported Activity with an intent filter for that action and the `DEFAULT` category. Example: ```xml ``` Use Activity mode for flows that cannot be represented faithfully as fields and actions. The HaP plugin is the reference example: it uses Activity mode for runtime state, source management, custom AceStream channels, channel tests, connected clients, and logs. ## Native Activity Visual Guidance Native plugin Activities should feel at home when launched from StreamVault and remain usable when opened directly from Android or Android TV. Recommended visual and interaction rules: - Design TV-first: every important control must be D-pad focusable and readable from couch distance. - Keep the style restrained and close to StreamVault: dark background, compact panels, clear focus states, and meaningful status colors for running, stopped, warning, and error states. - Collapse heavy or secondary sections by default, especially logs, source editors, and long channel-status lists. - Keep layout dimensions stable. Avoid buttons, rows, or status chips changing size when text or loading state changes. - Truncate or wrap long URLs, channel names, and error messages so text never overlaps adjacent controls. - Use Android resources and the system locale for all user-facing text. - Show direct feedback for loading, validation, success, and failure states. - Test both entry points: launched directly from the plugin APK and launched from StreamVault's Plugins screen. - Test on the same device classes StreamVault supports, including TV devices such as Chromecast and phone-sized devices such as Nexus 5X. ## Integration Checklist Before publishing a plugin: - Expose exactly one `com.streamvault.plugin.API` service. - Return a complete manifest from `MSG_GET_MANIFEST`. - Keep service metadata in sync with the runtime manifest as fallback. - Choose `host.schema` or `activity` as the primary configuration mode. - Advertise only capabilities that are fully implemented. - Validate user-provided URLs and secrets inside the plugin before persisting them. - Return user-facing error messages from IPC failures. - Verify install, enable, disable, configure, provider URL, playback prepare, and Cast URL rewrite on real devices.