docs: move BUG_REPORT.md to docs/

This commit is contained in:
fiatcode 2026-04-30 16:51:02 +07:00
parent 33935de4f2
commit 369ac49602
No known key found for this signature in database

View file

@ -1,178 +0,0 @@
# Traccar Client Bug Report: Location Data Not Reaching Server
**Date**: April 30, 2026
**Status**: Investigating
## Issue Summary
The Traccar Client app shows the device as **always offline** and no location reports reach the self-hosted Traccar server, even when:
- The correct Device ID is set and registered on the server
- The correct Server URL is configured
- The tracking toggle is ON
- The "Send Location" button appears to work
## Root Causes Identified
### Critical Bugs
#### 1. Heartbeat Never Fires (Process Isolation Issue)
**File**: `lib/bridge/location_bridge.dart` (Dart) and `android/app/src/main/kotlin/com/traccar/traccar_client/location/HeartbeatScheduler.kt`
**Problem**: The `HeartbeatWorker` runs in a separate process via Android WorkManager. When it executes, the static `onHeartbeatCallback` variable is always `null` because companion object static variables are not shared across process boundaries.
```kotlin
// HeartbeatScheduler.kt
class HeartbeatWorker(...) : Worker(...) {
override fun doWork(): Result {
onHeartbeatCallback?.invoke() // Always null!
return Result.success()
}
}
companion object {
var onHeartbeatCallback: (() -> Unit)? = null // Not shared across processes
}
```
**Impact**: Heartbeat locations are never sent, causing the device to appear offline after initial connection wears off.
---
#### 2. ConnectivityReceiver Never Registered
**File**: `android/app/src/main/kotlin/com/traccar/traccar_client/service/LocationTrackingService.kt`
**Problem**: The `ConnectivityReceiver` is created in `onCreate()` but **never registered** with the system. The code creates the receiver but doesn't call `registerReceiver()`.
```kotlin
// LocationTrackingService.kt - onCreate()
connectivityReceiver = ConnectivityReceiver { online ->
isNetworkAvailable = online
logEvent("NETWORK_CHANGE", "Network: ${if (online) "online" else "offline"}")
if (online) syncBufferedLocations()
}
// MISSING: registerReceiver(connectivityReceiver, intentFilter)
```
**Impact**:
- Network state is never detected
- When the app goes offline, buffered locations are never synced when connectivity returns
- App never knows if it's online or offline
---
#### 3. Timestamp Format Mismatch
**File**: `android/app/src/main/kotlin/com/traccar/traccar_client/network/TraccarHttpClient.kt`
**Problem**: The code sends timestamps as epoch milliseconds (e.g., `1704067200000`), but Traccar expects **ISO 8601 format** (e.g., `2024-01-01T00:00:00.000Z`).
```kotlin
// TraccarHttpClient.kt:55-61
return "$baseUrl/?" +
// ...
"&timestamp=$timestamp" // Sends: 1704067200000
// Should send: 2024-01-01T00:00:00.000Z
```
**Impact**: Server may ignore or misinterpret timestamps, causing positions to not appear correctly on the timeline or be rejected entirely.
---
### Important Bugs (From Code Review)
#### 4. Memory Leak - Stream Subscription Never Cancelled
**File**: `lib/main_screen.dart:52-67`
```dart
Future<void> _initLocationStream() async {
// ...
LocationBridge.locationUpdates.listen((location) { // Subscription created
// ...
});
// MISSING: dispose() never cancels this subscription
}
```
**Impact**: Memory leak that accumulates over time, especially when navigating away and back to the screen.
---
#### 5. Settings Number Fields Never Save
**File**: `lib/settings_screen.dart:149-174`
**Problem**: `_buildNumberField()` uses `initialValue` (which creates an internal controller) and `onSaved` callback. However, `_saveSettings()` never calls `formKey.currentState.save()`, so the `onSaved` callbacks at lines 161-172 **never execute**.
```dart
// settings_screen.dart
Future<void> _saveSettings() async {
await Preferences.setServerUrl(_serverUrlController.text);
await Preferences.setDeviceId(_deviceIdController.text);
// ... number fields use onSaved but form.save() is never called!
await LocationBridge.updateConfig({...});
}
```
**Impact**: Distance Filter, Update Interval, and Heartbeat settings are silently ignored when saving. The UI shows the new values but they aren't persisted.
---
#### 6. Distance Filter May Block All Updates
**File**: `lib/bridge/location_bridge.dart` (Android side: `DistanceFilterProcessor.kt`)
**Problem**: With default `distanceFilter = 75` meters, if the device is stationary or moving less than 75m, **all locations are filtered out**. The `intervalFilter` only serves as a fallback when distance filter would reject, not as a primary interval mechanism.
**Impact**: Stationary devices or devices in slow-moving traffic may not send any location updates.
---
## Verification Steps
To diagnose where the flow breaks, check the **Status/Logs** screen in the app:
| Log Entry | Color | Meaning |
|-----------|-------|---------|
| `LOCATION` | Green | Location received from GPS |
| `SYNC` | Cyan | Location successfully sent to server |
| `ERROR` | Red | Failed to send location |
| `FILTERED` | Grey | Location rejected by distance/interval filter |
| `NETWORK_CHANGE` | White | Network state changed |
**Questions**:
1. Do you see `LOCATION` entries?
2. Do you see `SYNC` entries after `LOCATION`?
3. Do you see any `ERROR` entries?
4. Do you see `NETWORK_CHANGE` entries?
---
## Files Affected
### Dart/Flutter Files
- `lib/main_screen.dart` - Memory leak, optimistic toggle
- `lib/settings_screen.dart` - Number fields not saving
- `lib/status_screen.dart` - OK
- `lib/preferences.dart` - OK
- `lib/bridge/location_bridge.dart` - OK
- `lib/main.dart` - OK
### Android/Kotlin Files
- `android/.../location/HeartbeatScheduler.kt` - Heartbeat never fires
- `android/.../service/LocationTrackingService.kt` - ConnectivityReceiver not registered
- `android/.../network/TraccarHttpClient.kt` - Timestamp format wrong
---
## Summary
The device appears offline because:
1. **Heartbeat locations are never sent** - WorkManager process isolation breaks the callback mechanism
2. **Buffered locations are never synced** - ConnectivityReceiver was never registered
3. **Timestamps may be malformed** - Server may reject positions due to timestamp format
**Recommendation**: Fix the three critical bugs (Heartbeat, ConnectivityReceiver, Timestamp) first, then re-test. Check the Status/Logs screen to confirm which stage the flow is breaking at.