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

Notification frequency issue #698

Closed Bubbleability closed 2 years ago

Bubbleability commented 2 years ago

Your Environment

• No issues found!

void backgroundGeolocationHeadlessTask(bg.HeadlessEvent headlessEvent) async { print('📬 --> $headlessEvent');

switch (headlessEvent.name) { case bg.Event.BOOT: bg.State state = await bg.BackgroundGeolocation.state; print("📬 didDeviceReboot: ${state.didDeviceReboot}"); break; case bg.Event.TERMINATE: try { bg.Location location = await bg.BackgroundGeolocation.getCurrentPosition(samples: 1); print("[getCurrentPosition] Headless: $location"); } catch (error) { print("[getCurrentPosition] Headless ERROR: $error"); } break; case bg.Event.HEARTBEAT:

  break;
case bg.Event.LOCATION:
  bg.Location location = headlessEvent.event;
  print(location);
  break;
case bg.Event.MOTIONCHANGE:
  bg.Location location = headlessEvent.event;
  print(location);
  break;
case bg.Event.GEOFENCE:
  bg.GeofenceEvent geofenceEvent = headlessEvent.event;
  print(geofenceEvent);
  break;
case bg.Event.GEOFENCESCHANGE:
  bg.GeofencesChangeEvent event = headlessEvent.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;
  print(event);
  break;
case bg.Event.HTTP:
  bg.HttpEvent response = headlessEvent.event;
  print(response);
  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;
  print(enabled);
  break;
case bg.Event.AUTHORIZATION:
  bg.AuthorizationEvent event = headlessEvent.event;
  print(event);
  bg.BackgroundGeolocation.setConfig(
      bg.Config(url: "http://tracker.transistorsoft.com"));
  break;

} }

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");

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); }

void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp();

SharedPreferences.getInstance().then((SharedPreferences prefs) { String appName = prefs.getString("app");

String orgname = prefs.getString("orgname");
String username = prefs.getString("username");

if (orgname == null && username != null) {
  prefs.setString("orgname", username);
  prefs.remove("username");
}

}); TransistorAuth.registerErrorHandler();

/// Register BackgroundGeolocation headless-task. bg.BackgroundGeolocation.registerHeadlessTask( backgroundGeolocationHeadlessTask);

/// Register BackgroundFetch headless-task. BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);

FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( alert: true, badge: true, sound: true, );

await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( alert: true, badge: true, sound: true);

SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then((_) { runApp(new MyApp()); });

// called in initState of homescreen

Future _initPlatformState() async { SharedPreferences prefs = await _prefs; String orgname = prefs.getString("orgname"); String username = prefs.getString("username");

// Sanity check orgname & username:  if invalid, go back to HomeApp to re-register device.
// if (orgname == null || username == null) {
//   return runApp(HomeApp());
// }

// Fetch a Transistor demo server Authorization token for tracker.transistorsoft.com.
bg.TransistorAuthorizationToken token =
    await bg.TransistorAuthorizationToken.findOrCreate(
        orgname, username, ENV.TRACKER_HOST);

// 1.  Listen to events (See docs for all 12 available events).
bg.BackgroundGeolocation.onLocation(_onLocation, _onLocationError);
bg.BackgroundGeolocation.getCurrentPosition().then((location) async {
  print("savedlocation ");
  var user = await getUser();
  Future.delayed(const Duration(seconds: 35), () {
    HomeRepo()
        .updateLocation(
            token: user.data.token,
            lat: location.coords.latitude,
            lng: location.coords.longitude)
        .then((res) {
      showLocalNoti(message: res.message);
    });
  });
});
bg.BackgroundGeolocation.onMotionChange(_onMotionChange); 
bg.BackgroundGeolocation.onActivityChange(_onActivityChange);
bg.BackgroundGeolocation.onProviderChange(_onProviderChange);
bg.BackgroundGeolocation.onConnectivityChange(_onConnectivityChange);
bg.BackgroundGeolocation.onHttp(_onHttp);
bg.BackgroundGeolocation.onAuthorization(_onAuthorization);

// 2.  Configure the plugin

bg.BackgroundGeolocation.ready(bg.Config(
        notificationPriority: 0,
        reset: true,
        debug: true,
        logLevel: bg.Config.LOG_LEVEL_VERBOSE,
        desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH,
        distanceFilter: 95.0,
        // locationUpdateInterval: 50000, android only
        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'),
        url: "${ENV.TRACKER_HOST}/api/locations",
        authorization: bg.Authorization(
            // <-- demo server authenticates with JWT
            strategy: bg.Authorization.STRATEGY_JWT,
            accessToken: token.accessToken,
            refreshToken: token.refreshToken,
            refreshUrl: "${ENV.TRACKER_HOST}/api/refresh_token",
            refreshPayload: {'refresh_token': '{refreshToken}'}),
        stopOnTerminate: false,
        stopOnStationary: false,
        preventSuspend: true,
        heartbeatInterval: 60,
        startOnBoot: true,

        enableHeadless: true))
    .then((bg.State state) {
  print("[ready] ${state.toMap()}");
  setState(() {
    _enabled = state.enabled;
    _isMoving = state.isMoving;
  });
}).catchError((error) {
  print('[ready] ERROR: $error');
});

} }


## Expected Behavior
<!--- Tell us what should happen -->
Reduction in the number of notifications that the users are receiving on their devices. I believe there should be an option to adjust whether we want to show notification or not. apart from that there is sound with notification which I also needs to addressed, there should an option to turn off and on the sound.

