A headless Android launcher designed for digital signage, kiosks, and remote displays. Controls application execution via a local HTTP API or browser-based control panel.
- REST API endpoints for programmatic application launching and intent execution.
- Embedded web interface for device management.
- Remote APK upload, installation, and package removal.
- Intent parameter passing (actions, data URIs, and extra key-value pairs).
Caution
This application has NO built-in authentication or encryption. The web server runs on port 9091 with unrestricted access to network clients.
❌ DO NOT expose this app directly to the internet
❌ DO NOT port forward port 9091
❌ DO NOT deploy on untrusted networks
❌ DO NOT assume any built-in security controls exist
- Android 7.0 (API 24) or higher.
- Android 14+ recommended for full foreground service type compliance.
- Install the APK package on the target device.
- Launch the application locally.
- Press D-Pad DOWN 3 times rapidly (or tap the center of the screen 3 times within 1 second) to invoke the settings UI.
- Select "Set as Default Launcher" to register the app as the system home handler.
To open the settings interface on a headless display:
- Return to the home screen (renders a black background).
- Press D-Pad DOWN 3 times quickly (or tap the center of the display 3 times within 1 second).
- Select "Hide UI" to return to headless mode.
Access the control panel from any HTTP client on the local network:
http://[device-ip-address]:9091
GET http://[device-ip]:9091/api/appsResponse:
[
{
"name": "Chrome",
"packageName": "com.android.chrome"
}
]POST http://[device-ip]:9091/api/launch
Content-Type: application/json
{
"packageName": "com.android.chrome"
}POST http://[device-ip]:9091/api/launch-intent
Content-Type: application/json
{
"packageName": "com.tpn.streamviewer",
"action": "android.intent.action.MAIN",
"extra_string": "camera_name:FRONTDOOR"
}Intent Payload Parameters:
| Field | Type | Description |
|---|---|---|
packageName |
String | Target package identifier (required). |
action |
String | Intent action string (e.g., android.intent.action.VIEW). |
data |
String | Intent data URI string. |
extra_string |
String | Comma-separated key-value pairs for intent extras (key:value). |
POST http://[device-ip]:9091/api/uninstall
Content-Type: application/json
{
"packageName": "com.example.app"
}POST http://[device-ip]:9091/api/upload-apk
Content-Type: multipart/form-data- Default Home Requirement: Must be registered as the default home launcher to ensure proper foreground task switching.
- Local Network Scope: Restricted to local network interfaces; lacks TLS/HTTPS support.
- User Prompts: Package installation and removal actions require manual confirmation via system dialogs on the physical display.
- Service Persistence: Ensure battery optimization is disabled for the application if the OS terminates the background service.
- Network Validation: Verify interface connectivity and local port availability (
9091). - Logcat Verification: Inspect logs using
adb logcat | grep DisplayLauncher.
# Launch Chrome
curl -X POST [http://192.168.1.100:9091/api/launch](http://192.168.1.100:9091/api/launch) -H "Content-Type: application/json" -d '{"packageName":"com.android.chrome"}'
# Launch Intent with Extras
curl -X POST [http://192.168.1.100:9091/api/launch-intent](http://192.168.1.100:9091/api/launch-intent) -H "Content-Type: application/json" -d '{"packageName":"com.tpn.streamviewer","action":"android.intent.action.MAIN","extra_string":"camera_name:FRONTDOOR"}'import requests
requests.post('[http://192.168.1.100:9091/api/launch](http://192.168.1.100:9091/api/launch)', json={'packageName': 'com.android.chrome'})- API Reference - Detailed REST API endpoint specification.
- Home Assistant Integration Guide - Integration examples for automation platforms.