Skip to content

WilsonFung418/lobster-remote

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LobsterRemote 🦐

Android universal remote control app that lets Wilson control his phone via OpenClaw.

Features

  • WebSocket Client - Connects to OpenClaw gateway for command reception
  • Accessibility Service - Tap, scroll, and type on any app
  • MediaProjection - Screen capture capability
  • Notification Listener - Read and reply to notifications
  • Task Queue - Sequential command execution
  • Kill Switch - Shake phone 5 times to disconnect
  • Self-Update - Automatic updates via GitHub releases

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    OpenClaw Gateway                         β”‚
β”‚                    (WebSocket Server)                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚ JSON Commands
                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 LobsterRemote Android App                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ WebSocket   β”‚  β”‚ Task Queue  β”‚  β”‚ Command Executor     β”‚ β”‚
β”‚  β”‚ Client      │──▢│ (Sequential)│──▢│ (tap/scroll/type)   β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚         β”‚                                        β”‚          β”‚
β”‚         β–Ό                                        β–Ό          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Auth        β”‚                       β”‚ Accessibility   β”‚  β”‚
β”‚  β”‚ Validation  β”‚                       β”‚ Service         β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚         β”‚                                        β”‚          β”‚
β”‚         β”‚                                        β–Ό          β”‚
β”‚         β”‚                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚         β”‚                              β”‚ MediaProjection β”‚ β”‚
β”‚         β”‚                              β”‚ (Screenshot)    β”‚ β”‚
β”‚         β”‚                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚         β”‚                                        β”‚          β”‚
β”‚         β–Ό                                        β–Ό          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚ Notification Listener Service                        β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Command Protocol

Commands are sent as JSON over WebSocket:

{"action": "open_app", "package": "com.foodpanda.android"}
{"action": "tap", "x": 500, "y": 300}
{"action": "type", "text": "pizza"}
{"action": "scroll", "direction": "down"}
{"action": "screenshot"}
{"action": "notification", "title": "Reminder", "text": "Meeting at 3pm"}
{"action": "dial", "number": "+85261234567"}

Response Format

{"id": "cmd_123", "success": true, "data": {"action": "tap"}}
{"id": "cmd_124", "success": false, "error": "App not found"}

Installation

Prerequisites

  • Android Studio Arctic Fox or newer
  • Android SDK 34 (Target) / 26 (Min)
  • Kotlin 1.9.20
  • Gradle 8.4

Build APK

# Clone / download project
cd lobster-remote

# Make gradlew executable
chmod +x gradlew

# Build debug APK
./gradlew assembleDebug

# Build release APK (requires signing config)
./gradlew assembleRelease

The APK will be at: app/build/outputs/apk/debug/app-debug.apk

Manual Installation

  1. Transfer app-debug.apk to your Android device
  2. Enable "Install from unknown sources" in Settings
  3. Install the APK
  4. Open Lobster Remote app

Permissions Required

  1. Accessibility Service - Required for tap/scroll/type actions

    • Settings > Accessibility > Lobster Remote > Enable
  2. Notification Listener - Required to read notifications

    • Settings > Apps > Special access > Notification access > Enable
  3. Screen Capture - Required for screenshots (requested on first connection)

  4. Phone - Required for dial action (optional)

Configuration

  1. Open Lobster Remote app
  2. Enter your OpenClaw gateway URL (e.g., ws://192.168.1.100:18789/ws)
  3. Enter your auth token
  4. Click "Save & Connect"
  5. Grant all required permissions

Security

  • All commands validated against OpenClaw auth token
  • Only accepts commands when authenticated
  • Shows persistent notification when active
  • Kill Switch: Shake phone 5 times rapidly to disconnect

Auto-Start

Enable "Auto-start on boot" to have the app reconnect automatically after device restart.

Self-Update

The app checks for updates every 12 hours from GitHub releases. To enable:

  1. Create a GitHub release at https://github.com/YOUR_USERNAME/lobster-remote/releases
  2. Upload the APK as a release asset
  3. Update the UPDATE_CHECK_URL in UpdateChecker.kt

Project Structure

lobster-remote/
β”œβ”€β”€ app/
β”‚   └── src/main/
β”‚       β”œβ”€β”€ java/com/lobsterremote/
β”‚       β”‚   β”œβ”€β”€ LobsterRemoteApp.kt        # Application class
β”‚       β”‚   β”œβ”€β”€ MainActivity.kt            # Settings UI
β”‚       β”‚   β”œβ”€β”€ model/
β”‚       β”‚   β”‚   └── RemoteCommand.kt       # Command models
β”‚       β”‚   β”œβ”€β”€ service/
β”‚       β”‚   β”‚   β”œβ”€β”€ RemoteService.kt       # Foreground service
β”‚       β”‚   β”‚   β”œβ”€β”€ LobsterAccessibilityService.kt
β”‚       β”‚   β”‚   └── NotificationInterceptorService.kt
β”‚       β”‚   β”œβ”€β”€ receiver/
β”‚       β”‚   β”‚   β”œβ”€β”€ ShakeDetectorReceiver.kt
β”‚       β”‚   β”‚   └── BootReceiver.kt
β”‚       β”‚   └── util/
β”‚       β”‚       β”œβ”€β”€ PermissionHelper.kt
β”‚       β”‚       └── UpdateChecker.kt
β”‚       └── res/
β”‚           β”œβ”€β”€ layout/activity_main.xml
β”‚           β”œβ”€β”€ xml/accessibility_service_config.xml
β”‚           └── values/
β”œβ”€β”€ build.gradle.kts
β”œβ”€β”€ settings.gradle.kts
└── gradle/wrapper/

Troubleshooting

"Accessibility service not enabled"

Go to Settings > Accessibility > Lobster Remote > Enable

"Notification listener not enabled"

Go to Settings > Apps > Special access > Notification access > Enable

"Screen capture permission denied"

Reconnect and grant the media projection permission when prompted

Connection keeps dropping

Check network connectivity and ensure the gateway URL is correct

License

MIT License - See LICENSE file

About

LobsterRemote - Android universal remote control app by Little Lobster 🦐

Resources

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors