Skip to content

[Help Wanted]: Ability to send heatbeat packets when not moving. (1 every 1 minute) #387

@cfowlerapps

Description

@cfowlerapps

Required Reading

  • Confirmed

Plugin Version

7.2.5

Mobile operating-system(s)

  • iOS
  • Android

Device Manufacturer(s) and Model(s)

android s23 pro

Device operating-systems(s)

android 16

What do you require assistance about?

Hi, I have the Capacitor version and looking for understanding if a feature is possible.

Essentially I want to detect when a user has stopped on the server and keep the 1 minute heartbeats being sent, at the moment when the user stops it stops sending any location updates which is good for performance but the server needs that heartbeat to be able to know the state of the user is still being still.

is there a way to setup the addon to do this? I tried the background headless task and it didn't work either. I set heartbeatInterval: HEARTBEAT_INTERVAL_SECONDS to 60 and passed that in and it didn't help either.

[Optional] Plugin Code and/or Config

/**
 * Tracking Configuration Constants
 * 
 * Centralized configuration for the Transistorsoft Background Geolocation plugin.
 * Adjust these values to tune tracking behavior for your use case.
 * 
 * @see https://transistorsoft.github.io/capacitor-background-geolocation/interfaces/config.html
 */

import i18n from '@/lib/i18n';

// ============================================================================
// GEOLOCATION CONFIG - Controls location accuracy and update frequency
// ============================================================================

/**
 * Distance in meters the device must move before generating a location update.
 * Lower values = more frequent updates but higher battery usage.
 * Default: 50m is good for motorcycle/vehicle tracking at highway speeds.
 * 
 * Note: This is auto-scaled by speed when elasticity is enabled (disableElasticity: false).
 * At 30 m/s (108 km/h), actual filter becomes: 50 * (30/5) = 300m
 */
export const DISTANCE_FILTER_METERS = 50;

/**
 * When speed-based elasticity is enabled, this multiplier scales the distance filter.
 * Higher values = fewer location updates at high speeds.
 * Default: 1.0 (no additional scaling)
 */
export const ELASTICITY_MULTIPLIER = 1.0;

/**
 * Disable automatic speed-based distance filter scaling.
 * Set to true for consistent distance filter regardless of speed.
 * Default: false (elasticity enabled for battery savings at high speed)
 */
export const DISABLE_ELASTICITY = false;

/**
 * iOS only: Radius in meters to consider device stationary.
 * Device must move beyond this radius to trigger motion detection.
 * Default: 25m is reasonable for detecting motorcycle movement.
 */
export const STATIONARY_RADIUS_METERS = 25;

/**
 * Location accuracy threshold in meters for odometer calculations.
 * Locations with accuracy worse than this are ignored for distance tracking.
 */
export const DESIRED_ODOMETER_ACCURACY = 100;

// ============================================================================
// MOTION DETECTION CONFIG - Controls stop/start detection
// ============================================================================

/**
 * Minutes device must remain stationary before stopping location services.
 * The plugin uses motion detection (accelerometer) to detect when stopped.
 * Lower values save battery but may cause frequent start/stop cycling.
 * For motorcycle rides with stops at traffic lights, fuel stops, etc., use 5+ minutes.
 * We use 20 minutes to avoid frequent stop/start cycling.
 */
export const STOP_TIMEOUT_MINUTES = 20;

/**
 * Delay in minutes before activating stop-detection after starting.
 * Use to prevent false "stopped" detection at ride start.
 * Default: 1 minute to allow settling
 */
export const STOP_DETECTION_DELAY_MINUTES = 1;

/**
 * Completely disable accelerometer-based stop detection.
 * Set to true for testing to verify HTTP sync works independent of motion.
 * ⚠️ For production, set to false to save battery.
 */
export const DISABLE_STOP_DETECTION = false; // Production: false for battery savings

/**
 * Disable motion activity updates (walking, in_vehicle, etc.).
 * ⚠️ NOT RECOMMENDED - the plugin is highly optimized to use this for battery savings.
 * Default: false
 */
