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.63k stars 425 forks source link

Please provide me the code in React Native for both iOS and Android. #590 #2156

Open ramkrushan-kaito opened 2 weeks ago

ramkrushan-kaito commented 2 weeks ago

Your Environment

Expected Behavior

Please provide me the code in React Native for both iOS and Android.

My API endpoint is: https://bfsi.staypinc.com/api/admin/add/dummy/data

The API request should look like this: { "latitude": "30.34567", "longitude": "10.90781", "device": "ios", "address": "TALKAT TEST TEST" } I need to send latitude and longitude to my API when the app is in the killed state, background, or foreground. I only need the code for this functionality.

Actual Behavior

Steps to Reproduce

1. 2. 3. 4.

Context

Debug logs

Logs ``` PASTE_YOUR_LOGS_HERE ```
christocracy commented 2 weeks ago

Edit your issue and enter the required info:

Plugin version: Platform: iOS or Android OS version: Device manufacturer / model: React Native version (react-native -v): Plugin config

ramkrushan-kaito commented 2 weeks ago

I have updated it. Please check.

christocracy commented 2 weeks ago

Plugin version: ? Plug-in Config: ?

ramkrushan-kaito commented 2 weeks ago

I have updated it. Please check.

christocracy commented 2 weeks ago

Plugin version: Latest

Meaningless. open your package.json and look! It’s not hard to determine the version of any dependency you’re using.

christocracy commented 2 weeks ago

Also.

Plugin config

provide the Config you’re sending to .ready(config)!

ramkrushan-kaito commented 2 weeks ago
// Initialize BackgroundGeolocation
BackgroundGeolocation.ready({
  desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
  distanceFilter: 10,
  stopTimeout: 5,
  debug: true,
  logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
  stopOnTerminate: false, // Keep tracking when the app is terminated
  startOnBoot: true, // Start tracking when the device is booted
  heartbeatInterval: 60, // Send heartbeat every 60 seconds
  enableHeadless: true, // Allow running in headless mode (when app is terminated)
  foregroundService: true, // Keep service running in the foreground
  autoSync: true, // Automatically send location data to the server
  batchSync: false, // Don't batch locations for syncing
  maxDaysToPersist: 1, // Persist data for 1 day
  url: 'https://bfsi.staypinc.com/api/admin/add/dummy/data', // API endpoint for location updates
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_TOKEN"
  },
  params: {
    "device_id": "your-device-id"
  },
}).then(state => {
  setEnabled(state.enabled);
  console.log("BackgroundGeolocation", state);
});
ramkrushan-kaito commented 2 weeks ago

Should I provide all my code to you?

christocracy commented 2 weeks ago

Plugin version: 0.75.3

That version of THIS PLUG-IN does not exist.

https://github.com/transistorsoft/react-native-background-geolocation/blob/master/CHANGELOG.md

ramkrushan-kaito commented 2 weeks ago

^4.17.1

ramkrushan-kaito commented 2 weeks ago

I have updated it. Please check.

christocracy commented 2 weeks ago

Search api docs (linked in the table of contents of the readme here) “Config.locationTemplate”.

"device": "ios",

This is meta-data: search api docs “Config.params” to learn how to append your own arbitrary meta-data.

"address": "TALKAT TEST TEST"

The plug-in does not do “reverse geocoding”. The plug-in provides no mechanism for querying an address from latitude/longitude. That sort of thing is best done on the application server in a background job.

ramkrushan-kaito commented 2 weeks ago

Please provide me the code in React Native for both iOS and Android.

My API endpoint is: https://bfsi.staypinc.com/api/admin/add/dummy/data

The API request should look like this: { "latitude": "30.34567", "longitude": "10.90781", "device": "ios", or 'android' } I need to send latitude and longitude to my API when the app is in the killed state, background, or foreground. I only need the code for this functionality.

christocracy commented 2 weeks ago

See api docs Config.locationTemplate.

the comprehensive and searchable api docs are linked in the Table of Contents at the top of the readme.

ramkrushan-kaito commented 2 weeks ago

