{"id":50915399,"url":"https://github.com/borankux/android-remote-control","last_synced_at":"2026-06-16T14:03:22.689Z","repository":{"id":363104960,"uuid":"1261340436","full_name":"borankux/android-remote-control","owner":"borankux","description":"Open-source rooted Android remote control stack with Kotlin app, Node relay, React console, MJPEG preview, and ADB bridge","archived":false,"fork":false,"pushed_at":"2026-06-07T12:14:15.000Z","size":898,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T14:10:23.779Z","etag":null,"topics":["adb","adb-bridge","android","android-automation","cloud-phone","device-automation","kotlin-android","mjpeg","mobile-testing","nodejs","qa-automation","react","remote-control","remote-desktop","rooted-android","uiautomator","vite","websocket"],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/borankux.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-06T14:57:27.000Z","updated_at":"2026-06-07T12:14:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/borankux/android-remote-control","commit_stats":null,"previous_names":["borankux/android-remote-control"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/borankux/android-remote-control","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borankux%2Fandroid-remote-control","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borankux%2Fandroid-remote-control/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borankux%2Fandroid-remote-control/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borankux%2Fandroid-remote-control/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/borankux","download_url":"https://codeload.github.com/borankux/android-remote-control/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borankux%2Fandroid-remote-control/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34408790,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adb","adb-bridge","android","android-automation","cloud-phone","device-automation","kotlin-android","mjpeg","mobile-testing","nodejs","qa-automation","react","remote-control","remote-desktop","rooted-android","uiautomator","vite","websocket"],"created_at":"2026-06-16T14:03:21.651Z","updated_at":"2026-06-16T14:03:22.685Z","avatar_url":"https://github.com/borankux.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Android Remote Control\n\nAndroid Remote Control is an open-source remote control stack for rooted Android devices and cloud phones. It combines a lightweight Kotlin Android app, a token-protected Node.js relay, a React web console, and local CLI helpers for controlled Android automation.\n\nThe project is designed for owned devices, lab devices, cloud phones, QA automation, device diagnostics, and remote Android operations where you need screenshots, UI dumps, taps, swipes, text input, app launch, and optional ADB bridging without exposing a public ADB port.\n\n\u003cp\u003e\n  \u003cimg src=\"docs/images/web-console-preview.png\" alt=\"Android remote control web console with cloud phone preview, Root API controls, MJPEG screen stream, device status, action log, and copy-ready Agent prompt\" width=\"100%\"\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n  \u003cimg src=\"docs/images/android-app-dashboard.png\" alt=\"Kotlin Android cloud phone inspector app showing relay online status, root ready status, ADB status, JSON copy, and remote control channel diagnostics\" width=\"360\"\u003e\n\u003c/p\u003e\n\n## Keywords\n\nandroid remote control, android automation, rooted android controller, cloud phone control, android adb bridge, android mjpeg streaming, android device dashboard, remote android screenshots, uiautomator dump, kotlin android diagnostics, node websocket relay, react device console\n\n## What It Includes\n\n- **Android app**: Kotlin + XML/View app that connects back to a relay, reports device diagnostics, checks root, handles whitelisted control commands, captures screenshots, dumps UI XML, and opens an ADB tunnel when enabled.\n- **Relay server**: Node.js HTTP/WebSocket service that registers devices, accepts token-authenticated commands, streams MJPEG previews, and bridges local ADB traffic through WebSocket.\n- **Web console**: Vite + React dashboard for device lists, live-ish screen preview, action logs, screenshots, UI dumps, and copy-ready Agent instructions.\n- **CLI helpers**: Local Node scripts for calling the Root API and exposing an ADB bridge on `localhost`.\n\n## Core Capabilities\n\n- Device inventory and heartbeat status\n- Root availability checks\n- System diagnostics and JSON report generation\n- Screenshot capture as PNG/JPEG/WebP\n- MJPEG browser preview with adaptive quality\n- UI XML dump through uiautomator\n- Whitelisted input actions: tap, long press, swipe, back, home, input text, clear text\n- App launch through a server-side package allowlist\n- Optional ADB bridge over token-protected WebSocket\n- Web console with device list, phone preview, action log, and Agent prompt copy\n\n## Safety Model\n\nThis repository does **not** provide an arbitrary shell API. Commands are fixed and whitelisted. The relay requires a shared token, and ADB is tunneled through the relay instead of opening a public ADB port.\n\nUse this only on devices you own or are authorized to control. Do not use it for stealth control, unauthorized automation, credential theft, or bypassing platform policies.\n\n## Repository Layout\n\n```text\napp/                    Kotlin Android app\ncloudphone-relay/       Node.js relay server\ncloudphone-console/     React web console\ntools/                  Local Root API and ADB bridge helpers\ngradle/                 Android Gradle wrapper\n```\n\n## Configuration\n\nDo not hardcode production URLs or tokens into source code. Use environment variables or Gradle properties.\n\n### Android build config\n\nPass these values through environment variables or Gradle properties:\n\n```bash\nexport CLOUDPHONE_RELAY_URL='wss://your-domain.example/cloudphone-relay/ws/device'\nexport CLOUDPHONE_RELAY_TOKEN='replace-with-a-long-random-token'\nexport CLOUDPHONE_UPDATE_HOST='your-domain.example'\n\n./gradlew assembleDebug\n```\n\nThe app reads:\n\n- `CLOUDPHONE_RELAY_URL`: device WebSocket endpoint\n- `CLOUDPHONE_RELAY_TOKEN`: shared relay token\n- `CLOUDPHONE_UPDATE_HOST`: host allowed for self-update APK downloads\n\n### Relay server\n\n```bash\ncd cloudphone-relay\nnpm install\n\nexport RELAY_TOKEN='replace-with-a-long-random-token'\nexport PORT='18088'\nexport UPDATE_URL_PREFIX='https://your-domain.example/download/'\n\nnpm start\n```\n\nRelay endpoints:\n\n- `GET /health`\n- `GET /devices`\n- `POST /commands`\n- `GET /commands/{id}`\n- `GET /stream/mjpeg/{deviceId}`\n- `GET /adb/tunnels`\n- WebSocket `/ws/device/{deviceId}`\n- WebSocket `/adb/client/{deviceId}`\n- WebSocket `/adb/device/{deviceId}/{tunnelId}`\n\n### Web console\n\n```bash\ncd cloudphone-console\nnpm install\nnpm run build\n```\n\nDeploy `cloudphone-console/dist` under your web root, for example:\n\n```text\nhttps://your-domain.example/cloudphone-console/#token=\u003crelay-token\u003e\n```\n\nThe console calls the relay through the same origin path:\n\n```text\n/cloudphone-relay/*\n```\n\n## CLI Usage\n\nSet connection variables:\n\n```bash\nexport CLOUDPHONE_RELAY_URL='https://your-domain.example/cloudphone-relay'\nexport CLOUDPHONE_RELAY_WS_URL='wss://your-domain.example/cloudphone-relay'\nexport CLOUDPHONE_RELAY_TOKEN='replace-with-a-long-random-token'\nexport CLOUDPHONE_DEVICE_ID='your-device-id'\n```\n\nCall the Root API:\n\n```bash\nnode tools/cloudphone-api-client.mjs devices\nnode tools/cloudphone-api-client.mjs cmd snapshot\nnode tools/cloudphone-api-client.mjs cmd launch_xhs\nnode tools/cloudphone-api-client.mjs cmd screencap '{\"format\":\"jpeg\",\"maxWidth\":540,\"quality\":65}'\nnode tools/cloudphone-api-client.mjs cmd dump_ui\nnode tools/cloudphone-api-client.mjs cmd tap '{\"x\":360,\"y\":720}'\nnode tools/cloudphone-api-client.mjs cmd swipe '{\"x1\":360,\"y1\":1050,\"x2\":360,\"y2\":420,\"durationMs\":450}'\nnode tools/cloudphone-api-client.mjs cmd input_text '{\"text\":\"hello\"}'\nnode tools/cloudphone-api-client.mjs cmd wait_for_text '{\"text\":\"Search\",\"timeoutMs\":5000}'\n```\n\nStart an ADB bridge:\n\n```bash\nnode tools/cloudphone-api-client.mjs cmd adb_enable\nnode tools/cloudphone-api-client.mjs cmd adb_status\nnode tools/adb-bridge-client.mjs --device \"$CLOUDPHONE_DEVICE_ID\" --port 15555\nadb connect localhost:15555\nadb shell wm size\n```\n\n## Agent Prompt Support\n\nThe web console can copy a complete Agent prompt for the selected device. It includes the relay URL, token usage, device ID, command protocol, Root API command list, CLI examples, ADB bridge instructions, recommended control flow, and safety boundaries. This lets another AI Agent connect and operate without guessing the API.\n\n## Command Protocol\n\nCreate a command:\n\n```http\nPOST /cloudphone-relay/commands\nContent-Type: application/json\nx-relay-token: \u003crelay-token\u003e\n```\n\n```json\n{\n  \"deviceId\": \"your-device-id\",\n  \"name\": \"screencap\",\n  \"params\": {\n    \"format\": \"jpeg\",\n    \"maxWidth\": 540,\n    \"quality\": 65\n  }\n}\n```\n\nPoll the command result:\n\n```text\nGET /cloudphone-relay/commands/{id}\n```\n\nCommand status is one of:\n\n- `queued`\n- `sent`\n- `completed`\n- `failed`\n- `offline`\n\n## Notes\n\n- Root is required for most control commands.\n- MJPEG preview is built on repeated screenshots; it is useful for observation but is not a replacement for hardware video encoding.\n- ADB bridge support depends on the device allowing root control over `adbd`.\n- Package launch is intentionally allowlisted in the relay server.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fborankux%2Fandroid-remote-control","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fborankux%2Fandroid-remote-control","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fborankux%2Fandroid-remote-control/lists"}