capacitor-community / background-geolocation

A Capacitor plugin that sends you geolocation updates, even while the app is in the background.
MIT License
190 stars 57 forks source link

Is called foreground #125

Open Rossella-Mascia-Neosyn opened 1 week ago

Rossella-Mascia-Neosyn commented 1 week ago

Describe the bug When the app starts I call the watch but it is called in the foreground and not in the background

To Reproduce

import { useRef } from 'react';

import { BackgroundGeolocationPlugin, Location } from '@capacitor-community/background-geolocation';

import { registerPlugin } from '@capacitor/core';

import { GeolocationData, IGeolocation } from '../geolocation.type';

const BackgroundGeolocation = registerPlugin<BackgroundGeolocationPlugin>('BackgroundGeolocation');

export const useNativeGeolocationBackground = (): IGeolocation => {
  const watchIdRef = useRef<string | null>(null);

  const startGeolocation = async () => {
    watchIdRef.current = await BackgroundGeolocation.addWatcher(
      {
        backgroundMessage: 'App is tracking your location in background',
        backgroundTitle: 'Background Tracking',
        requestPermissions: true,
        stale: false,
        distanceFilter: 50,
      },
      (position, error) => {
        if (error) {
          if (error.code === 'NOT_AUTHORIZED') {
            if (window.confirm('Location access is denied. Open settings to grant access?')) {
              BackgroundGeolocation.openSettings();
            }
          }
          console.error('Error during background tracking', error);
        }

        if (position) {
          const { latitude, longitude, accuracy, time } = position;
          console.log('Background position:', latitude, longitude);
          return {
            latitude,
            longitude,
            accuracy,
            timestamp: time,
          };
        } else {
          throw new Error('Position is undefined');
        }
      },
    );
  };

  const startTracking = async () => {
    try {
      console.info('Starting background geolocation');
      startGeolocation();
    } catch (error) {
      console.error('Error starting background geolocation', error);
    }
  };

  const stopTracking = async () => {
    try {
      if (watchIdRef.current !== null) {
        console.info('Stopping background geolocation');
        await BackgroundGeolocation.removeWatcher({ id: watchIdRef.current });
        watchIdRef.current = null;
      }
    } catch (error) {
      console.error('Error stopping background geolocation', error);
    }
  };

  const getCurrentPosition = async (): Promise<GeolocationData> => {
    let lastLocation: Location | undefined;

    try {
      const id = await BackgroundGeolocation.addWatcher(
        {
          requestPermissions: false,
          stale: true,
        },
        location => {
          lastLocation = location || undefined;
        },
      );

      if (lastLocation) {
        await new Promise(resolve => setTimeout(resolve, 10000));
        await BackgroundGeolocation.removeWatcher({ id });
        return {
          coords: {
            ...lastLocation,
          },
          timestamp: Date.now(),
        };
      }
      throw new Error(`Error current position is: ${lastLocation}`);
    } catch (error) {
      throw new Error(`Error while getting current position: ${error}`);
    }
  };

  return { startTracking, stopTracking, getCurrentPosition };
};

Expected behavior the expected behavior should be that it is only called in the background

Screenshots

https://github.com/user-attachments/assets/ee1a9e4d-9470-4ebe-8983-8081f621a2d1

Desktop (please complete the following information):

Smartphone (please complete the following information):

diachedelic commented 1 week ago

That is correct. When the backgroundMessage options is specified, location updates are delivered in both the foreground and the background. You could call App.getState() and ignore location updates that arrive in the foreground?

Rossella-Mascia-Neosyn commented 1 week ago

That is correct. When the backgroundMessage options is specified, location updates are delivered in both the foreground and the background. You could call App.getState() and ignore location updates that arrive in the foreground?

ahh okok very clear, thank you. I have other questions:

  1. This plugin is not a background runner right? and consequently does not have the limitation that sends the location every 15 minutes? https://capacitorjs.com/docs/apis/background-runner#limitations-of-background-tasks

  2. I can’t figure out why there is no local notification, what could be my mistake?

diachedelic commented 1 week ago
  1. No.
  2. Probably the notification icon is misconfigured. Make sure you follow the Android configuration instructions exactly.