I'm using my API: https://bfsi.staypinc.com/api/admin/add/dummy/data, and I'm sending the latitude and longitude I receive from your BackgroundGeolocation to my API. They are being stored in my database. However, when I kill the app, I receive null values. I need the code for that.

christocracy commented 2 weeks ago

The plug-in does not send “null values”.

show me the JSON your server receives showing “null values”.

ramkrushan-kaito commented 2 weeks ago

{ "status": true, "status_code": 200, "message": "Success", "data": [ { "id": 900, "latitude": "30.34567", "longitude": "10.90781", "device": "ios", "address": "TALKAT TEST TEST", "created_at": "2024-09-30T13:21:11.000Z", "updated_at": "2024-09-30T13:21:11.000Z" }, { "id": 901, "latitude": null, "longitude": null, "device": "ios", "address": "TALKAT TEST TEST", "created_at": "2024-09-30T13:21:39.000Z", "updated_at": "2024-09-30T13:21:39.000Z" } ] }

ramkrushan-kaito commented 2 weeks ago

Should I provide you with my code?

christocracy commented 2 weeks ago

That is not data from the plug-in. That is your own representation of data you received.

The plug-in does not send “null values”. I suggest you have a close look at your server code.

ramkrushan-kaito commented 2 weeks ago

this is my app.js file code import React, { useEffect, useState } from 'react'; import { Switch, Text, View } from 'react-native'; import BackgroundGeolocation from 'react-native-background-geolocation'; import BackgroundFetch from 'react-native-background-fetch';

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

// Function to send the location manually to the API const callApiWithLocation = (loc) => { const coords = loc.coords; const latitude = coords?.latitude; const longitude = coords?.longitude;

console.log('latitude', latitude);
console.log('longitude', longitude);

const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");

const raw = JSON.stringify({
  "latitude": latitude.toString(),
  "longitude": longitude.toString(),
  "device": 'android',
  "address": 'TEST'
});

const requestOptions = {
  method: "POST",
  headers: myHeaders,
  body: raw,
  redirect: "follow"
};

fetch("https://bfsi.staypinc.com/api/admin/add/dummy/data", requestOptions)
  .then((response) => response.text())
  .then((result) => console.log(result))
  .catch((error) => console.error('Error:', error));

};

useEffect(() => { // Subscribe to BackgroundGeolocation events const onLocation = BackgroundGeolocation.onLocation((loc) => { console.log('[onLocation]', loc); setLocation(JSON.stringify(loc, null, 2)); callApiWithLocation(loc); // Call the API when location is updated });

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);
});

// Initialize BackgroundGeolocation
BackgroundGeolocation.ready({
  desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
  distanceFilter: 10,
  stopTimeout: 5,
  debug: true,
  logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
  stopOnTerminate: false, // Keep tracking when the app is terminated
  startOnBoot: true, // Start tracking when the device is booted
  heartbeatInterval: 60, // Send heartbeat every 60 seconds
  enableHeadless: true, // Allow running in headless mode (when app is terminated)
  foregroundService: true, // Keep service running in the foreground
  autoSync: true, // Automatically send location data to the server
  batchSync: false, // Don't batch locations for syncing
  maxDaysToPersist: 1, // Persist data for 1 day
  url: 'https://bfsi.staypinc.com/api/admin/add/dummy/data', // API endpoint for location updates
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_TOKEN"
  },
  params: {
    "device_id": "your-device-id"
  }
}).then(state => {
  setEnabled(state.enabled);
  console.log("- BackgroundGeolocation is configured and ready: ", state.enabled);
});

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

}, []);

// Start/stop BackgroundGeolocation based on the enabled state useEffect(() => { if (enabled) { BackgroundGeolocation.start(); } else { BackgroundGeolocation.stop(); setLocation(''); } }, [enabled]);

// Initialize Background Fetch useEffect(() => { BackgroundFetch.configure({ minimumFetchInterval: 15, // Fetch every 15 minutes stopOnTerminate: false, // Continue fetching even after app is terminated startOnBoot: true, // Start fetching when the device is booted enableHeadless: true // Ensure it works when the app is killed }, async (taskId) => { console.log("[BackgroundFetch] taskId:", taskId);

  // Fetch the latest location manually
  BackgroundGeolocation.getCurrentPosition({
    persist: true,
    samples: 1,
    timeout: 30
  }).then(loc => {
    console.log("[BackgroundFetch] Location:", loc);
    callApiWithLocation(loc);  // Call your API
  });

  BackgroundFetch.finish(taskId);
}, (error) => {
  console.log("[BackgroundFetch] failed to start:", error);
});

}, []);