## Actual Behavior
<!--- Tell us what happens instead -->
There are a lot of notifications that are being received on the devices that may bother the users a lot and eventually comes out as a bad experience, 

![screenshot](https://user-images.githubusercontent.com/98166038/151507786-52f7894c-2d80-4f44-9788-e10e1e78cb4c.png)

## Steps to Reproduce
<!--- reproduce this issue; include code to reproduce, if relevant -->
1. Basic configuration of plugin.
2. Call this function in initstate of your homescreen/ dashboard screen

Future _initPlatformState() async { SharedPreferences prefs = await _prefs; String orgname = prefs.getString("orgname"); String username = prefs.getString("username");

// Sanity check orgname & username:  if invalid, go back to HomeApp to re-register device.
// if (orgname == null || username == null) {
//   return runApp(HomeApp());
// }

// Fetch a Transistor demo server Authorization token for tracker.transistorsoft.com.
bg.TransistorAuthorizationToken token =
    await bg.TransistorAuthorizationToken.findOrCreate(
        orgname, username, ENV.TRACKER_HOST);

// 1.  Listen to events (See docs for all 12 available events).
bg.BackgroundGeolocation.onLocation(_onLocation, _onLocationError);
bg.BackgroundGeolocation.getCurrentPosition().then((location) async {
  print("savedlocation ");
  var user = await getUser();
  Future.delayed(const Duration(seconds: 35), () {
    HomeRepo()
        .updateLocation(
            token: user.data.token,
            lat: location.coords.latitude,
            lng: location.coords.longitude)
        .then((res) {
      showLocalNoti(message: res.message);
    });
  });
});
bg.BackgroundGeolocation.onMotionChange(_onMotionChange); 
bg.BackgroundGeolocation.onActivityChange(_onActivityChange);
bg.BackgroundGeolocation.onProviderChange(_onProviderChange);
bg.BackgroundGeolocation.onConnectivityChange(_onConnectivityChange);
bg.BackgroundGeolocation.onHttp(_onHttp);
bg.BackgroundGeolocation.onAuthorization(_onAuthorization);

// 2.  Configure the plugin

bg.BackgroundGeolocation.ready(bg.Config(
        notificationPriority: 0,
        reset: true,
        debug: true,
        logLevel: bg.Config.LOG_LEVEL_VERBOSE,
        desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH,
        distanceFilter: 95.0,
        // locationUpdateInterval: 50000, android only
        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'),
        url: "${ENV.TRACKER_HOST}/api/locations",
        authorization: bg.Authorization(
            // <-- demo server authenticates with JWT
            strategy: bg.Authorization.STRATEGY_JWT,
            accessToken: token.accessToken,
            refreshToken: token.refreshToken,
            refreshUrl: "${ENV.TRACKER_HOST}/api/refresh_token",
            refreshPayload: {'refresh_token': '{refreshToken}'}),
        stopOnTerminate: false,
        stopOnStationary: false,
        preventSuspend: true,
        heartbeatInterval: 60,
        startOnBoot: true,

        enableHeadless: true))
    .then((bg.State state) {
  print("[ready] ${state.toMap()}");
  setState(() {
    _enabled = state.enabled;
    _isMoving = state.isMoving;
  });
}).catchError((error) {
  print('[ready] ERROR: $error');
});

} }


3. That's it.

## Context
<!--- What were you trying to do? -->
We want to get the location and send to server without getting a lot of notification with sound that you can also check in the attached screenshot.

## 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 -->

🔵-[BackgroundTaskManager onPreventSuspendTimer:] Prevent-suspend timer fired! (bg time remaining: 20.140356)
ℹ️+[LocationAuthorization run:onCancel:] status: 3
╔═══════════════════════════════════════════════════════════
║ -[TSLocationManager createMotionTypeChangedHandler]_block_invoke | still/33 | isMoving: 0
╚═══════════════════════════════════════════════════════════
╔═══════════════════════════════════════════════════════════
║ -[TSLocationManager createMotionTypeChangedHandler]_block_invoke | still/33 | isMoving: 0
╚═══════════════════════════════════════════════════════════
╔═══════════════════════════════════════════════════════════
║ -[TSLocationManager createMotionTypeChangedHandler]_block_invoke | still/33 | isMoving: 0
╚═══════════════════════════════════════════════════════════
╔═══════════════════════════════════════════════════════════
║ -[TSLocationManager createMotionTypeChangedHandler]_block_invoke | still/33 | isMoving: 0
╚═══════════════════════════════════════════════════════════
🔵-[TSLocationManager onHeartbeat] Heartbeat
╔═══════════════════════════════════════════════════════════
║ -[TSLocationManager createMotionTypeChangedHandler]_block_invoke | still/33 | isMoving: 0
╚═══════════════════════════════════════════════════════════
╔═══════════════════════════════════════════════════════════
║ -[TSLocationManager createMotionTypeChangedHandler]_block_invoke | still/33 | isMoving: 0
╚═══════════════════════════════════════════════════════════
╔═══════════════════════════════════════════════════════════
║ -[TSLocationManager createMotionTypeChangedHandler]_block_invoke | still/33 | isMoving: 0
╚═══════════════════════════════════════════════════════════

christocracy commented 2 years ago

Read the API docs Config.debug. Those notifications are there to assist you during development so you can see (and hear) the plugin working while out field-testing, so you don't have to run back to your office to determine if the plugin worked or not.