makeing it direct wifi able and removed gliches from core and as well added a apk builder - #4
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a Wi‑Fi companion-app workflow for screen mirroring when ADB over Wi‑Fi is unavailable, including an auto-APK build pipeline and an HTTP endpoint to download the companion APK and accept raw JPEG frames.
Changes:
- Added an Android companion app (Activity + foreground MediaProjection service) that captures the screen and POSTs JPEG frames to the desktop server.
- Added
APKBuilderto auto-download/install required Android SDK components (when missing), build/sign the APK, and cache it per server URL. - Updated the TUI + web mirror server to serve the companion APK and accept
image/jpegframe uploads.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| src/fiver/web_mirror.py | Phone landing page now offers companion APK download; adds /download/companion.apk; accepts raw image/jpeg frames. |
| src/fiver/tui.py | Companion-mode fallback: builds APK, serves it, tunnels via Cloudflare, and waits for streaming. |
| src/fiver/apk_builder.py | New APK build/sign/cache implementation with SDK auto-install behavior. |
| src/fiver/companion/AndroidManifest.xml | New manifest for the companion app (permissions + service/activity registration). |
| src/fiver/companion/MainActivity.java | New UI to request MediaProjection permission and start/stop capture service. |
| src/fiver/companion/ScreenCaptureService.java | New foreground service that captures frames and POSTs JPEG to /api/frame. |
| src/fiver/companion/init.py | Package marker for bundling companion sources. |
| src/fiver/banner.py | Updates ASCII banner art. |
| pyproject.toml | Packages companion .java/.xml sources as package data. |
| patch.py | Adds a local patching script (currently hard-coded to an absolute path). |
| build/lib/fiver/banner.py | Updates banner art in a build artifact copy. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+256
to
+260
| with open(MirrorHandler.apk_path, "rb") as f: | ||
| apk_data = f.read() | ||
| self.send_header("Content-Length", str(len(apk_data))) | ||
| self.end_headers() | ||
| self.wfile.write(apk_data) |
Comment on lines
+236
to
+239
| host = self.headers.get("Host", "localhost") | ||
| proto = "https" if isinstance(self.connection, ssl.SSLSocket) else "http" | ||
| html = PHONE_HTML.replace("{{LOCAL_SERVER_URL}}", f"{proto}://{host}") | ||
| self.wfile.write(html.encode("utf-8")) |
Comment on lines
520
to
522
| local_ip, _ = _local_subnet() | ||
| local_ip = local_ip or "127.0.0.1" | ||
|
|
Comment on lines
527
to
529
| self.web_server = WebMirrorServer(port=8080) | ||
| self.web_server.start() | ||
| server_addr = self.web_server.start() | ||
|
|
Comment on lines
+12
to
+14
| <application | ||
| android:label="Fiver Mirror" | ||
| android:theme="@android:style/Theme.DeviceDefault.NoActionBar"> |
Comment on lines
+156
to
+162
| zip_path = _SDK_DIR / "cmdline-tools.zip" | ||
| try: | ||
| _run(["curl", "-fsSL", "-o", str(zip_path), _CMDLINE_TOOLS_URL]) | ||
| except RuntimeError: | ||
| # Fallback to wget | ||
| _run(["wget", "-q", "-O", str(zip_path), _CMDLINE_TOOLS_URL]) | ||
|
|
Comment on lines
+214
to
+250
| @staticmethod | ||
| def _cache_key(server_url: str) -> str: | ||
| return hashlib.sha256(server_url.encode()).hexdigest()[:16] | ||
|
|
||
| def get_cached_apk(self, server_url: str) -> Optional[str]: | ||
| """Return path to cached APK if it exists for this server_url.""" | ||
| key = self._cache_key(server_url) | ||
| path = _APK_CACHE_DIR / f"companion-{key}.apk" | ||
| return str(path) if path.is_file() else None | ||
|
|
||
| # ── Build ───────────────────────────────────────────────── | ||
|
|
||
| def build_apk(self, server_url: str) -> str: | ||
| """Build the companion APK with *server_url* embedded. | ||
|
|
||
| Returns the absolute path to the signed APK. | ||
| Raises ``RuntimeError`` on failure. | ||
| """ | ||
| # 1. Cache check | ||
| cached = self.get_cached_apk(server_url) | ||
| if cached: | ||
| log.info("Using cached APK: %s", cached) | ||
| return cached | ||
|
|
||
| # 2. Tool check — auto-install if needed | ||
| missing = self._missing_tools() | ||
| if missing: | ||
| log.info("Missing SDK tools: %s — attempting auto-install", missing) | ||
| self.install_sdk() | ||
| missing = self._missing_tools() | ||
| if missing: | ||
| raise RuntimeError( | ||
| f"Required tools not found: {', '.join(missing)}.\n" | ||
| "Please install the Android SDK build-tools and platform.\n" | ||
| " Arch/CachyOS: yay -S android-sdk-build-tools android-platform\n" | ||
| " Or run: fiver --doctor" | ||
| ) |
Comment on lines
+1
to
+12
| import re | ||
| import os | ||
|
|
||
| def patch_web_mirror(): | ||
| path = "/home/cachy/github-p/fiver/src/fiver/web_mirror.py" | ||
| with open(path, "r") as f: | ||
| content = f.read() | ||
|
|
||
| # 1. PHONE_HTML | ||
| start_str = '# HTML template for the phone (Matte Black Theme, Instant Tap Permission)' | ||
| end_str = '"""\n\n# HTML template for the Desktop viewer' | ||
|
|
Comment on lines
1
to
16
| """ASCII branding for the fiver CLI.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from . import __version__ | ||
|
|
||
| ART = r""" | ||
| ░▒▓████████▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓████████▓▒░▒▓███████▓▒░ | ||
| ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ | ||
| ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ | ||
| ░▒▓██████▓▒░ ░▒▓█▓▒░░▒▓█▓▒▒▓█▓▒░░▒▓██████▓▒░ ░▒▓███████▓▒░ | ||
| ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ | ||
| ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ | ||
| ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░ | ||
| ART = r""" | ||
| ███████╗██╗██╗ ██╗███████╗██████╗ | ||
| ██╔════╝██║██║ ██║██╔════╝██╔══██╗ | ||
| █████╗ ██║██║ ██║█████╗ ██████╔╝ | ||
| ██╔══╝ ██║╚██╗ ██╔╝██╔══╝ ██╔══██╗ | ||
| ██║ ██║ ╚████╔╝ ███████╗██║ ██║ | ||
| ╚═╝ ╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝ | ||
| """ | ||
|
|
||
| TAGLINE = " android desk control | local server | your device" |
Comment on lines
+572
to
575
| # Poll until phone starts streaming or user exits | ||
| while not MirrorHandler.accepted and not MirrorHandler.declined: | ||
| time.sleep(0.5) | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fiver Wireless Companion App - Implementation Complete
What Was Built
A complete wireless screen mirroring system that works without USB debugging. When a phone scans a QR code, it downloads a companion Android app that captures the screen and streams it live to the laptop over WiFi.
New Files Created
companion/__init__.pycompanion/AndroidManifest.xmlcompanion/MainActivity.javacompanion/ScreenCaptureService.javaapk_builder.pyModified Files
web_mirror.py/download/companion.apkendpoint, raw JPEG frame support, APK download pagetui.pypyproject.tomlComplete Flow
Required Dependencies
Before the APK can be built, you need JDK installed:
Important
The Android SDK build-tools and platform will be auto-downloaded on first use to
~/.fiver/sdk/. No manual Android Studio setup needed.Key Design Decisions
commandlinetoolsfrom Google, then usessdkmanagerto installbuild-tools;34.0.0andplatforms;android-34~/.fiver/apk/keyed by server URL hashMediaProjectionAPI which only needs user consent