transistorsoft / flutter_background_geolocation

Sophisticated, battery-conscious background-geolocation & geofencing with motion-detection
https://www.transistorsoft.com/shop/products/flutter-background-geolocation
Other
640 stars 237 forks source link

Android headless task doesn't start in some cases #892

Closed viplavrawal closed 1 year ago

viplavrawal commented 1 year ago

Your Environment

Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.3.6, on macOS 12.6 21G115 darwin-arm (Rosetta), locale en-GB) [!] Android toolchain - develop for Android devices (Android SDK version 30.0.2) ✗ cmdline-tools component is missing Run path/to/sdkmanager --install "cmdline-tools;latest" See https://developer.android.com/studio/command-line for more details. ✗ Android license status unknown. Run flutter doctor --android-licenses to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/macos#android-setup for more details. [✓] Xcode - develop for iOS and macOS (Xcode 14.1) [✓] Chrome - develop for the web [✓] Android Studio (version 2021.3) [✓] VS Code (version 1.73.1) [✓] Connected device (3 available) [✓] HTTP Host Availability

Expected Behavior

The service should start everytime

Actual Behavior

The service starts 50% of times, rest of the times we see the exception: [c.t.f.b.HeadlessTask startBackgroundIsolate] ‼️ Fatal: failed to find callback: -3461665204332439026

Steps to Reproduce

  1. Setup the code as per the example app
  2. Kill the app after service starts and geofences start getting triggered in app
  3. Expect service to start each time
  4. Background service only starts some times

Context

Trigger local notifications when user enters geofences

Debug logs

