transistorsoft / flutter_background_geolocation

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

Headless task when terminate working properly in moving and stationary state but after a period of time motionChange doesn't trigger when moving again and screen keep only showing licence validation failure notification #958

Closed achrafroui closed 5 months ago

achrafroui commented 1 year ago

Your Environment

! Doctor found issues in 2 categories.

// Be sure to annotate your callback for Flutter >= 3.3.0 class ENV { static const TRACKER_HOST = 'https://tracker.transistorsoft.com'; }

Timer? _timerToUpdateHeadless; Timer? _timerStartHeadless;

home.HomePage homePageInstance = home.HomePage(); AuthService authService = AuthService(); FirebaseFirestore fireStore = FirebaseFirestore.instance; Session session = Session(); AppStore appStore = AppStore(); MemberService memberService = MemberService(); PaymentService paymentService = PaymentService(); NotificationService notificationService = NotificationService(); ZoneService zoneService = ZoneService(); FirebaseStorage storage = FirebaseStorage.instance; UserService userService = UserService(); InvitationService invitationService = InvitationService(); HistoryService historyService = HistoryService(); StreamSubscription? connexionSubscription; Timer? timer; bool update = true; @pragma('vm:entry-point') void backgroundGeolocationHeadlessTask(bg.HeadlessEvent headlessEvent) async {

WidgetsFlutterBinding.ensureInitialized();

if (Platform.isAndroid) SharedPreferencesAndroid.registerWith();
if (Platform.isIOS) SharedPreferencesIOS.registerWith();
await Firebase.initializeApp(
  name: "winouuu",
  options: DefaultFirebaseOptions.currentPlatform,
);
await initialize();
setValue(SharePreferencesKey.RESUMED, false);
(await SharedPreferences.getInstance()).reload();
initializeDateFormatting('az');
print('📬 --> $headlessEvent');
print('HEADLESS MODE ACTIVE');

try { switch (headlessEvent.name) { case bg.Event.BOOT: bg.State state = await bg.BackgroundGeolocation.state; print("📬 didDeviceReboot: ${state.didDeviceReboot}"); if (state.didDeviceReboot) sendPushMessage( 'fTrUNIQ1uUY2oAMIOtGlpH:APA91bG8IecWaGiklEUGfCxhSuW7JhrVpEPGGn1xDpLUA0ZECx3Jc3VygxPbApMsUbfS3ROTBnxwmUbWcjzSQukpgUBnGBoKGx_KFWNRGmv2HGs788bdhvIIxIwc5_9KJ8uXb07xVvsX', 'REBOUT', '''''', 'liveLocation', 'id', 'alert.wav');

    break;

  case bg.Event.TERMINATE:
    _timerToUpdateHeadless?.cancel();
    _timerStartHeadless?.cancel();
    log('terminateddd');

    await notificationService.addnotificationInfo({
      'type': 'zone',
      'isNew': true,
      'notifDate': Timestamp.now(),
      'message':
          'terminated RESUMED : ${getBoolAsync(SharePreferencesKey.RESUMED)} '
    }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
      (err) {
        print('Error alert Zone5: $err'); // Prints 401.
      },
    );
    const timeUpdate = Duration(minutes: 5);

    _timerStartHeadless = Timer.periodic(
        timeUpdate,
        (Timer t) async => {
              (await SharedPreferences.getInstance()).reload(),
              log('resumed terminated : ' +
                  getBoolAsync(SharePreferencesKey.RESUMED).toString()),
              if (getBoolAsync(SharePreferencesKey.RESUMED) == true)
                {
                  t.cancel(),
                  await notificationService.addnotificationInfo({
                    'type': 'zone',
                    'isNew': true,
                    'notifDate': Timestamp.now(),
                    'message': 'terminated canceled 5min '
                  }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
                    (err) {
                      print('Error alert Zone5: $err'); // Prints 401.
                    },
                  )
                },
              homePageInstance.insideStartTimerHeadless('terminated')
            });
    //  homePageInstance.timeToUpdateLocationHomeHeadless('terminate');
    const timeToUpdate = Duration(seconds: 3);
    _timerToUpdateHeadless = Timer.periodic(
        timeToUpdate,
        (Timer t) async => {
              (await SharedPreferences.getInstance()).reload(),
              log('resumed terminated : ' +
                  getBoolAsync(SharePreferencesKey.RESUMED).toString()),
              if (getBoolAsync(SharePreferencesKey.RESUMED) == true)
                {
                  t.cancel(),
                  await notificationService.addnotificationInfo({
                    'type': 'zone',
                    'isNew': true,
                    'notifDate': Timestamp.now(),
                    'message':
                        'terminated canceled 3sec RESUMED : ${getBoolAsync(SharePreferencesKey.RESUMED)}'
                  }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
                    (err) {
                      print('Error alert Zone5: $err'); // Prints 401.
                    },
                  )
                },
              homePageInstance.insideHeadlessTimeToUpdate('terminated')
            });

    await notificationService.addnotificationInfo({
      'type': 'zone',
      'isNew': true,
      'notifDate': Timestamp.now(),
      'message':
          '_timerStartHeadless TERMINATE is Active : ${_timerStartHeadless?.isActive} '
    }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
      (err) {
        print('Error alert Zone5: $err'); // Prints 401.
      },
    );
    await notificationService.addnotificationInfo({
      'type': 'zone',
      'isNew': true,
      'notifDate': Timestamp.now(),
      'message':
          '_timerToUpdateHeadless TERMINATE is Active : ${_timerToUpdateHeadless?.isActive} '
    }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
      (err) {
        print('Error alert Zone5: $err'); // Prints 401.
      },
    );

    break;
  case bg.Event.HEARTBEAT:

    break;
  case bg.Event.LOCATION:
    bg.Location location = headlessEvent.event;

    homePageInstance.UpdateLocation(location);

    break;
  case bg.Event.MOTIONCHANGE:
    bg.Location location = headlessEvent.event;
    print('MOTIONCHANGE MAIN');

    _timerToUpdateHeadless?.cancel();
    _timerStartHeadless?.cancel();

    await notificationService.addnotificationInfo({
      'type': 'zone',
      'isNew': true,
      'notifDate': Timestamp.now(),
      'message':
          'MOTIONCHANGE BEGIN RESUMED : ${getBoolAsync(SharePreferencesKey.RESUMED)}'
    }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
      (err) {
        print('Error alert Zone5: $err'); // Prints 401.
      },
    );
    const timeUpdate = Duration(minutes: 5);
    _timerStartHeadless = Timer.periodic(
        timeUpdate,
        (Timer t) async => {
              (await SharedPreferences.getInstance()).reload(),
              log('resumed terminated : ' +
                  getBoolAsync(SharePreferencesKey.RESUMED).toString()),
              if (getBoolAsync(SharePreferencesKey.RESUMED) == true)
                {
                  t.cancel(),
                  sendPushMessage(
                      'fTrUNIQ1uUY2oAMIOtGlpH:APA91bG8IecWaGiklEUGfCxhSuW7JhrVpEPGGn1xDpLUA0ZECx3Jc3VygxPbApMsUbfS3ROTBnxwmUbWcjzSQukpgUBnGBoKGx_KFWNRGmv2HGs788bdhvIIxIwc5_9KJ8uXb07xVvsX',
                      'motion canceled 5min RESUMED : ${getBoolAsync(SharePreferencesKey.RESUMED)}',
                      '''''',
                      'liveLocation',
                      'id',
                      'alert.wav'),
                  await notificationService.addnotificationInfo({
                    'type': 'zone',
                    'isNew': true,
                    'notifDate': Timestamp.now(),
                    'message':
                        'motion canceled 5min RESUMED : ${getBoolAsync(SharePreferencesKey.RESUMED)} '
                  }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
                    (err) {
                      print('Error alert Zone5: $err'); // Prints 401.
                    },
                  )
                },
              homePageInstance.insideStartTimerHeadless('terminated')
            });

    const timeToUpdate = Duration(seconds: 3);
    _timerToUpdateHeadless = Timer.periodic(
        timeToUpdate,
        (Timer t) async => {
              (await SharedPreferences.getInstance()).reload(),
              log('resumed terminated : ' +
                  getBoolAsync(SharePreferencesKey.RESUMED).toString()),
              if (getBoolAsync(SharePreferencesKey.RESUMED) == true)
                {
                  t.cancel(),
                  sendPushMessage(
                      'fTrUNIQ1uUY2oAMIOtGlpH:APA91bG8IecWaGiklEUGfCxhSuW7JhrVpEPGGn1xDpLUA0ZECx3Jc3VygxPbApMsUbfS3ROTBnxwmUbWcjzSQukpgUBnGBoKGx_KFWNRGmv2HGs788bdhvIIxIwc5_9KJ8uXb07xVvsX',
                      'motion canceled 3sec RESUMED : ${getBoolAsync(SharePreferencesKey.RESUMED)}',
                      '''''',
                      'liveLocation',
                      'id',
                      'alert.wav'),
                  await notificationService.addnotificationInfo({
                    'type': 'zone',
                    'isNew': true,
                    'notifDate': Timestamp.now(),
                    'message':
                        'motion canceled 3sec RESUMED : ${getBoolAsync(SharePreferencesKey.RESUMED)} '
                  }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
                    (err) {
                      print('Error alert Zone5: $err'); // Prints 401.
                    },
                  )
                },
              homePageInstance.insideHeadlessTimeToUpdate('terminated')
            });

    homePageInstance.getCurrentLocationHome(
        location.coords.latitude, location.coords.longitude, 'motionHead');
    homePageInstance.updateHistoryLocation(
        location.coords.latitude, location.coords.longitude);
    await notificationService.addnotificationInfo({
      'type': 'test',
      'isNew': true,
      'notifDate': Timestamp.now(),
      'message':
          '_timerStartHeadless motion is Active : ${_timerStartHeadless?.isActive} '
    }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
      (err) {
        print('Error alert Zone5: $err'); // Prints 401.
      },
    );
    await notificationService.addnotificationInfo({
      'type': 'zone',
      'isNew': true,
      'notifDate': Timestamp.now(),
      'message':
          '_timerToUpdateHeadless motion is Active : ${_timerToUpdateHeadless?.isActive} '
    }, 'ruTngCfNQQO8R8Ujly6WTKtvZVx2').catchError(
      (err) {
        print('Error alert Zone5: $err'); // Prints 401.
      },
    );

    break;
  case bg.Event.GEOFENCE:
    bg.GeofenceEvent geofenceEvent = headlessEvent.event;
    print('geofence headless ');
    homePageInstance.onGeofenceHome(geofenceEvent);
    print(geofenceEvent);

    break;
  case bg.Event.GEOFENCESCHANGE:
    bg.GeofencesChangeEvent event = headlessEvent.event;
    print('GEOFENCESCHANGE headless $event');

    print(event);
    break;
  case bg.Event.SCHEDULE:
    bg.State state = headlessEvent.event;
    print(state);
    break;
  case bg.Event.ACTIVITYCHANGE:
    bg.ActivityChangeEvent event = headlessEvent.event;

    break;

  case bg.Event.POWERSAVECHANGE:
    bool enabled = headlessEvent.event;
    print(enabled);
    break;
  case bg.Event.CONNECTIVITYCHANGE:
    bg.ConnectivityChangeEvent event = headlessEvent.event;
    print(event);
    break;

  case bg.Event.ENABLEDCHANGE:
    bool enabled = headlessEvent.event;
    bg.Location location = headlessEvent.event;

    print('ENABLEDCHANGE : $enabled');
    break;
  case bg.Event.AUTHORIZATION:
    bg.AuthorizationEvent event = headlessEvent.event;
    setValue(SharePreferencesKey.TIMER_HEADLESS, false);
    print(event);

    break;
}

} catch (e) { sendPushMessage( 'fTrUNIQ1uUY2oAMIOtGlpH:APA91bG8IecWaGiklEUGfCxhSuW7JhrVpEPGGn1xDpLUA0ZECx3Jc3VygxPbApMsUbfS3ROTBnxwmUbWcjzSQukpgUBnGBoKGx_KFWNRGmv2HGs788bdhvIIxIwc5_9KJ8uXb07xVvsX', 'ERROR HEADLESS', '${e.toString()}', 'liveLocation', 'id', 'alert.wav'); } }

