react-native-background-geolocation icon indicating copy to clipboard operation
react-native-background-geolocation copied to clipboard

Realtime Database Firebase

Open renangc90 opened this issue 1 year ago • 13 comments

I replaced sqlite with firebase, but it doesn't work with the app in the background

Your Environment

  • Plugin version: 4.16.3
  • Platform: Android
  • OS version: 13
  • Device manufacturer / model: Samsung A54
  • React Native version (react-native -v): 2.0.1
  • Plugin config

import React from 'react';
import { Switch, Text, View, PermissionsAndroid, Platform } from 'react-native';
import { dbFirebase } from '../../services/firebaseConfig';
import { set, ref } from 'firebase/database';

import BackgroundGeolocation from "react-native-background-geolocation";

const HelloWorld = () => {
  const [enabled, setEnabled] = React.useState(false);
  const [location, setLocation] = React.useState('');

  const sanitizeFirebaseKey = (key) => {
    return key.replace(/[\.\#\$\[\]]/g, '_');
  };

  React.useEffect(() => {
    const requestPermissions = async () => {
      if (Platform.OS === 'android') {
        try {
          const granted = await PermissionsAndroid.requestMultiple([
            PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
            PermissionsAndroid.PERMISSIONS.ACCESS_BACKGROUND_LOCATION,
          ]);
          if (
            granted[PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION] !== PermissionsAndroid.RESULTS.GRANTED ||
            granted[PermissionsAndroid.PERMISSIONS.ACCESS_BACKGROUND_LOCATION] !== PermissionsAndroid.RESULTS.GRANTED
          ) {
            console.error("Permissions not granted");
            return;
          }
        } catch (err) {
          console.warn(err);
        }
      }
    };

    requestPermissions();

    BackgroundGeolocation.ready({
      desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
      distanceFilter: 5,
      stopTimeout: 1,
      debug: true,
      logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
      stopOnTerminate: false,
      startOnBoot: true,
      foregroundService: true,
      notification: {
        title: "Background tracking",
        text: "Your location is being tracked",
      },
    }).then((state) => {
      setEnabled(state.enabled);
      console.log("- BackgroundGeolocation is configured and ready: ", state.enabled);

      const onLocation = BackgroundGeolocation.onLocation(async (location) => {
        console.log('[onLocation]', location);
        setLocation(JSON.stringify(location, null, 2));

        try {
          const sanitizedTimestamp = sanitizeFirebaseKey(new Date(location.timestamp).toISOString());
          const locationRef = ref(dbFirebase, `locations/${location.uuid}_${sanitizedTimestamp}`);
          await set(locationRef, {
            latitude: location.coords.latitude,
            longitude: location.coords.longitude,
            timestamp: location.timestamp
          });
          console.log("Location saved to Firebase");
        } catch (error) {
          console.error("Error saving location to Firebase: ", error);
        }
      });

      const onMotionChange = BackgroundGeolocation.onMotionChange((event) => {
        console.log('[onMotionChange]', event);
      });

      const onActivityChange = BackgroundGeolocation.onActivityChange((event) => {
        console.log('[onActivityChange]', event);
      });

      const onProviderChange = BackgroundGeolocation.onProviderChange((event) => {
        console.log('[onProviderChange]', event);
      });

      return () => {
        onLocation.remove();
        onMotionChange.remove();
        onActivityChange.remove();
        onProviderChange.remove();
      };
    }).catch(error => {
      console.error("Error during BackgroundGeolocation ready: ", error);
    });

  }, []);

  React.useEffect(() => {
    if (enabled) {
      BackgroundGeolocation.start().then(() => {
        console.log("BackgroundGeolocation started");
      }).catch(error => {
        if (error.message === "Waiting for previous start action to complete") {
          BackgroundGeolocation.stop().then(() => {
            console.log("BackgroundGeolocation stopped, restarting...");
            BackgroundGeolocation.start().then(() => {
              console.log("BackgroundGeolocation restarted");
            }).catch(error => {
              console.error("Error restarting BackgroundGeolocation: ", error);
            });
          }).catch(stopError => {
            console.error("Error stopping BackgroundGeolocation: ", stopError);
          });
        } else {
          console.error("Error starting BackgroundGeolocation: ", error);
        }
      });
    } else {
      BackgroundGeolocation.stop().then(() => {
        console.log("BackgroundGeolocation stopped");
      }).catch(error => {
        console.error("Error stopping BackgroundGeolocation: ", error);
      });
      setLocation('');
    }
  }, [enabled]);

  return (
    <View style={{ alignItems: 'center' }}>
      <Text>Click to enable BackgroundGeolocation</Text>
      <Switch value={enabled} onValueChange={setEnabled} />
      <Text style={{ fontFamily: 'monospace', fontSize: 12 }}>{location}</Text>
    </View>
  );
};

export default HelloWorld;

Expected Behavior

My app has the business rule of seeing online service providers in real time on a map. I would like this data to be sent even with the app in the background, so that I don't have to keep the map screen open

Actual Behavior

Only saves when it is in the foreground

Steps to Reproduce

Context

My app has the business rule of seeing online service providers in real time on a map. I would like this data to be sent even with the app in the background, so that I don't have to keep the map screen open

Debug logs

Logs

renangc90 avatar Jun 27 '24 12:06 renangc90

Do you know you need to travel at least 200 meters before tracking engages? You need to go outside and move.

christocracy avatar Jun 27 '24 12:06 christocracy

Yes, I walked 5000 meters and it didn't send data to Firebase

renangc90 avatar Jun 27 '24 15:06 renangc90

I’m not concerned about your Firebase. Does the plug-in make debug sound FX?

learn to fetch and analyze the plug-in logs. See wiki “Debugging”. Search api docs “emailLog”

christocracy avatar Jun 27 '24 15:06 christocracy

Issued, is it not compatible with realtime firebase?

renangc90 avatar Jun 27 '24 15:06 renangc90

You’re responsible for your own JavaScript code implementing Firebase. That’s not the plug-ins responsibility.

im only concerned with “does the plugin track location and emit debug soundFX.

christocracy avatar Jun 27 '24 15:06 christocracy

Please learn to syntax highlight codeblocks: https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks

christocracy avatar Jun 28 '24 16:06 christocracy

BackgroundGeolocation.ready({
      // Geolocation Config
      backgroundPermissionRationale: {
        title: 'Permitir acesso à sua localização em background',
        message:
          'Para obter sua localização com precisão, por favor permita que o App obtenha sua localização o tempo todo.',
        positiveAction: 'Configurar',
        negativeAction: 'Cancelar',
      },
      locationAuthorizationAlert: {
        titleWhenOff: 'Localização indisponível',
        titleWhenNotEnabled: 'Localização em background indisponível',
        instructions:
          'Para obter sua localização com precisão, por favor permita que o App obtenha sua localização o tempo todo.',
        settingsButton: 'Configurar',
        cancelButton: 'Cancelar',
      },
      notification: {
        title: 'Acompanhando sua localização',
        text: 'Acompanhamos sua localização para enviar corridas próximas e monitorar a entrega.',
      },
      desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
      distanceFilter: 10,
      // Activity Recognition
      stopTimeout: 5,
      // Application config
      debug: true, // <-- enable this hear sounds for background-geolocation life-cycle.
      logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
      stopOnTerminate: false,   // <-- Allow the background-service to continue tracking when user closes the app.
      startOnBoot: true,        // <-- Auto start tracking when device is powered-up.
      // HTTP / SQLite config
      url: 'https://shark-app-j3vbs.ondigitalocean.app/geolocationbackground',
      batchSync: false,       // <-- [Default: false] Set true to sync locations to server in a single HTTP request.
      autoSync: true,         // <-- [Default: true] Set true to sync each location to server as it arrives.
      headers: {              // <-- Optional HTTP headers
        // "X-FOO": "bar"
        "Authorization": `Bearer ${prestador.token}`
      },
      params: {               // <-- Optional HTTP params
        // "auth_token": "maybe_your_server_authenticates_via_token_YES?"
        "prestador_id": prestador.id,
        "nome": prestador.nome,
        "genero": prestador.genero,
        "foto_perfil": prestador.foto_perfil,
        "prestadorsubcategoria": prestador.prestadorsubcategoria
      }
    }).then((state) => {
      setEnabled(state.enabled)
      console.log("- BackgroundGeolocation is configured and ready: ", state.enabled);
    });

Do I need to do something special to send the parameters? It's only arriving with the screen on.

renangc90 avatar Jun 28 '24 16:06 renangc90

See api docs .emailLog. Learn to fetch and observe the plug-in logs.

and get rid of this: you do NOT need to do this.

if (error.message === "Waiting for previous start action to complete") {
          BackgroundGeolocation.stop().then(() => {
            console.log("BackgroundGeolocation stopped, restarting...");
            BackgroundGeolocation.start().then(() => {
              console.log("BackgroundGeolocation restarted");
            }).catch(error => {
              console.error("Error restarting BackgroundGeolocation: ", error);
            });
          }).catch(stopError => {
            console.error("Error stopping BackgroundGeolocation: ", stopError);
          });
        } else {
          console.error("Error starting BackgroundGeolocation: ", error);
        }

christocracy avatar Jun 28 '24 16:06 christocracy

import React, { useContext } from 'react';
import { Switch, Text, View, PermissionsAndroid } from 'react-native';
import BackgroundGeolocation from "react-native-background-geolocation";
import { AuthContext } from '../../contexts/AuthContext';
import api from '../../services/api';

const HelloWorld = () => {
  const [enabled, setEnabled] = React.useState(false);
  const [location, setLocation] = React.useState('');

  const { prestador } = useContext(AuthContext);

  React.useEffect(() => {
    const requestLocationPermissions = async () => {
      try {
        const granted = await PermissionsAndroid.requestMultiple([
          PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
          PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
          PermissionsAndroid.PERMISSIONS.ACCESS_BACKGROUND_LOCATION,
        ]);

        if (
          granted['android.permission.ACCESS_FINE_LOCATION'] === PermissionsAndroid.RESULTS.GRANTED &&
          granted['android.permission.ACCESS_COARSE_LOCATION'] === PermissionsAndroid.RESULTS.GRANTED &&
          granted['android.permission.ACCESS_BACKGROUND_LOCATION'] === PermissionsAndroid.RESULTS.GRANTED
        ) {
          console.log('Você tem todas as permissões de localização');
        } else {
          console.log('Permissões de localização negadas');
        }
      } catch (err) {
        console.warn(err);
      }
    };

    requestLocationPermissions();

    const onLocation = BackgroundGeolocation.onLocation(async (location) => {
      console.log('[onLocation]', location);
      setLocation(JSON.stringify(location, null, 2));

      let dados = {
        "prestador_id": prestador.id,
        "nome": prestador.nome,
        "genero": prestador.genero,
        "foto_perfil": prestador.foto_perfil,
        "prestadorsubcategoria": prestador.prestadorsubcategoria,
        "location": {
          "coords": {
            "latitude": location.coords.latitude,
            "longitude": location.coords.longitude,
          }
        }
      };
      
      try {
        const response = await api.post('/geolocationbackground/', dados, {
          headers: {
            'Authorization': `Bearer ${prestador.token}`
          }
        });
        console.log('Post successful: ', response.data);
      } catch (error) {
        console.error('Post failed: ', error);
      }
    });

    const onMotionChange = BackgroundGeolocation.onMotionChange((event) => {
      console.log('[onMotionChange]', event);
    });

    const onActivityChange = BackgroundGeolocation.onActivityChange((event) => {
      console.log('[onActivityChange]', event);
    });

    const onProviderChange = BackgroundGeolocation.onProviderChange((event) => {
      console.log('[onProviderChange]', event);
    });

    BackgroundGeolocation.ready({
      backgroundPermissionRationale: {
        title: 'Permitir acesso à sua localização em background',
        message: 'Para obter sua localização com precisão, por favor permita que o App obtenha sua localização o tempo todo.',
        positiveAction: 'Configurar',
        negativeAction: 'Cancelar',
      },
      locationAuthorizationAlert: {
        titleWhenOff: 'Localização indisponível',
        titleWhenNotEnabled: 'Localização em background indisponível',
        instructions: 'Para obter sua localização com precisão, por favor permita que o App obtenha sua localização o tempo todo.',
        settingsButton: 'Configurar',
        cancelButton: 'Cancelar',
      },
      notification: {
        title: 'Acompanhando sua localização',
        text: 'Acompanhamos sua localização para enviar corridas próximas e monitorar a entrega.',
      },
      desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
      distanceFilter: 10,
      stopTimeout: 5,
      debug: true,
      logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
      stopOnTerminate: false,
      startOnBoot: true,
      url: 'https://shark-app-j3vbs.ondigitalocean.app/geolocationbackground',
      batchSync: false,
      autoSync: true,
      headers: {
        "Authorization": `Bearer ${prestador.token}`
      },
      params: {
        "prestador_id": prestador.id,
        "nome": prestador.nome,
        "genero": prestador.genero,
        "foto_perfil": prestador.foto_perfil,
        "prestadorsubcategoria": prestador.prestadorsubcategoria
      }
    }).then((state) => {
      setEnabled(state.enabled);
      console.log("- BackgroundGeolocation is configured and ready: ", state.enabled);

      let Logger = BackgroundGeolocation.logger;
      Logger.emailLog('[email protected]')
        .then(success => {
          console.log(success, '[emailLog] success');
        })
        .catch(error => {
          console.log('[emailLog] FAILURE: ', error);
        });
    });

    return () => {
      onLocation.remove();
      onMotionChange.remove();
      onActivityChange.remove();
      onProviderChange.remove();
    };
  }, []);

  React.useEffect(() => {
    if (enabled) {
      BackgroundGeolocation.start();
    } else {
      BackgroundGeolocation.stop();
      setLocation('');
    }
  }, [enabled]);

  return (
    <View style={{ alignItems: 'center' }}>
      <Text>Click to enable BackgroundGeolocation</Text>
      <Switch value={enabled} onValueChange={setEnabled} />
      <Text style={{ fontFamily: 'monospace', fontSize: 12 }}>{location}</Text>
    </View>
  );
};

export default HelloWorld;

If I give setEnabled true in the Android emulator, it saves a post record on my server, but using the debug apk, if I enable it, nothing happens, that's all that's needed for it to work.

renangc90 avatar Jul 01 '24 11:07 renangc90

Are you observing the plug-in logs in adb logcat?

see wiki “Debugging”.

You can’t develop with this plugin without observing the native device logs.

christocracy avatar Jul 01 '24 12:07 christocracy

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] avatar Aug 01 '24 01:08 github-actions[bot]

Even using BackgroundGeolocation.NOTIFICATION_PRIORITY_MIN it still emits sound, could the API not emit any sound at all?

notification: {
                priority: BackgroundGeolocation.NOTIFICATION_PRIORITY_MIN,
                title: 'Acompanhando sua localização',
                text: 'Acompanhamos sua localização para enviar chamados de clientes próximos a você.',
            },

renangc90 avatar Aug 07 '24 10:08 renangc90

See api docs Config.debug

christocracy avatar Aug 07 '24 12:08 christocracy

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] avatar Sep 07 '24 01:09 github-actions[bot]

This issue was closed because it has been inactive for 14 days since being marked as stale.

github-actions[bot] avatar Sep 21 '24 02:09 github-actions[bot]