Logs ``` 12-01 13:32:25.559 14109 14307 I TSLocationManager: - Enable: false → true, trackingMode: 0 12-01 13:32:25.637 14109 14307 E TSLocationManager: [c.t.l.s.LocationRequestService handleStartAction] 12-01 13:32:25.637 14109 14307 E TSLocationManager: ‼️ Failed to find SingleLocationRequest in START action; requestId: 1; Intent: Intent { act=start cmp=com.milesandmore.android.dev/com.transistorsoft.locationmanager.service.LocationRequestService (has extras) } 12-01 13:34:00.367 16343 16458 I TSLocationManager: [c.t.l.logger.LoggerFacade$a a] 12-01 13:34:00.367 16343 16458 I TSLocationManager: ╔═════════════════════════════════════════════ 12-01 13:34:00.367 16343 16458 I TSLocationManager: ║ TSLocationManager version: 3.2.8 (414) 12-01 13:34:00.367 16343 16458 I TSLocationManager: ╠═════════════════════════════════════════════ 12-01 13:34:00.367 16343 16458 I TSLocationManager: ╟─ samsung SM-S901E @ 13 (flutter) 12-01 13:34:00.367 16343 16458 I TSLocationManager: { 12-01 13:34:00.367 16343 16458 I TSLocationManager: "activityRecognitionInterval": 10000, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "allowIdenticalLocations": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "authorization": {}, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "autoSync": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "autoSyncThreshold": 0, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "backgroundPermissionRationale": { 12-01 13:34:00.367 16343 16458 I TSLocationManager: "title": "Allow {applicationName} to also use your location even when you are not using the app?", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "message": "You don't have the Miles & More app permanently open but still don't want to miss any location-based offers? Select the \"Always allow\" option.", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "positiveAction": "Change to Always Allow", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "negativeAction": "Keep Only While Using" 12-01 13:34:00.367 16343 16458 I TSLocationManager: }, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "batchSync": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "configUrl": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "debug": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "deferTime": 0, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "desiredAccuracy": -1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "desiredOdometerAccuracy": 100, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "disableAutoSyncOnCellular": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "disableElasticity": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "disableLocationAuthorizationAlert": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "disableMotionActivityUpdates": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "disableProviderChangeRecord": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "disableStopDetection": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "distanceFilter": 0, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "elasticityMultiplier": 1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "enableHeadless": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "enableTimestampMeta": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "extras": {}, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "fastestLocationUpdateInterval": -1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "foregroundService": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "geofenceInitialTriggerEntry": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "geofenceModeHighAccuracy": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "geofenceProximityRadius": 1000, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "geofenceTemplate": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "headers": {}, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "headlessJobService": "com.transistorsoft.flutter.backgroundgeolocation.HeadlessTask", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "heartbeatInterval": -1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "httpRootProperty": "location", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "httpTimeout": 60000, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "isMoving": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "locationAuthorizationRequest": "Always", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "locationTemplate": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "locationTimeout": 60, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "locationUpdateInterval": 1000, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "locationsOrderDirection": "ASC", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "logLevel": 1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "logMaxDays": 3, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "maxBatchSize": -1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "maxDaysToPersist": 1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "maxRecordsToPersist": -1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "method": "POST", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "minimumActivityRecognitionConfidence": 75, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "motionTriggerDelay": 0, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "notification": { 12-01 13:34:00.367 16343 16458 I TSLocationManager: "layout": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "title": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "text": "Location access is activated for information and offers near you.", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "color": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "channelName": "Geolocation", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "channelId": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "smallIcon": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "largeIcon": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "priority": 0, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "sticky": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "strings": {}, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "actions": [] 12-01 13:34:00.367 16343 16458 I TSLocationManager: }, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "params": {}, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "persist": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "persistMode": -1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "schedule": [ 12-01 13:34:00.367 16343 16458 I TSLocationManager: "1-7 0:01-1:00" 12-01 13:34:00.367 16343 16458 I TSLocationManager: ], 12-01 13:34:00.367 16343 16458 I TSLocationManager: "scheduleUseAlarmManager": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "speedJumpFilter": 300, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "startOnBoot": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "stationaryRadius": 25, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "stopAfterElapsedMinutes": 0, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "stopOnStationary": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "stopOnTerminate": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "stopTimeout": 5, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "triggerActivities": "in_vehicle, on_bicycle, on_foot, running, walking", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "url": "", 12-01 13:34:00.367 16343 16458 I TSLocationManager: "useSignificantChangesOnly": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "enabled": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "schedulerEnabled": true, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "trackingMode": 1, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "odometer": 0, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "isFirstBoot": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "didLaunchInBackground": false, 12-01 13:34:00.367 16343 16458 I TSLocationManager: "didDeviceReboot": false 12-01 13:34:00.367 16343 16458 I TSLocationManager: } 12-01 13:34:00.367 16343 16343 D TSLocationManager: [c.t.l.l.LifecycleManager onCreate] ☯️ onCreate 12-01 13:34:00.367 16343 16343 I TSLocationManager: [c.t.l.a.BackgroundGeolocation ] 12-01 13:34:00.367 16343 16343 I TSLocationManager: ✅ Google Play Services: connected (version code:12451000) 12-01 13:34:00.373 16343 16458 I TSLocationManager: [c.t.l.logger.LoggerFacade$a a] 12-01 13:34:00.373 16343 16458 I TSLocationManager: ╔═════════════════════════════════════════════ 12-01 13:34:00.373 16343 16458 I TSLocationManager: ║ DEVICE SENSORS 12-01 13:34:00.373 16343 16458 I TSLocationManager: ╠═════════════════════════════════════════════ 12-01 13:34:00.373 16343 16458 I TSLocationManager: ╟─ ✅ ACCELEROMETER: {Sensor name="lsm6dso LSM6DSO Accelerometer Non-wakeup", vendor="STMicro", version=15933, type=1, maxRange=78.4532, resolution=0.0023928226, power=0.17, minDelay=5000} 12-01 13:34:00.373 16343 16458 I TSLocationManager: ╟─ ✅ GYROSCOPE: {Sensor name="lsm6dso LSM6DSO Gyroscope Non-wakeup", vendor="STMicro", version=15933, type=4, maxRange=17.453018, resolution=6.108648E-4, power=0.55, minDelay=5000} 12-01 13:34:00.373 16343 16458 I TSLocationManager: ╟─ ✅ MAGNETOMETER: {Sensor name="ak0991x AK09918 Magnetometer Non-wakeup", vendor="akm", version=146972, type=2, maxRange=4912.0503, resolution=0.15, power=1.1, minDelay=10000} 12-01 13:34:00.373 16343 16458 I TSLocationManager: ╟─ ✅ SIGNIFICANT_MOTION: {Sensor name="smd Wakeup", vendor="Samsung", version=1, type=17, maxRange=1.0, resolution=1.0, power=0.001, minDelay=-1} 12-01 13:34:00.373 16343 16458 I TSLocationManager: ╚═════════════════════════════════════════════ 12-01 13:34:00.373 16343 16458 D TSLocationManager: [c.t.l.logger.LoggerFacade$a a] 12-01 13:34:00.373 16343 16458 D TSLocationManager: 🎾 AbstractService [eventCount: 1] 12-01 13:34:00.373 16343 16458 D TSLocationManager: [c.t.l.logger.LoggerFacade$a a] 12-01 13:34:00.900 16343 16343 E TSLocationManager: [c.t.f.b.HeadlessTask startBackgroundIsolate] 12-01 13:34:00.900 16343 16343 E TSLocationManager: ‼️ Fatal: failed to find callback: -3461665204332439026 ```
christocracy commented 1 year ago