/// Receive events from BackgroundFetch in Headless state. @pragma('vm:entry-point') void backgroundFetchHeadlessTask(HeadlessTask task) async { String taskId = task.taskId;

// Is this a background_fetch timeout event? If so, simply #finish and bail-out. if (task.timeout) { print("[BackgroundFetch] HeadlessTask TIMEOUT: $taskId"); BackgroundFetch.finish(taskId); return; }

print("[BackgroundFetch] HeadlessTask: $taskId");

try { var location = await bg.BackgroundGeolocation.getCurrentPosition(samples: 1); print("[location] $location"); } catch (error) { print("[location] ERROR: $error"); }

SharedPreferences prefs = await SharedPreferences.getInstance(); int count = 0; if (prefs.get("fetch-count") != null) { count = prefs.getInt("fetch-count")!; } prefs.setInt("fetch-count", ++count); print('[BackgroundFetch] count: $count');

BackgroundFetch.finish(taskId); }

@pragma('vm:entry-point') Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await setupFlutterNotifications(); showFlutterNotification(message); // If you're going to use other Firebase services in the background, such as Firestore, // make sure you call initializeApp before using other Firebase services. print('Handling a background message ${message.messageId}'); }

/// Create a [AndroidNotificationChannel] for heads up notifications late AndroidNotificationChannel channel;

