Kotlin SDK Integration Guide
Integrate WatchTower monitoring into your Android POS terminal app in under 15 minutes. The SDK handles gRPC connection, heartbeats, GPS tracking, offline queuing, and reconnection automatically.Requirements
- Android 5.0+ (API 21+)
- No Google Play Services required (works on AOSP terminals)
- An agent API key from the WatchTower dashboard
Step 1: Add the Dependency
Add the WatchTower SDK to your app’sbuild.gradle.kts:
Step 2: Add Permissions
The SDK needs these permissions in yourAndroidManifest.xml:
Note: If your app already has these permissions (most POS apps do), no changes needed.
Step 3: Initialize the Agent
Create the agent in your Application class or main Activity:Step 4: Handle Platform Commands
ImplementAgentCallback to react to commands from the WatchTower platform:
Step 5: Report Transactions
After each payment transaction completes, report it to WatchTower:reportTransaction() automatically queues the transaction in local SQLite. When the connection is restored, queued transactions are flushed automatically (oldest first).
Step 6: Manual Controls (Optional)
Configuration Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
serverHost | String | (required) | WatchTower gRPC server hostname |
serverPort | Int | 9090 | gRPC server port |
apiKey | String | (required) | Agent API key (wt_agent_*) |
terminalId | String | (required) | Terminal serial number |
useTls | Boolean | true | Use TLS for gRPC connection |
heartbeatIntervalSeconds | Int | 30 | Heartbeat frequency in seconds |
gpsEnabled | Boolean | true | Enable GPS location tracking |
offlineQueueEnabled | Boolean | true | Queue transactions when offline |
maxOfflineQueueSize | Int | 10000 | Max queued events before oldest are dropped |
reconnectEnabled | Boolean | true | Auto-reconnect on disconnect |
reconnectMinDelayMs | Long | 1000 | Minimum reconnect backoff (ms) |
reconnectMaxDelayMs | Long | 60000 | Maximum reconnect backoff (ms) |
How Heartbeats Work
The SDK automatically sends heartbeats at the configured interval. Each heartbeat includes:| Field | Source | Notes |
|---|---|---|
| GPS coordinates | LocationManager or FusedLocationProvider | Falls back gracefully if unavailable |
| Battery percentage | BatteryManager | Reads current battery level |
| Signal strength | TelephonyManager | Cellular signal strength |
| Uptime | System clock | Seconds since agent started |
- Google
FusedLocationProviderClient(if Play Services available — better accuracy) - Android
LocationManagerwithGPS_PROVIDER(works on all AOSP devices) - Android
LocationManagerwithNETWORK_PROVIDER(fallback) - No location (heartbeats sent without GPS if all providers fail)
Offline Queue
When the terminal loses connectivity:- Transactions are queued in local SQLite (
watchtower_queue.db) - Heartbeats are NOT queued (stale heartbeats are useless)
- Queue is FIFO — oldest transactions sent first on reconnect
- Max queue size is configurable (default 10,000)
- When the queue is full, oldest events are dropped
- Queue is flushed before normal operations resume
onQueueFlushed(count)callback fires with the number of flushed events- Regular heartbeats and transaction reporting continue
Reconnection Behavior
When the gRPC connection drops:onDisconnected(reason)callback fires- SDK waits with exponential backoff: 1s → 2s → 4s → 8s → … → 60s (capped)
- Random jitter (0-500ms) added to prevent all terminals reconnecting simultaneously
onReconnecting(attempt, delayMs)fires before each attempt- On successful reconnect:
onConnected()fires, offline queue is flushed - Backoff resets to 1s on successful connection
Threading
- All callbacks are dispatched on the Android main thread — safe to update UI directly
- gRPC operations run on background IO threads
- SQLite operations run on background threads
- No threading concerns for your app code
Testing with the WatchTower Test Agent
Before integrating the SDK, you can test your WatchTower setup using the CLI test agent:Troubleshooting
Agent won’t connect:- Verify the API key is correct and has
agentscope - Verify the terminal serial number matches what’s registered in WatchTower
- Check network connectivity and firewall rules (gRPC uses port 9090)
- For local development, set
useTls = false
- Ensure
ACCESS_FINE_LOCATIONpermission is granted at runtime (Android 6.0+) - Check that GPS is enabled in device settings
- The SDK falls back gracefully — heartbeats still send without GPS
- Check
onErrorcallback for errors - If offline, transactions are queued — they’ll appear after reconnect
- Verify the terminal is registered and active in WatchTower
- The terminal must be connected (gRPC stream active)
- If the terminal was offline when blocked, it will see the blocked status on next API query
- Check
onBlockCommandcallback implementation