Skip to content

Commit 7e0f8b6

Browse files
sprobst76claude
andcommitted
docs: add geofence troubleshooting and bug report
- Add help dialog to Geofence Debug Screen explaining common issues - Create detailed bug report for geofence_foreground_service package - Document alternative packages (native_geofence, flutter_background_geolocation) - Explain battery optimization requirement Bug Report: docs/GEOFENCE_SERVICE_BUG_REPORT.md Alternatives: docs/GEOFENCE_ALTERNATIVES.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0907667 commit 7e0f8b6

File tree

5 files changed

+392
-1
lines changed

5 files changed

+392
-1
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
1414

1515
---
1616

17+
## [0.1.0-beta.34] - 2026-01-22
18+
19+
### Hinzugefügt
20+
- **Hilfe-Dialog im Geofence Debug**: Erklärt häufige Probleme und Lösungen
21+
- Warum Arbeitszeit nicht automatisch erfasst wird
22+
- Bedeutung der Akkuoptimierung
23+
- Bekanntes Package-Problem dokumentiert
24+
- Debug-Informationen erklärt
25+
26+
### Dokumentation
27+
- Bug Report für geofence_foreground_service Package erstellt
28+
- Alternativen-Analyse dokumentiert (native_geofence, flutter_background_geolocation)
29+
30+
---
31+
1732
## [0.1.0-beta.33] - 2026-01-22
1833

1934
### Hinzugefügt

