transistorsoft / capacitor-background-geolocation

The most sophisticated background location-tracking & geofencing module with battery-conscious motion-detection intelligence for iOS and Android.
MIT License
96 stars 15 forks source link

iOS Background Location Tracking Stops When The Application is in Background Mode #295

Closed Habka closed 17 minutes ago

Habka commented 4 days ago

Your Environment

Expected Behavior

The app continues tracking the user's location and sends it to the server, even while running in the background.

Actual Behavior

On iOS, the app stops tracking the user's location as soon as the app is minimized or the screen is locked.

Steps to Reproduce

  1. Run the app and start tracking a route.
  2. Minimize or lock the screen.

Context

We have a driver location tracking app that begins tracking the driver's location as soon as they have an order to deliver. This location data is sent to the server to display the driver's current location to the customer. Therefore, we need the app to continue receiving location updates even when it is minimized or the screen is locked.

christocracy commented 4 days ago

Have you read the wiki “Philosophy of Operation”?

the plug-in tracks when the device is detected to be moving. While sitting at your desk, you can expect the plug-in to not be tracking location. You need to go outside and move at least 200 meters. This is easily tested in the iOS Simulator with location simulated with “Freeway Drive”.

Habka commented 3 days ago

Yes, we did, and we tested it by minimizing the app and moving more than 200 meters, but no location request occurs after minimizing.

christocracy commented 3 days ago

debug: false,

The first thing to do is set that true.

See api docs .emailLog to learn how to fetch the plug-in logs.

also see wiki “Debugging”.

and test in the iOS simulator with “Freeway Drive”.

Habka commented 2 days ago

After reviewing the app in debug mode, I noticed that the notification popup remains as a "Stationary" even while moving in a car. Additionally, the "Motion and Fitness" permission prompt does not appear during installation (although it does show on Android). It’s worth mentioning that the NSMotionUsageDescription key is correctly included in the Info.plist file.

christocracy commented 2 days ago

If the motion permission is not requested, you did something wrong.

see the api docs .emailLog to learn how to retrieve the plug-in logs.

Habka commented 2 days ago

The issue is that it’s returning an empty file, and getLog returns {log: ""}. Is there a way to determine why this is happening? Regarding the motion permission, it used to display and work properly, but now it doesn’t, even though we haven’t changed the code. Any help would be greatly appreciated.

christocracy commented 2 days ago

logLevel: 'LOG_LEVEL_VERBOSE',

See the api docs for Config.logLevel. You’re doing it wrong. This option does not accept a String, as you’re doing it.

Habka commented 2 days ago

Thank you for your help! I fixed the configuration and checked the log, but I couldn’t identify the issue causing the motion permission popup not to appear.

{ activityRecognitionInterval = 10000; activityType = 1; authorization = { }; autoSync = 0; autoSyncThreshold = 0; batchSync = 0; debug = 1; desiredAccuracy = 10; desiredOdometerAccuracy = 100; didDeviceReboot = 0; didLaunchInBackground = 0; didRequestUpgradeLocationAuthorization = 1; disableAutoSyncOnCellular = 0; disableElasticity = 0; disableLocationAuthorizationAlert = 0; disableMotionActivityUpdates = 0; disableStopDetection = 0; distanceFilter = 10; elasticityMultiplier = 1; enableTimestampMeta = 0; enabled = 0; extras = { }; geofenceInitialTriggerEntry = 1; geofenceProximityRadius = 2000; geofenceTemplate = ""; headers = { }; heartbeatInterval = 60; httpRootProperty = location; httpTimeout = 60000; iOSHasWarnedLocationServicesOff = 0; isFirstBoot = 1; isMoving = 0; lastLocationAuthorizationStatus = 3; locationAuthorizationAlert = { cancelButton = Cancel; instructions = "You must enable 'WhenInUse' in location-services, in order to allow Weevi to access this device's location even when closed or not in use."; settingsButton = Settings; titleWhenNotEnabled = "Yo, location-services not enabled"; titleWhenOff = "Location tracking is OFF"; }; locationAuthorizationRequest = Always; locationTemplate = ""; locationTimeout = 60; locationsOrderDirection = ASC; logLevel = 5; logMaxDays = 3; maxBatchSize = "-1"; maxDaysToPersist = 1; maxRecordsToPersist = "-1"; method = POST; minimumActivityRecognitionConfidence = 70; odometer = 0; params = { }; pausesLocationUpdatesAutomatically = 1; persistMode = 2; preventSuspend = 0; schedule = ( ); schedulerEnabled = 0; showsBackgroundLocationIndicator = 1; startOnBoot = 0; stationaryRadius = 25; stopAfterElapsedMinutes = "-1"; stopDetectionDelay = 0; stopOnStationary = 0; stopOnTerminate = 1; stopTimeout = 5; trackingMode = 1; triggerActivities = ""; url = ""; useSignificantChangesOnly = 0; }