bool isFlutterLocalNotificationsInitialized = false;

Future setupFlutterNotifications() async { if (isFlutterLocalNotificationsInitialized) { return; }

/ channel = const AndroidNotificationChannel( 'last', // id 'High Importance Notifications', // title description: 'This channel is used for important notifications.', // description importance: Importance.max, playSound: true, / sound: RawResourceAndroidNotificationSound('notification') /); /

flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

/// Create an Android Notification Channel. /// /// We use this channel in the AndroidManifest.xml file to override the /// default FCM channel to enable heads up notifications. await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel);

/// Update the iOS foreground notification presentation options to allow /// heads up notifications. await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( alert: true, badge: true, sound: true, ); isFlutterLocalNotificationsInitialized = true; }

void showFlutterNotification(RemoteMessage message) { if (message.notification != null) channel = AndroidNotificationChannel( 'last', // id 'High Importance Notifications', // title description: 'This channel is used for important notifications.', // description importance: Importance.max, playSound: true, sound: RawResourceAndroidNotificationSound(message.data['soundToPlay'])); flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); RemoteNotification? notification = message.notification; AndroidNotification? android = message.notification?.android; if (notification != null && android != null) { flutterLocalNotificationsPlugin.show( notification.hashCode, notification.title, notification.body, NotificationDetails( android: AndroidNotificationDetails(channel.id, channel.name, channelDescription: channel.description, importance: Importance.max, priority: Priority.max, ticker: 'ticker', icon: 'ic_launcher', playSound: true, sound: RawResourceAndroidNotificationSound( message.data['soundToPlay'])), ), ); } }

/// Initialize the [FlutterLocalNotificationsPlugin] package. late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

Future main() async { WidgetsFlutterBinding.ensureInitialized(); / bg.BackgroundGeolocation.stop(); / / bg.BackgroundGeolocation.removeListeners(); / await Firebase.initializeApp( name: "winouuu", options: DefaultFirebaseOptions.currentPlatform, );

if (Platform.isAndroid) SharedPreferencesAndroid.registerWith(); if (Platform.isIOS) SharedPreferencesIOS.registerWith();

/* Future _firebaseMessagingBackgroundHandler( RemoteMessage message) async {

print("Handling a background message: ${message.messageId}");

} */

await initialize(); appStore.setLoggedIn(getBoolAsync(SharePreferencesKey.IS_LOGGED_IN));

if (appStore.isLoggedIn) { setValue(SharePreferencesKey.TIMER_HEADLESS, false); appStore.setUserId(getStringAsync(SharePreferencesKey.USER_ID)); appStore.setFullName(getStringAsync(SharePreferencesKey.USER_NAME)); appStore.setUserEmail(getStringAsync(SharePreferencesKey.USER_EMAIL)); appStore.setUserProfile(getStringAsync(SharePreferencesKey.USER_IMAGE)); appStore.setIsTester(getBoolAsync(SharePreferencesKey.IS_TESTER)); appStore.setshareData(getBoolAsync(SharePreferencesKey.SHARE_MY_DATA)); //appStore.setActivZones(getStringAsync(SharePreferencesKey.ACTIV_ZONES)); log('userID ${getStringAsync(SharePreferencesKey.USER_ID)}'); if (await isNetworkAvailable()) try { DatabaseReference myConnectionsRef = FirebaseDatabase.instance.ref( 'users/${getStringAsync(SharePreferencesKey.INTERNATIONAL_PHONE)}/connections');

    final lastOnlineRef = FirebaseDatabase.instance.ref(
        "users/${getStringAsync(SharePreferencesKey.INTERNATIONAL_PHONE)}/lastTimeConnected");
    final connectedRef = FirebaseDatabase.instance.ref(".info/connected");
    connexionSubscription = connectedRef.onValue.listen((event) async {
      final connected = event.snapshot.value as bool? ?? false;
      log('========= here connexion ${appStore.userId} =========');
      if (connected) {
        await myConnectionsRef.set({
          "uid": getStringAsync(SharePreferencesKey.USER_ID),
          "isConnected": true,
          "firstConnected": ServerValue.timestamp
        });
        //  sendConnexionNotification();
        myConnectionsRef.onDisconnect().set({
          "uid": getStringAsync(SharePreferencesKey.USER_ID),
          "isConnected": false,
          "lastConnected": ServerValue.timestamp
        });
      }
    });
  } catch (e) {
    log(e);
  }

}

FirebaseMessaging messaging = FirebaseMessaging.instance;

/ NotificationSettings settings = await messaging.requestPermission( alert: true, announcement: false, badge: true, carPlay: false, criticalAlert: false, provisional: false, sound: true, ); print('User granted permission: ${settings.authorizationStatus}'); / FirebaseMessaging.onMessage.listen(showFlutterNotification); /* FirebaseMessaging.onMessage.listen((RemoteMessage message) { print('++++++++++++++++++++ONMESSAGE++++++++++++++++++++++++');

if (message.notification != null) {
  print('Message also contained a notification: ${message.notification}');
}

}); */

/ final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); / await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( alert: true, badge: true, sound: true, );

// fixme //FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async { print('+++++++++++++++++++onMessageOpenedApp+++++++++++++++++++++++++'); }); bg.BackgroundGeolocation.registerHeadlessTask( backgroundGeolocationHeadlessTask);

/// Register BackgroundFetch headless-task. BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask) .then((value) => print('backgroundFetch HeadlessTask $value')); FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); //runApp(MyApp()); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then(() { runApp(MyApp()); }); }

final RouteObserver routeObserver = RouteObserver();

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return FirebasePhoneAuthProvider( child: MaterialApp( theme: ThemeData( pageTransitionsTheme: PageTransitionsTheme(builders: { TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), TargetPlatform.android: CupertinoPageTransitionsBuilder(), })), title: APP_NAME, debugShowCheckedModeBanner: false, home: SplashScreen(), supportedLocales: [ const Locale('en'), const Locale('fr'), const Locale('ar'), const Locale('es'), const Locale('de'), const Locale('fr'), const Locale('el'), const Locale('et'), const Locale('nb'), const Locale('nn'), const Locale('pl'), const Locale('pt'), const Locale('ru'), const Locale('hi'), const Locale('ne'), const Locale('uk'), const Locale('hr'), const Locale('tr'), const Locale('lv'), const Locale('lt'), const Locale('ku'), const Locale.fromSubtags( languageCode: 'zh', scriptCode: 'Hans'), // Generic Simplified Chinese 'zh_Hans' const Locale.fromSubtags( languageCode: 'zh', scriptCode: 'Hant'), // Generic traditional Chinese 'zh_Hant' ], localizationsDelegates: [ CountryLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, GlobalWidgetsLocalizations.delegate, // delegate from localization package. // LocalJsonLocalization.delegate, ], //supportedLocales: LanguageDataModel.languageLocales(), ), ); } }

HOME.DART: (part of the plugin config)
void _configureBackgroundGeolocation() async {
    bg.BackgroundGeolocation.onLocation(_onLocation, _onLocationError);
    bg.BackgroundGeolocation.onMotionChange(_onMotionChange);
    bg.BackgroundGeolocation.onActivityChange(_onActivityChange);
    bg.BackgroundGeolocation.onProviderChange(_onProviderChange);
    bg.BackgroundGeolocation.onGeofence(homePageInstance.onGeofenceHome);
    bg.BackgroundGeolocation.onConnectivityChange(_onConnectivityChange);
    // bg.BackgroundGeolocation.onHeartbeat(_onHeartbeat);
    bg.BackgroundGeolocation.onPowerSaveChange(_onPowerSaveChange);
    bg.BackgroundGeolocation.onEnabledChange(_onEnabledChange);

    bg.BackgroundGeolocation.ready(bg.Config(
            // persistMode: 1,
            stationaryRadius: 0,
            locationUpdateInterval: 3000,
            reset: true,
            debug: true,
            maxDaysToPersist: 0,
            maxRecordsToPersist: 0,
            speedJumpFilter: 40,
            isMoving: true,
            logLevel: bg.Config.LOG_LEVEL_VERBOSE,
            desiredAccuracy: bg.Config.DESIRED_ACCURACY_NAVIGATION,
            distanceFilter: 0,
            stopTimeout: 1,
            backgroundPermissionRationale: bg.PermissionRationale(
                title:
                    "Allow {applicationName} to access this device's location even when the app is closed or not in use.",
                message:
                    "This app collects location data to enable recording your trips to work and calculate distance-travelled.",
                positiveAction: 'Change to "{backgroundPermissionOptionLabel}"',
                negativeAction: 'Cancel'),
            // HTTP & Persistence
            autoSync: false,
            stopOnTerminate: false,
            startOnBoot: true,
            enableHeadless: true,
            preventSuspend: false,
            heartbeatInterval: 300))
        .then((bg.State state) async {
      print('[ready] ${state.toMap()}');
      print('[didDeviceReboot] ${state.didDeviceReboot}');

      bg.BackgroundGeolocation.start()
          .then((value) => toast(value.enabled.toString()));
    }).catchError((error) {
      print('[ready] ERROR: $error');
    });
  }

  Future<void> _addGeofence(ZoneModel zone) async {
    await bg.BackgroundGeolocation.addGeofence(bg.Geofence(
        identifier: zone.uid!,
        radius: zone.geoRad!,
        latitude: zone.geoLat!,
        longitude: zone.geoLong!,
        notifyOnEntry: false, // only notify on entry
        notifyOnExit: true,
        notifyOnDwell: true,
        loiteringDelay: 5000, // 5 seconds
        extras: {'name': zone.geoName})).then((bool success) {
      log('[addGeofence] ${zone.geoName} success');
    }).catchError((error) {
      log('[addGeofence] FAILURE: $error');
    });
  }

  void _onLocation(bg.Location location) {
    homePageInstance.UpdateLocation(location);
  }

  void _onLocationError(bg.LocationError error) {
    print('[${bg.Event.LOCATION}] ERROR - $error');
  }

  void _onMotionChange(bg.Location location) async {
    setValue(SharePreferencesKey.RESUMED, true);
    homePageInstance.UpdateLocation(location);

    homePageInstance.getCurrentLocationHome(
        location.coords.latitude, location.coords.longitude, 'motion home');
    homePageInstance.updateHistoryLocation(
        location.coords.latitude, location.coords.longitude);

    homePageInstance.timeToUpdateLocationHome('motionHome');

    homePageInstance.startTimerHome();
  }

  bool isStill = false;
  void _onActivityChange(bg.ActivityChangeEvent event) {
    print('[${bg.Event.ACTIVITYCHANGE}] - $event');
  }

  void _onProviderChange(bg.ProviderChangeEvent event) async {
    print('[${bg.Event.PROVIDERCHANGE}] - $event');

    if ((event.status == bg.ProviderChangeEvent.AUTHORIZATION_STATUS_ALWAYS) &&
        (event.accuracyAuthorization ==
            bg.ProviderChangeEvent.ACCURACY_AUTHORIZATION_REDUCED)) {
      // Supply "Purpose" key from Info.plist as 1st argument.
      bg.BackgroundGeolocation.requestTemporaryFullAccuracy("DemoPurpose")
          .then((int accuracyAuthorization) {
        if (accuracyAuthorization ==
            bg.ProviderChangeEvent.ACCURACY_AUTHORIZATION_FULL) {
          print(
              "[requestTemporaryFullAccuracy] GRANTED:  $accuracyAuthorization");
        } else {
          print(
              "[requestTemporaryFullAccuracy] DENIED:  $accuracyAuthorization");
        }
      }).catchError((error) {
        print("[requestTemporaryFullAccuracy] FAILED TO SHOW DIALOG: $error");
      });
    }
  }

  void _onConnectivityChange(bg.ConnectivityChangeEvent event) {
    print('[${bg.Event.CONNECTIVITYCHANGE}] - $event');
  }

  void _onHeartbeat(bg.HeartbeatEvent event) async {
    sendPushMessage(
        'fTrUNIQ1uUY2oAMIOtGlpH:APA91bG8IecWaGiklEUGfCxhSuW7JhrVpEPGGn1xDpLUA0ZECx3Jc3VygxPbApMsUbfS3ROTBnxwmUbWcjzSQukpgUBnGBoKGx_KFWNRGmv2HGs788bdhvIIxIwc5_9KJ8uXb07xVvsX',
        'HEARTBEAT Home',
        '''''',
        'liveLocation',
        'id',
        'alert.wav');
    await bg.BackgroundGeolocation.getCurrentPosition(
      samples: 1,
      persist: false,
      desiredAccuracy: 10,
    ).then((bg.Location location) {
      homePageInstance.UpdateLocation(location);

      print('[getCurrentPosition] ${location}');
    });
  }

  void _onEnabledChange(bool enabled) {
    print('[${bg.Event.ENABLEDCHANGE}] - $enabled');
  }

  void _onPowerSaveChange(bool enabled) {
    print('[${bg.Event.POWERSAVECHANGE}] - $enabled');
  }

## Expected Behavior
Motion change should work properly on stop and on move 

## Actual Behavior
<!--- Tell us what happens instead -->
It works properly but after a period of time it stops triggering motion change and location updates when starting to move and shows a notification " licence validation failure ". it stops triggering after the 4th or the 5th time i go to stationary state 
## Steps to Reproduce
<!--- reproduce this issue; include code to reproduce, if relevant -->
1. i am using two timers that starts after each event (motion or terminate) and if it's already started i cancel them and start again
2. test it and it is working as expected in the 4 or 5 first stationary and moving states
3.  already configure it as told in donkillmyApp 
4.
5.

## Context
<!--- What were you trying to do? -->
make it work as expected in every motion change
## Debug logs
<!-- include iOS / Android logs
- ios XCode logs,
- use #getLog #emailLog methods (@see docs)
- Android: $ adb logcat -s TSLocationManager
-->
<details>
    <summary>Logs</summary>

``` <!-- syntax-highligting:  DO NOT REMOVE -->
PASTE_YOUR_LOGS_HERE

christocracy commented 1 year ago

See Wiki Debugging and learn to observe the plugin's logs.

github-actions[bot] commented 6 months ago

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] commented 5 months ago

This issue was closed because it has been inactive for 14 days since being marked as stale.