return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>

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

); };

export default App;

index.js import { AppRegistry } from 'react-native'; import BackgroundFetch from 'react-native-background-fetch'; import BackgroundGeolocation from 'react-native-background-geolocation'; import App from './App'; import { name as appName } from './app.json';

// Headless task to handle background location fetch when the app is terminated const MyHeadlessTask = async (event) => { console.log("[BackgroundFetch HeadlessTask] start", event.taskId);

try { // Manually get the latest location const location = await BackgroundGeolocation.getCurrentPosition({ persist: true, samples: 1, timeout: 30, });

console.log("[BackgroundFetch HeadlessTask] Location:", location);

const { latitude, longitude } = location.coords;

// Prepare headers and body for the API request
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");

const raw = JSON.stringify({
  latitude: latitude.toString(),
  longitude: longitude.toString(),
  device: 'android',
  address: 'TEST'
});

const requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: raw,
  redirect: 'follow',
};

// Make the API call
const response = await fetch("https://bfsi.staypinc.com/api/admin/add/dummy/data", requestOptions);
const result = await response.text();
console.log("[API Response] Result:", result);

} catch (error) { console.error("[BackgroundFetch HeadlessTask] Error fetching location:", error); }

// Must call finish on the task BackgroundFetch.finish(event.taskId); };

AppRegistry.registerComponent(appName, () => App); BackgroundFetch.registerHeadlessTask(MyHeadlessTask);

christocracy commented 2 weeks ago

Please learn to syntax highlight “fenced code blocks”:

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

ramkrushan-kaito commented 2 weeks ago
import React, { useEffect, useState } from 'react';
import { Switch, Text, View } from 'react-native';
import BackgroundGeolocation from 'react-native-background-geolocation';
import BackgroundFetch from 'react-native-background-fetch';

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

  // Function to send the location manually to the API
  const callApiWithLocation = (loc) => {
    const coords = loc.coords;
    const latitude = coords?.latitude;
    const longitude = coords?.longitude;

    console.log('latitude', latitude);
    console.log('longitude', longitude);

    const myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");

    const raw = JSON.stringify({
      "latitude": latitude.toString(),
      "longitude": longitude.toString(),
      "device": 'android',
      "address": 'TEST'
    });

    const requestOptions = {
      method: "POST",
      headers: myHeaders,
      body: raw,
      redirect: "follow"
    };

    fetch("https://bfsi.staypinc.com/api/admin/add/dummy/data", requestOptions)
      .then((response) => response.text())
      .then((result) => console.log(result))
      .catch((error) => console.error('Error:', error));
  };

  useEffect(() => {
    // Subscribe to BackgroundGeolocation events
    const onLocation = BackgroundGeolocation.onLocation((loc) => {
      console.log('[onLocation]', loc);
      setLocation(JSON.stringify(loc, null, 2));
      callApiWithLocation(loc);  // Call the API when location is updated
    });

    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);
    });

    // Initialize BackgroundGeolocation
    BackgroundGeolocation.ready({
      desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
      distanceFilter: 10,
      stopTimeout: 5,
      debug: true,
      logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
      stopOnTerminate: false, // Keep tracking when the app is terminated
      startOnBoot: true, // Start tracking when the device is booted
      heartbeatInterval: 60, // Send heartbeat every 60 seconds
      enableHeadless: true, // Allow running in headless mode (when app is terminated)
      foregroundService: true, // Keep service running in the foreground
      autoSync: true, // Automatically send location data to the server
      batchSync: false, // Don't batch locations for syncing
      maxDaysToPersist: 1, // Persist data for 1 day
      url: 'https://bfsi.staypinc.com/api/admin/add/dummy/data', // API endpoint for location updates
      headers: {
        "Content-Type": "application/json",
        "Authorization": "Bearer YOUR_TOKEN"
      },
      params: {
        "device_id": "your-device-id"
      }
    }).then(state => {
      setEnabled(state.enabled);
      console.log("- BackgroundGeolocation is configured and ready: ", state.enabled);
    });

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

  // Start/stop BackgroundGeolocation based on the enabled state
  useEffect(() => {
    if (enabled) {
      BackgroundGeolocation.start();
    } else {
      BackgroundGeolocation.stop();
      setLocation('');
    }
  }, [enabled]);

  // Initialize Background Fetch
  useEffect(() => {
    BackgroundFetch.configure({
      minimumFetchInterval: 15,  // Fetch every 15 minutes
      stopOnTerminate: false,    // Continue fetching even after app is terminated
      startOnBoot: true,         // Start fetching when the device is booted
      enableHeadless: true       // Ensure it works when the app is killed
    }, async (taskId) => {
      console.log("[BackgroundFetch] taskId:", taskId);

      // Fetch the latest location manually
      BackgroundGeolocation.getCurrentPosition({
        persist: true,
        samples: 1,
        timeout: 30
      }).then(loc => {
        console.log("[BackgroundFetch] Location:", loc);
        callApiWithLocation(loc);  // Call your API
      });

      BackgroundFetch.finish(taskId);
    }, (error) => {
      console.log("[BackgroundFetch] failed to start:", error);
    });
  }, []);

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

