transistorsoft / react-native-background-geolocation

Sophisticated, battery-conscious background-geolocation with motion-detection
http://shop.transistorsoft.com/pages/react-native-background-geolocation
MIT License
2.58k stars 425 forks source link

Realtime Database Firebase #2072

Open renangc90 opened 1 week ago

renangc90 commented 1 week ago

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

Your Environment

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' }}>

Click to enable BackgroundGeolocation
  <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
<!--- reproduce this issue; include code to reproduce, if relevant -->
1.
2.
3.
4.

## 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
<!-- include iOS / Android logs
- ios XCode logs,
- use #getLog #emailLog methods (@see docs)
- Android: $ adb logcat -s TSLocationManager
-->
<details><summary>Logs</summary>

``` <!-- Syntax highlighting:  DO NOT REMOVE -->

christocracy commented 1 week ago

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

renangc90 commented 1 week ago

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

christocracy commented 1 week ago

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”

renangc90 commented 1 week ago

Issued, is it not compatible with realtime firebase?

christocracy commented 1 week ago

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 commented 1 week ago

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

renangc90 commented 1 week ago
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.

christocracy commented 1 week ago

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);
        }
renangc90 commented 6 days ago
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('castro.renan90@gmail.com')
        .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.

christocracy commented 6 days ago

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.