docs/GEOFENCE_ALTERNATIVES.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Geofence Package Alternativen für VibedTracker
2+
3+
## Aktuelles Problem
4+
5+
Das aktuelle Package `geofence_foreground_service` (v1.1.5) hat einen kritischen Bug:
6+
- Service crasht mit NullPointerException wenn Android ihn nach Memory-Pressure neu startet
7+
- Geofencing fällt für 46+ Minuten aus nach jedem Crash
8+
9+
---
10+
11+
## Alternative Packages
12+
13+
### 1. native_geofence (Empfohlen)
14+
15+
**pub.dev:** https://pub.dev/packages/native_geofence
16+
17+
**Vorteile:**
18+
- Basiert auf demselben Konzept, aber aktiver maintained
19+
- Nutzt native iOS (CLLocationManager) und Android (GeofencingClient) APIs
20+
- Erlaubt Customizing der Foreground Service Notification
21+
- Wake Lock Duration konfigurierbar
22+
- Battery-effizient
23+
24+
**Nachteile:**
25+
- Erfordert iOS 14+ und Android API 29+
26+
- Flutter + Kotlin 2+ Kompatibilitätsprobleme (Jan 2025)
27+
28+
**Migration Aufwand:** Mittel - ähnliche API wie geofence_foreground_service
29+
30+
```yaml
31+
dependencies:
32+
native_geofence: ^1.0.0
33+
```
34+
35+
---
36+
37+
### 2. flutter_background_geolocation (Transistorsoft)
38+
39+
**Website:** https://www.transistorsoft.com/shop/products/flutter-background-geolocation
40+
41+
**Vorteile:**
42+
- Professionell maintained, sehr robust
43+
- Sophisticated motion-detection intelligence
44+
- Unlimited Geofences (bis 100 pro Device wegen Google-Limit)
45+
- Polygon Geofences unterstützt
46+
- Überlebt Device Reboot und App Terminate
47+
- Beste Battery-Effizienz
48+
49+
**Nachteile:**
50+
- **Kommerziell** - Lizenz erforderlich für Production
51+
- Komplexere Integration
52+
53+
**Migration Aufwand:** Hoch - andere API, aber robuster
54+
55+
---
56+
57+
### 3. Radar.io SDK
58+
59+
**Docs:** https://docs.radar.com/sdk/flutter
60+
61+
**Vorteile:**
62+
- Cloud-basiertes Geofencing
63+
- Analytics und Insights
64+
- Server-side Geofence Management
65+
66+
**Nachteile:**
67+
- Benötigt Cloud-Account
68+
- Datenschutz-Bedenken (Standort geht an Drittanbieter)
69+
- Overkill für einfache Use Cases
70+
71+
**Migration Aufwand:** Hoch - komplett anderes Konzept
72+
73+
---
74+
75+
### 4. DIY: WorkManager + Location Polling
76+
77+
**Konzept:** Eigene Implementierung mit `workmanager` + `geolocator`
78+
79+
**Vorteile:**
80+
- Volle Kontrolle
81+
- Kein Dependency auf externe Packages
82+
- Kann spezifisch für unsere Needs optimiert werden
83+
84+
**Nachteile:**
85+
- Mehr Entwicklungsaufwand
86+
- Battery-Effizienz muss selbst optimiert werden
87+
- Kein echtes Geofencing, nur periodisches Polling (alle 15 min)
88+
89+
**Migration Aufwand:** Sehr hoch - komplett neu implementieren
90+
91+
---
92+
93+
## Empfehlung
94+
95+
### Kurzfristig (jetzt):
96+
1. **Workaround nutzen:** Akkuoptimierung deaktivieren
97+
2. **Bug Report** an geofence_foreground_service Maintainer senden
98+
3. Warten auf Fix
99+
100+
### Mittelfristig (wenn kein Fix kommt):
101+
1. **Migration zu `native_geofence`** - ähnlichste API, aktiver maintained
102+
2. Oder: Package forken und selbst fixen
103+
104+
### Langfristig (wenn Budget vorhanden):
105+
1. **flutter_background_geolocation** evaluieren - professionellste Lösung
106+
107+
---
108+
109+
## Migration Checkliste (zu native_geofence)
110+
111+
- [ ] pubspec.yaml updaten
112+
- [ ] GeofenceService.dart anpassen
113+
- [ ] GeofenceCallback.dart anpassen
114+
- [ ] AndroidManifest.xml Permissions prüfen
115+
- [ ] iOS Info.plist Permissions prüfen
116+
- [ ] Notification Channel anpassen
117+
- [ ] Testen auf Android und iOS
118+
119+
---
120+
121+
## Referenzen
122+
123+
- [Flutter Geolocation Packages](https://fluttergems.dev/geolocation-utilities/)
124+
- [native_geofence Docs](https://pub.dev/documentation/native_geofence/latest/)
125+
- [Geofencing in Flutter (Medium)](https://medium.com/@m5lk3n/geofencing-in-flutter-f610cb212964)
126+
- [Flutter Background Processes](https://docs.flutter.dev/packages-and-plugins/background-processes)
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Bug Report: NullPointerException in GeofenceForegroundService.onStartCommand
2+
3+
## Package
4+
- **Name:** geofence_foreground_service
5+
- **Version:** 1.1.5
6+
- **Repository:** https://github.com/Basel-525k/geofence_foreground_service
7+
8+
## Issue Summary
9+
10+
When Android restarts the `GeofenceForegroundService` after it was killed due to memory pressure, the service crashes with a `NullPointerException` because the `intent` parameter in `onStartCommand` is null.
11+
12+
## Environment
13+
14+
- **Device:** Google Pixel (Android 14/15)
15+
- **Flutter:** 3.x
16+
- **Package Version:** 1.1.5
17+
18+
## Steps to Reproduce
19+
20+
1. Start the geofence service with `startGeofencingService()`
21+
2. Register geofence zones
22+
3. Put the app in background
23+
4. Wait for Android to kill the service due to memory pressure (or use `adb shell am kill <package>`)
24+
5. Observe the service crash when Android tries to restart it
25+
26+
## Expected Behavior
27+
28+
The service should handle null intents gracefully and either:
29+
- Return `START_STICKY` to retry later
30+
- Restore state from SharedPreferences and continue
31+
32+
## Actual Behavior
33+
34+
The service crashes with:
35+
36+
```
37+
java.lang.RuntimeException: Unable to start service com.f2fk.geofence_foreground_service.GeofenceForegroundService@... with null
38+
39+
Caused by: java.lang.NullPointerException: Parameter specified as non-null is null: method com.f2fk.geofence_foreground_service.GeofenceForegroundService.onStartCommand, parameter intent
40+
at com.f2fk.geofence_foreground_service.GeofenceForegroundService.onStartCommand(Unknown Source:2)
41+
```
42+
43+
After the crash, Android reschedules the restart with exponential backoff:
44+
```
45+
W ActivityManager: Rescheduling restart of crashed service ... in 2759775ms for mem-pressure-event
46+
```
47+
48+
This means the service is offline for **46+ minutes** after each crash!
49+
50+
## Root Cause
51+
52+
In `GeofenceForegroundService.kt`, line 73:
53+
54+
```kotlin
55+
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
56+
```
57+
58+
The `intent` parameter is declared as non-nullable (`Intent` instead of `Intent?`), but Android can pass `null` when restarting a service that uses `START_STICKY`.
59+
60+
From Android documentation:
61+
> If your service returns START_STICKY, the system restarts it with a **null intent** (unless there are pending intents to deliver).
62+
63+
## Proposed Fix
64+
65+
Change the method signature to accept nullable intent and handle it gracefully:
66+
67+
```kotlin
68+
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
69+
// Handle null intent (service restart after being killed)
70+
if (intent == null) {
71+
Log.w(TAG, "Service restarted with null intent - recovering from saved state")
72+
return recoverFromSavedState(flags, startId)
73+
}
74+
75+
// Existing code...
76+
val geofenceAction: GeofenceServiceAction = GeofenceServiceAction.valueOf(
77+
intent.getStringExtra(
78+
applicationContext!!.extraNameGen(Constants.geofenceAction)
79+
)!!
80+
)
81+
// ...
82+
}
83+
84+
private fun recoverFromSavedState(flags: Int, startId: Int): Int {
85+
// Option 1: Return START_STICKY to try again later
86+
// return START_STICKY
87+
88+
// Option 2: Restore from SharedPreferences and restart foreground notification
89+
val prefs = getSharedPreferences("geofence_service_state", Context.MODE_PRIVATE)
90+
if (!prefs.getBoolean("is_running", false)) {
91+
stopSelf()
92+
return START_NOT_STICKY
93+
}
94+
95+
val channelId = prefs.getString("channel_id", "default_channel")!!
96+
val contentTitle = prefs.getString("content_title", "Geofencing active")!!
97+
val contentText = prefs.getString("content_text", "Monitoring location")!!
98+
val serviceId = prefs.getInt("service_id", 525600)
99+
val appIcon = prefs.getInt("app_icon", android.R.drawable.ic_menu_mylocation)
100+
101+
val notification = NotificationCompat.Builder(this, channelId)
102+
.setOngoing(true)
103+
.setSmallIcon(appIcon)
104+
.setContentTitle(contentTitle)
105+
.setContentText(contentText)
106+
.build()
107+
108+
startForeground(serviceId, notification, FOREGROUND_SERVICE_TYPE_LOCATION)
109+
110+
// Re-subscribe to location updates
111+
subscribeToLocationUpdates()
112+
113+
return START_STICKY
114+
}
115+
```
116+
117+
Additionally, save the service state when starting:
118+
119+
```kotlin
120+
private fun saveServiceState(channelId: String, contentTitle: String, contentText: String, serviceId: Int, appIcon: Int) {
121+
getSharedPreferences("geofence_service_state", Context.MODE_PRIVATE)
122+
.edit()
123+
.putString("channel_id", channelId)
124+
.putString("content_title", contentTitle)
125+
.putString("content_text", contentText)
126+
.putInt("service_id", serviceId)
127+
.putInt("app_icon", appIcon)
128+
.putBoolean("is_running", true)
129+
.apply()
130+
}
131+
```
132+
133+
## Workaround for Users
134+
135+
Until this is fixed, users can disable battery optimization for their app:
136+
137+
1. Go to **SettingsApps → [Your App] → Battery**
138+
2. Select **Unrestricted** or **Don't optimize**
139+
140+
This prevents Android from killing the service due to memory pressure.
141+
142+
## Impact
143+
144+
- **Severity:** High - Geofencing becomes unreliable
145+
- **Affected users:** Anyone using the package on Android with memory pressure
146+
- **User experience:** Geofence events are missed for 46+ minutes after each crash
147+
148+
## Related
149+
150+
- Android Service lifecycle documentation: https://developer.android.com/reference/android/app/Service#START_STICKY
151+
- Similar issues in other packages handling foreground services
152+
153+
---
154+
155+
**Reported by:** VibedTracker App
156+
**Date:** 2026-01-22

0 commit comments

Comments
 (0)