2024-11-23 18:10:09.146 ℹ️-[TSConfig persist]

2024-11-23 18:10:09.150 🔵-[TSLocationManager ready]

2024-11-23 18:10:09.157 ℹ️+[LocationAuthorization run:onCancel:] status: 0

2024-11-23 18:10:09.157 🔵+[LocationAuthorization run:onCancel:] Request: requestAlwaysAuthorization

2024-11-23 18:10:13.376 🔵-[LocationManager locationManager:didChangeAuthorizationStatus:] 4

2024-11-23 18:10:13.377 🔵-[LocationManager locationManager:didChangeAuthorizationStatus:] 4

2024-11-23 18:10:13.377 🔵-[PolygonGeofencingService locationManager:didChangeAuthorizationStatus:] 4

2024-11-23 18:10:13.378 ℹ️-[TSConfig persist]

2024-11-23 18:10:13.381 🔵-[TSLocationManager locationManager:didChangeAuthorizationStatus:] status 4

2024-11-23 18:10:13.389 🔵-[LocationManager locationManager:didChangeAuthorizationStatus:] 4

2024-11-23 18:10:13.389 🔵-[BackgroundTaskManager locationManager:didChangeAuthorizationStatus:] 4

2024-11-23 18:10:13.404 ℹ️+[LocationAuthorization run:onCancel:] status: 4

2024-11-23 18:10:13.404 ℹ️-[TSConfig persist]

2024-11-23 18:10:13.406 ℹ️+[LocationAuthorization run:onCancel:] Location authorization upgrade: WhenInUse -> Always

2024-11-23 18:10:13.406 🔵+[LocationAuthorization run:onCancel:] Request: requestAlwaysAuthorization

2024-11-23 18:10:15.503 🔵-[LocationManager locationManager:didChangeAuthorizationStatus:] 3

2024-11-23 18:10:15.504 🔵-[LocationManager locationManager:didChangeAuthorizationStatus:] 3

2024-11-23 18:10:15.504 🔵-[PolygonGeofencingService locationManager:didChangeAuthorizationStatus:] 3

2024-11-23 18:10:15.505 ℹ️-[TSConfig persist]

2024-11-23 18:10:15.508 🔵-[TSLocationManager locationManager:didChangeAuthorizationStatus:] status 3

2024-11-23 18:10:15.514 🔵-[LocationManager locationManager:didChangeAuthorizationStatus:] 3

2024-11-23 18:10:15.514 🔵-[BackgroundTaskManager locationManager:didChangeAuthorizationStatus:] 3

2024-11-23 18:10:15.518 🔴-[LocationManager stopWatchPosition] STOP

2024-11-23 18:10:16.523 🎾-[LocationManager watchPosition:] START

2024-11-23 18:10:16.527 ✅-[BackgroundTaskManager createBackgroundTask] 23

2024-11-23 18:10:16.530 ℹ️+[LocationAuthorization run:onCancel:] status: 3

2024-11-23 18:10:16.531 🎾-[LocationManager onWatchPositionTimer:] ONESHOT

2024-11-23 18:10:26.535 📍<+34.12779514,+36.12941067> +/- 16.94m (speed 0.00 mps / course -1.00) @ 11/23/24, 6:10:16 PM Eastern European Standard Time

