- Add signing config (reads from env vars) - Enable R8 minification and resource shrinking - Expand ProGuard rules for Gson - Update README with build instructions and Play Store checklist
5.3 KiB
5.3 KiB
Tether API
Android app that exposes your phone's connection status via HTTP API, accessible from tethered devices.
Features
- Auto-start on tether: Server automatically starts/stops when tethering is enabled/disabled
- Real-time status: Connection type (5G/LTE/3G/WIFI), signal strength, carrier, battery level
- Simple REST API: JSON responses, easy to integrate with any client
- No root required: Works with standard Android permissions
Installation
Build with Android Studio or use the release APK.
Required permissions:
READ_PHONE_STATE- Network connection type and carrierACCESS_FINE_LOCATION- Required by Android 10+ for signal strengthPOST_NOTIFICATIONS- Service status notification
API Reference
Default port: 8765
Common gateway IPs when tethering:
- USB tethering:
192.168.42.1 - WiFi hotspot:
192.168.43.1
GET /status
Returns full phone status.
Response:
{
"connection": {
"type": "LTE",
"signal_dbm": -89,
"signal_bars": 3,
"carrier": "T-Mobile",
"operator": "310260",
"roaming": false
},
"battery": {
"level": 73,
"charging": false
},
"network": {
"wifi_ssid": null,
"ip_addresses": ["192.168.42.129"]
},
"timestamp": 1702915200
}
Fields:
| Field | Description |
|---|---|
connection.type |
5G, LTE, HSPA, 3G, 2G, WIFI, CELLULAR, NONE |
connection.signal_dbm |
Signal strength in dBm (-999 if unavailable) |
connection.signal_bars |
0-4 signal bars |
connection.carrier |
Network operator name |
connection.operator |
MCC+MNC code |
connection.roaming |
Whether roaming is active |
battery.level |
Battery percentage (0-100) |
battery.charging |
Whether device is charging |
network.wifi_ssid |
WiFi SSID if connected via WiFi |
network.ip_addresses |
List of device IP addresses |
timestamp |
Unix timestamp of response |
GET /health
Health check endpoint.
Response:
{"status": "ok"}
GET /
API information.
Response:
{
"name": "Tether API",
"version": "1.0.0",
"endpoints": [
{"path": "/status", "method": "GET", "description": "Get phone status"},
{"path": "/health", "method": "GET", "description": "Health check"}
]
}
Client Examples
Basic curl
curl http://192.168.42.1:8765/status
Auto-discover phone IP
#!/bin/bash
for ip in 192.168.42.1 192.168.43.1 192.168.44.1; do
if curl -s --connect-timeout 1 "http://$ip:8765/health" | grep -q "ok"; then
echo "$ip"
exit 0
fi
done
exit 1
Waybar module
~/.config/waybar/config:
{
"custom/phone": {
"exec": "~/.local/bin/phone-status.sh",
"return-type": "json",
"interval": 10,
"format": "{}"
}
}
~/.local/bin/phone-status.sh:
#!/bin/bash
PHONE_IP="${PHONE_IP:-192.168.42.1}"
PORT="${PORT:-8765}"
status=$(curl -s --connect-timeout 2 "http://$PHONE_IP:$PORT/status")
if [ -z "$status" ]; then
echo '{"text": "N/A", "tooltip": "Phone not connected", "class": "disconnected"}'
exit 0
fi
type=$(echo "$status" | jq -r '.connection.type')
bars=$(echo "$status" | jq -r '.connection.signal_bars')
battery=$(echo "$status" | jq -r '.battery.level')
case $bars in
4) signal="▂▄▆█" ;;
3) signal="▂▄▆░" ;;
2) signal="▂▄░░" ;;
1) signal="▂░░░" ;;
*) signal="░░░░" ;;
esac
echo "{\"text\": \"$type $signal $battery%\", \"tooltip\": \"$type | Signal: $bars/4 | Battery: $battery%\", \"class\": \"$type\"}"
Python client
import requests
def get_phone_status(ip="192.168.42.1", port=8765):
try:
r = requests.get(f"http://{ip}:{port}/status", timeout=2)
return r.json()
except:
return None
status = get_phone_status()
if status:
print(f"Connection: {status['connection']['type']}")
print(f"Signal: {status['connection']['signal_bars']}/4")
print(f"Battery: {status['battery']['level']}%")
KDE Plasmoid / Generic widget
Most desktop widgets can execute shell commands. Use the curl/jq approach:
curl -s http://192.168.42.1:8765/status | jq -r '"\(.connection.type) \(.connection.signal_bars)/4 \(.battery.level)%"'
Building
Debug build
./gradlew assembleDebug
# Output: app/build/outputs/apk/debug/app-debug.apk
Release build
- Generate a keystore:
keytool -genkey -v -keystore keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias release
- Build with signing:
export KEYSTORE_PASSWORD="your-password"
export KEY_ALIAS="release"
export KEY_PASSWORD="your-key-password"
./gradlew assembleRelease
# Output: app/build/outputs/apk/release/app-release.apk
Play Store Publishing
Still needed:
- App icons - Replace placeholder icons in
app/src/main/res/mipmap-*with proper 512x512 adaptive icons - Privacy policy - Required URL (app uses location permission)
- Screenshots - Phone screenshots for Play Store listing
- Feature graphic - 1024x500 banner image
- Store description - Short and full descriptions
Already configured:
- Release signing config
- ProGuard/R8 minification
- Target SDK 36 (meets Play Store requirements)
License
MIT