export const DISABLE_MOTION_ACTIVITY_UPDATES = false;

// ============================================================================
// APPLICATION LIFECYCLE CONFIG - Controls behavior on app close/reboot
// ============================================================================

/**
 * Continue tracking after user terminates/closes the app.
 * Essential for ride tracking where users may lock phone during ride.
 * Default: false to stop - we use true so tracking continues
 */
export const STOP_ON_TERMINATE = false;

/**
 * Automatically resume tracking when device reboots.
 * Useful if phone dies during a ride and is restarted.
 * Default: true for ride tracking use case
 */
export const START_ON_BOOT = true;

/**
 * Heartbeat interval in seconds. Fires periodic events even when stationary.
 * Useful for keeping database connection alive and verifying tracking is working.
 * Set to 0 to disable heartbeat.
 * Default: 60 seconds (1 minute) - more frequent for reliability
 */
export const HEARTBEAT_INTERVAL_SECONDS = 60;

/**
 * iOS only: Prevent iOS from suspending the app in background while stationary.
 * Required if you want heartbeat events while stationary.
 * ⚠️ Increases battery usage - use with heartbeatInterval.
 * Default: true for reliable background tracking
 */
export const PREVENT_SUSPEND = true;

// ============================================================================
// ANDROID FOREGROUND SERVICE CONFIG - Critical for background operation
// ============================================================================

/**
 * Android: Run as foreground service with persistent notification.
 * Makes the plugin mostly immune to OS termination due to memory pressure.
 * REQUIRED for reliable background tracking on Android.
 * Default: true for ride tracking
 */
export const FOREGROUND_SERVICE = true;

/**
 * Android: Enable "Headless" mode for when app is terminated.
 * Allows responding to plugin events in native Android environment.
 * Default: true for maximum reliability
 */
export const ENABLE_HEADLESS = true;

/**
 * Android: With distanceFilter: 0, sets desired interval for location updates in ms.
 * ⚠️ Ignored when distanceFilter > 0
 * Default: 1000ms
 */
export const LOCATION_UPDATE_INTERVAL_MS = 1000;

/**
 * Android: Fastest interval for location updates in ms.
 * Even if other apps request faster updates, this is the limit.
 * Default: 5000ms (5 seconds)
 */
export const FASTEST_LOCATION_UPDATE_INTERVAL_MS = 5000;

// ============================================================================
// GEOFENCING CONFIG - For proximity-based features
// ============================================================================

/**
 * Radius in meters to query for geofences within proximity.
 * Only geofences within this radius are actively monitored.
 * Default: 1000m
 */
export const GEOFENCE_PROXIMITY_RADIUS_METERS = 1000;

/**
 * Trigger geofence ENTER immediately if device is already inside when added.
 * Default: true
 */
export const GEOFENCE_INITIAL_TRIGGER_ENTRY = true;

/**
 * Android: Run geofences with foreground service for more consistent triggering.
 * Higher power usage but more reliable geofence detection.
 * Default: false
 */
export const GEOFENCE_MODE_HIGH_ACCURACY = false;

// ============================================================================
// HTTP & PERSISTENCE CONFIG - For built-in HTTP sync to Supabase
// ============================================================================

/**
 * The URL to POST location updates to.
 * Uses the edge function for background updates when app is terminated.
 */
export const HTTP_URL = `${import.meta.env.VITE_SUPABASE_URL}/functions/v1/update-location`;

/**
 * HTTP method for location sync
 */
export const HTTP_METHOD = "POST";

/**
 * Maximum days to store locations in plugin's SQLite database.
 * Locations older than this are deleted.
 * Increased for longer connectivity gaps during remote rides.
 */
export const MAX_DAYS_TO_PERSIST = 7;

/**
 * Maximum number of records to persist. -1 = no limit.
 * Increased to handle longer connectivity outages.
 */
export const MAX_RECORDS_TO_PERSIST = 1000;