export default App;
import { AppRegistry } from 'react-native';
import BackgroundFetch from 'react-native-background-fetch';
import BackgroundGeolocation from 'react-native-background-geolocation';
import App from './App';
import { name as appName } from './app.json';

// Headless task to handle background location fetch when the app is terminated
const MyHeadlessTask = async (event) => {
  console.log("[BackgroundFetch HeadlessTask] start", event.taskId);

  try {
    // Manually get the latest location
    const location = await BackgroundGeolocation.getCurrentPosition({
      persist: true,
      samples: 1,
      timeout: 30,
    });

    console.log("[BackgroundFetch HeadlessTask] Location:", location);

    const { latitude, longitude } = location.coords;

    // Prepare headers and body for the API request
    const myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");

    const raw = JSON.stringify({
      latitude: latitude.toString(),
      longitude: longitude.toString(),
      device: 'android',
      address: 'TEST'
    });

    const requestOptions = {
      method: 'POST',
      headers: myHeaders,
      body: raw,
      redirect: 'follow',
    };

    // Make the API call
    const response = await fetch("https://bfsi.staypinc.com/api/admin/add/dummy/data", requestOptions);
    const result = await response.text();
    console.log("[API Response] Result:", result);
  } catch (error) {
    console.error("[BackgroundFetch HeadlessTask] Error fetching location:", error);
  }

  // Must call finish on the task
  BackgroundFetch.finish(event.taskId);
};

AppRegistry.registerComponent(appName, () => App);
BackgroundFetch.registerHeadlessTask(MyHeadlessTask);
christocracy commented 2 weeks ago

You seem to be doing your own HTTP requests in addition to providing the plug-in an url. The plug-in is not responsible for your own custom http requests.

I suggest you do error checking on the data you receive from the plug-in before executing your http requests.

If you’re doing your own http request, i suggest you remove the url attribute from your plug-in config

christocracy commented 2 weeks ago

Btw, do you realize that the HeadlessTask is an Android-only mechanism? There’s no such thing as headless iOS.

ramkrushan-kaito commented 2 weeks ago

I am currently only testing on an Android device, not iOS.

christocracy commented 2 weeks ago

The plug-in is not responsible for invalid data of your own custom http requests.

I suggest you error-check the data you’re sending before you send it.

ramkrushan-kaito commented 2 weeks ago

But when I start the app, I am receiving the correct latitude and longitude, and I am passing it to my API. However, when the app is put into kill mode, I receive null values. I needed a solution for this. Please check my code in two files: app.js and index.js. Please provide me with the updated working code.

christocracy commented 2 weeks ago

But when I start the app, I am receiving the correct latitude and longitude,

I suggest you observe the plugin logs in $ adb logcat *:S TSLocationManager to see if anything unusual is reported in the logs. Also see Wiki "Debugging"