home / skills / dbobkov245-source / pwa-torserve / capacitor-bridge
This skill orchestrates React and Android native bridge to launch external video players, resuming playback position after completion.
npx playbooks add skill dbobkov245-source/pwa-torserve --skill capacitor-bridgeReview the files below or copy the command above to add this skill to your agents.
---
name: capacitor-bridge
description: Specialist in Android Intents, Java-JS bridging, and External Player integration.
---
# Capacitor Bridge Skill
This skill handles the communication between the React Frontend and the Native Android layer (`TVPlayer.java`).
**Primary Goal:** Launch external players (VLC, MX Player, Vimu) correctly and handle their return results (resume position).
## 桥 API Contract
### `TVPlayer.play(options)`
Launches a single video file. **Must return a Promise that resolves only after the player closes.**
**Options:**
* `url` (string, required): Direct link to the video stream.
* `package` (string, optional): Specific player package name (e.g., `net.gtvbox.videoplayer`). If null, opens system chooser.
* `title` (string): Title to display in the player.
* `position` (number): Resume position in milliseconds.
**Java Extras (What actually gets sent):**
* `Intent.ACTION_VIEW`
* `return_result`: `true`
* **Flags:** `FLAG_ACTIVITY_CLEAR_TOP`, `FLAG_ACTIVITY_SINGLE_TOP` (Crucial for preventing double rendering).
### `TVPlayer.playList(options)`
Launches a playlist (Season/Series).
**Options:**
* `urls` (string[]): Array of video URLs.
* `names` (string[]): Array of episode titles.
* `startIndex` (number): Which index to start playing.
* `position` (number): Resume position for the *started* episode.
## 📱 Supported Players & Extras
### Vimu Player (`net.gtvbox.videoplayer`)
* **Single:** `forcename` (Title), `forcedirect` (No buffer), `startfrom` (Position).
* **Playlist:** Uses `application/vnd.gtvbox.filelist` MIME type.
* `asusfilelist` (URLs)
* `asusnamelist` (Names)
### MX Player (`com.mxtech.videoplayer.ad` / `.pro`)
* **Single:** `title`, `position`.
* **Playlist:** Uses standard `video/*` with extras.
* `video_list` (Parcelable Uri[])
* `video_list.name` (String[])
### VLC (`org.videolan.vlc`)
* **Single:** `title`, `from_start` (false).
* **Playlist:** *Not fully supported via Intent extras, falls back to acting as single file player currently.*
## ⚠️ Critical Rules
1. **Do NOT change `FLAG_ACTIVITY_SINGLE_TOP`.** This prevents the app from restarting or opening a second instance of the intent chooser.
2. **RESTRICTED: `FLAG_ACTIVITY_NEW_TASK` and `FLAG_ACTIVITY_CLEAR_TOP`**. These flags are essential for correct stack manipulation between PWA and Native Player. Removing them breaks the return journey.
3. **Lifecycle:** The promise resolves when `onActivityResult` fires (i.e., user closes the player).
* **Requirement:** `play()` method MUST return a Promise resolving with `{ position, duration }`.
4. **Resume Logic:** The result object contains `{ position: number, duration: number, finished: boolean }`. You MUST save this to `localStorage` immediately.
This skill handles the bridge between a React frontend and the native Android player layer to launch external players and manage their return results. It focuses on reliable Intent construction, player-specific extras, and guaranteeing the play() Promise resolves only after the external player closes. The skill ensures resume position and duration are captured and persisted for seamless playback recovery.
It exposes play() and playList() operations that construct Android Intents with required flags and extras, then waits for onActivityResult to resolve a Promise with { position, duration, finished }. The implementation applies player-specific extras (Vimu, MX Player, VLC), enforces critical Intent flags, and writes the returned resume data to localStorage immediately. The bridge supports single files and playlists, mapping arrays and names into the correct MIME type and extras per player.
What must play() return?
play() must return a Promise that resolves with { position, duration, finished } after the external player closes (onActivityResult).
Which Intent flags are mandatory?
Keep FLAG_ACTIVITY_SINGLE_TOP and FLAG_ACTIVITY_CLEAR_TOP. Removing them breaks return behavior and can cause duplicate rendering.
How should resume data be stored?
Immediately save the returned resume object to localStorage to ensure position/duration persistence across sessions.