Agontuk / react-native-geolocation-service

React native geolocation service for iOS and android
https://www.npmjs.com/package/react-native-geolocation-service
MIT License
1.61k stars 291 forks source link

Search for location in the background - Android #427

Closed ifgabriel closed 10 months ago

ifgabriel commented 10 months ago

Platforms

Android

Versions

Please add the used versions/branches

AndroidManifest

  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

Code

  const handleLocationPermission = async () => {
    if (Platform.OS === 'android' && Platform.Version < '23') {
      return true;
    }
    const hasPermission = await PermissionsAndroid.check(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
    );
    if (hasPermission) {
      return true;
    }
    const status = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
    );
    if (status === PermissionsAndroid.RESULTS.GRANTED) {
      return true;
    }
    if (status === PermissionsAndroid.RESULTS.DENIED) {
      ToastAndroid.show('Permissão de localização negada pelo usuário.', ToastAndroid.LONG);
    } else if (status === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {
      ToastAndroid.show('Permissão de localização revogada pelo usuário', ToastAndroid.LONG);
    }
    return false;
  };

  useEffect(() => {
    const hasPermission = handleLocationPermission();

    const handleLocation = async () => {
      if (dutyId && hasPermission) {
        const handleTask = async () => {
          await new Promise(() => {
            Geolocation.watchPosition(
              async ({ coords }) => {
                if (BackgroundService.isRunning()) {
                  mutate({
                    position: {
                      latitude: coords.latitude,
                      longitude: coords.longitude,
                    },
                    speed: convertMetersPerSecondToKmPerHour(coords.speed),
                  });
                  setCoordinates({
                    latitude: coords.latitude,
                    longitude: coords.longitude,
                  });
                  BackgroundService.updateNotification(notificationOptions);
                }
              },

              undefined,
              {
                enableHighAccuracy: true,
                distanceFilter: 0,
                interval: TEN_SECONDS_FOR_MILLISECONDS,
                forceRequestLocation: true,
                showLocationDialog: true,
              }
            );
          });
        };

        await BackgroundService.start(handleTask, notificationOptions);
      } else {
        BackgroundService.stop();
      }
    };

    handleLocation();
  }, [mutate, occurrenceId, dutyId, notificationOptions]);

Expected

I'm trying to send a user's location to my API every 10 seconds. This should work if the screen is off, if the phone is using another app, etc. But this is not working correctly. I already used the backround example in src/example and it didn't work. Can anyone help me?

Tanani1994 commented 7 months ago

Can you tell me how did you fix it because I see you set it as completed? Thank you so much

ifgabriel commented 7 months ago

@Tanani1994 I gave up using this library, and use react-native-background-actions

I used this code

import BackgroundService from 'react-native-background-actions';

useEffect(() => {
    const handlePermission = async () => {
      await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_BACKGROUND_LOCATION, {
        title: '',
        message: '',
        buttonPositive: 'OK',
      });
    };

    const handleLocation = async () => {
      const handleTask = async () => {
        if (BackgroundService.isRunning()) {
          BackgroundService.updateNotification(notificationOptions);

          await new Promise(() => {
            Geolocation.watchPosition(
              ({ coords, mocked }) => {
               (YOUR FUNCTION)
              },
              undefined,
              {
                enableHighAccuracy: true,
                distanceFilter: 0,
                interval: 30000,
                forceRequestLocation: true,
                showLocationDialog: true,
              }
            );
          });
        } else {
          BackgroundService.stop();
        }
      };

      if (!BackgroundService.isRunning() && !!dutyId) {
        await BackgroundService.start(handleTask, notificationOptions);
      }
    };

    handlePermission();
    handleLocation();
  }, [mutate, occurrenceId, dutyId, notificationOptions]);

These permissions are required

  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

I hope it helped you

shafnashah95 commented 7 months ago

useEffect(() => { const handlePermission = async () => { await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_BACKGROUND_LOCATION, { title: '', message: '', buttonPositive: 'OK', }); };

const handleLocation = async () => {
  const handleTask = async () => {
    if (BackgroundService.isRunning()) {
      BackgroundService.updateNotification(notificationOptions);

      await new Promise(() => {
        Geolocation.watchPosition(
          ({ coords, mocked }) => {
           (YOUR FUNCTION)
          },
          undefined,
          {
            enableHighAccuracy: true,
            distanceFilter: 0,
            interval: 30000,
            forceRequestLocation: true,
            showLocationDialog: true,
          }
        );
      });
    } else {
      BackgroundService.stop();
    }
  };

  if (!BackgroundService.isRunning() && !!dutyId) {
    await BackgroundService.start(handleTask, notificationOptions);
  }
};

handlePermission();
handleLocation();

}, [mutate, occurrenceId, dutyId, notificationOptions]);

Can you explain what does this mutate, occurenceId, means and where is this defined is it in utils or screens?