Post your lib/main.dart

viplavrawal commented 1 year ago

We actually have three different versions of main.dart due to different flavors. To keep redundancy to a minimum, the registration is being done in a different file and the headless task is being passed to that file from the main function.

Code

main_dev.dart ``` dart Future main() async { await commonMain(headlessTask); await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then((_) { runApp(App()); }); } initHeadless() async { // // } void headlessTask(HeadlessEvent headlessEvent) async { // method stored in another class headlessTaskSwitch(headlessEvent, initHeadless); } ```
common_main.dart ``` dart Future commonMainInit(Function headlessTask) async { WidgetsFlutterBinding.ensureInitialized(); if (Platform.isAndroid) { // Register your headlessTask: BackgroundGeolocation.registerHeadlessTask(headlessTask); } BackgroundGeolocation.ready( Config( geofenceModeHighAccuracy: true, enableHeadless: true, desiredAccuracy: Config.DESIRED_ACCURACY_HIGH, distanceFilter: 0, stopOnTerminate: false, scheduleUseAlarmManager: true, startOnBoot: true, autoSync: true, debug: false, logLevel: Config.LOG_LEVEL_ERROR, reset: true, disableMotionActivityUpdates: true, schedule: GeolocationConstants.schedule, ), ); } ```
christocracy commented 1 year ago

See CHANGELOG 4.8.3. Also see latest API docs Config.enableHeadless

Recent Flutter SDK now requires headless-task to be annotated with @pragma('vm-entry-point').

@pragma('vm:entry-point')
void headlessTask(bg.HeadlessEvent headlessEvent) async {
  print('[HeadlessTask]: ${headlessEvent}');
}

Also, BackgroundGeolocation.ready is meant to be called within a Flutter Widget component.

jairwt commented 1 year ago

See CHANGELOG 4.8.3. Also see latest API docs Config.enableHeadless

Recent Flutter SDK now requires headless-task to be annotated with @pragma('vm-entry-point').

@pragma('vm:entry-point')
void headlessTask(bg.HeadlessEvent headlessEvent) async {
  print('[HeadlessTask]: ${headlessEvent}');
}

Also, BackgroundGeolocation.ready is meant to be called within a Flutter Widget component.

I have tried this solution and moved this BackgroundGeolocation.ready and registerHeadlessTask() in my main, and started calling them within a Flutter widget, but now I started getting below error.

E/flutter ( 6400): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value
E/flutter ( 6400): #0      BackgroundGeolocation.registerHeadlessTask
package:flutter_background_geolocation/models/background_geolocation.dart:1612
christocracy commented 1 year ago

I suggest you test within a simple HelloWorld app.

viplavrawal commented 1 year ago

Hi @christocracy Our issue was resolved after making a few changes in our code. Thanks for your help