2024-11-23 18:10:26.535 🔴-[LocationManager stopUpdatingLocation] OFF

2024-11-23 18:10:26.536 ╔═══════════════════════════════════════════════════════════ ║ -[LocationManager locationManager:didUpdateLocations:] Sample 1 of 1 (9971 ms old) ╚═══════════════════════════════════════════════════════════

2024-11-23 18:10:26.560 ✅-[LocationDAO unlock]_block_invoke UNLOCKED ALL RECORDS

2024-11-23 18:10:26.562 ✅-[TSLocationManager persistLocation:]_block_invoke INSERT: 9A394F01-27EF-4158-BBC8-04ED4CC0C2E7

2024-11-23 18:10:26.604 ℹ️-[TSDBLogger db_save] Log committed

2024-11-23 18:10:31.530 🎾-[LocationManager onWatchPositionTimer:] ONESHOT

christocracy commented 2 days ago

Post all your code where you’re interacting with BackgroundGeolocation.

Habka commented 2 days ago

Kindly find below the requested code:

Capacitor.Plugins.BackgroundGeolocation.addListener('watchposition', async function (location) {
    if (location.error == null) {
        $http.post("{url}/api/drivers/UpdateDriverLocation", {
            lat: location.coords.latitude,
            lng: location.coords.longitude,
            batteryIsCharging: location.battery.is_charging,
            batteryLevel: location.battery.level,
            altitude: location.coords.altitude,
            heading: location.coords.heading,
            speed: location.coords.speed,
            is_moving: location.is_moving,
            odometer: location.odometer,
            dateCreated: location.timestamp
        }, {
            headers: {
                accessToken: "{accesstoken}"
            }
        }).success(function (data1) {
        }).error(function (e, f) {
        });
    } else {
    }
}, function (error) {
    console.warn('[js] watch watchPosition FAILURE: ', error);
})

Capacitor.Plugins.BackgroundGeolocation.ready({
    options: {
        debug: true,
        logLevel: 5,
        locationAuthorizationRequest: 'Always',
        desiredAccuracy: 10,
        backgroundPermissionRationale: {
            title: "Allow Weevi to access this device's location even when 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'
        },
        locationAuthorizationAlert: {
            titleWhenNotEnabled: "Yo, location-services not enabled",
            titleWhenOff: "Location tracking is OFF",
            instructions: "You must enable 'WhenInUse' in location-services, in order to allow Weevi to access this device's location even when closed or not in use.",
            cancelButton: "Cancel",
            settingsButton: "Settings"
        },
        distanceFilter: 10,
        stopTimeout: 5,
        stopOnTerminate: true,
        startOnBoot: false,
        enableHeadless: false,
        autoSync: false
    }
}).then(async (state) => {
    try {
        var status = await Capacitor.Plugins.BackgroundGeolocation.requestPermission();
        console.log('[requestPermission] success: ', status);
    } catch (status) {
        console.warn('[requestPermission] FAILURE: ', status);
    }
    setTimeout(function () {
        Capacitor.Plugins.BackgroundGeolocation.watchPosition({
            options: {
                interval: 5000,
                desiredAccuracy: 10,
                persist: true
            }
        }).then(async (location) => {
            console.log('[js] watchPosition: ', location);
        }).catch(error => {
            console.warn('[js] watchPosition FAILURE: ', error);
        });
    }, 1000)

}).catch((error) => {
    console.warn('- BackgroundGeolocation configuration error: ', error);
});
christocracy commented 2 days ago

I don’t know where you got the idea to do what you’re doing, but it’s all wrong.

don’t use .watchPosition!

you just need to call .start().

christocracy commented 2 days ago

I suggest you see the Example in the readme.

Habka commented 2 days ago

Thank you, I will apply the .start, but this will fix the motion issue?

christocracy commented 2 days ago

Just start by following the suggested way of using the plug-in.

do not use .watchPosition. I have you no idea where you got the ideas how to write your code.

Habka commented 3 hours ago

Thank you so much for your help, it's working now.