/**
 * Automatically sync locations to configured URL.
 * CRITICAL: This must be true for background sync to work!
 */
export const AUTO_SYNC = true;

/**
 * When auto-sync is disabled, trigger a sync only when this many locations are in DB.
 * Default: 1 (sync immediately)
 */
export const AUTO_SYNC_THRESHOLD = 1;

/**
 * Number of locations to send per HTTP request.
 * Default: 1 (send each location immediately for real-time tracking)
 */
export const BATCH_SYNC = 1;

/**
 * The root property in the HTTP body JSON.
 * Default: "location" - sends { location: {...} }
 */
export const HTTP_ROOT_PROPERTY = "location";

/**
 * HTTP timeout in milliseconds
 */
export const HTTP_TIMEOUT_MS = 30000;

/**
 * Order direction for syncing locations.
 * "DESC" sends newest locations first (better for real-time tracking).
 */
export const LOCATIONS_ORDER_DIRECTION = "DESC";

// ============================================================================
// LOGGING & DEBUG CONFIG
// ============================================================================

/**
 * Enable debug sounds and notifications for plugin lifecycle events.
 * Useful during development, disable for production.
 * Default: false for production
 */
export const DEBUG_MODE = false;

/**
 * Maximum days to keep log entries in database.
 * Default: 3 days
 */
export const LOG_MAX_DAYS = 3;

// ============================================================================
// NOTIFICATION CONFIG - Android foreground service notification
// ============================================================================

/**
 * Default title for Android foreground notification
 */

/**
 * Default message for Android foreground notification
 */
export const NOTIFICATION_MESSAGE = i18n.t('notifications.bgNotificationMessage', {
	defaultValue: "Live ride sharing is active. Tap to return to the ride.",
});

/**
 * Allow overriding notification title via env during build/dev
 */
export const NOTIFICATION_TITLE = i18n.t('notifications.bgNotificationTitle', {
	defaultValue: "Group Ride",
});

/**
 * Android notification channel name
 */
export const NOTIFICATION_CHANNEL_NAME = "Location Tracking";

/**
 * Small icon for notification (Android resource name)
 * Place the asset at android/app/src/main/res/drawable/ride_logo.png (lowercase/underscores only).
 */
export const NOTIFICATION_SMALL_ICON = "drawable/ride_logo";

/**
 * Large icon for notification (Android resource name)
 */
export const NOTIFICATION_LARGE_ICON = "drawable/ride_logo";

// ============================================================================
// getCurrentPosition CONFIG
// ============================================================================

/**
 * Timeout in seconds for getCurrentPosition requests.
 */
export const GET_POSITION_TIMEOUT_SECONDS = 30;

/**
 * Maximum age in milliseconds of a cached position to return.
 */
export const GET_POSITION_MAX_AGE_MS = 10000;

/**
 * Desired accuracy in meters for getCurrentPosition.
 */
export const GET_POSITION_DESIRED_ACCURACY = 10;

/**
 * Number of location samples to collect for getCurrentPosition.
 */
export const GET_POSITION_SAMPLES = 1;


// ============================================================================
// backgroundPermissionRationale CONFIG
// ============================================================================

/**
 * The Title for the modal dialog shown when requesting background location permission.
 */
export const BACKGROUND_RATIONALE_TITLE = "Allow Group Ride to access your location in the background?";

/**
 * The Title for the modal dialog shown when requesting background location permission.
 */
export const BACKGROUND_RATIONALE_MESSAGE = "To track your ride and share your location with group members and trackers, Group Ride needs access to your location even when the app is closed or not in use. This helps keep you connected with your ride group and loved ones.";

/**
 * The Title for the modal dialog shown when requesting background location permission.
 */
export const BACKGROUND_RATIONALE_POS_ACTION = "Allow all the time";

/**
 * The Title for the modal dialog shown when requesting background location permission.
 */
export const BACKGROUND_RATIONALE_NEG_ACTION = "Decline";

[Optional] Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions