Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
ramkrushan-kaito opened this issue Sep 30, 2024 · 28 comments

Comments

@ramkrushan-kaito
Copy link

ramkrushan-kaito commented Sep 30, 2024

Your Environment

  • Plugin version: ^4.17.1
  • Platform: iOS or Android => iOS and Android
  • OS version: iOS 14 / Android 14
  • Device manufacturer / model: iOS (iPhone 12)
  • React Native version (react-native -v): React Native 0.71.x
  • Plugin config
PASTE_YOUR_CODE_HERE

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

Context

Debug logs

Logs
PASTE_YOUR_LOGS_HERE
@christocracy
Copy link
Member

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
Copy link
Author

I have updated it. Please check.

@christocracy
Copy link
Member

Plugin version: ?
Plug-in Config: ?

@ramkrushan-kaito
Copy link
Author

I have updated it. Please check.

@christocracy
Copy link
Member

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
Copy link
Member

christocracy commented Sep 30, 2024

Also.

Plugin config

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

@ramkrushan-kaito
Copy link
Author

// 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
Copy link
Author

Should I provide all my code to you?

@christocracy
Copy link
Member

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
Copy link
Author

^4.17.1

@ramkrushan-kaito
Copy link
Author

I have updated it. Please check.

@christocracy
Copy link
Member

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
Copy link
Author

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
Copy link
Member

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
Copy link
Author

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
Copy link
Member

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

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

@ramkrushan-kaito
Copy link
Author

{
"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
Copy link
Author

Should I provide you with my code?

@christocracy
Copy link
Member

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
Copy link
Author

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

<Text style={{ fontFamily: 'monospace', fontSize: 12 }}>{location}

);
};

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
Copy link
Member

@ramkrushan-kaito
Copy link
Author

ramkrushan-kaito commented Sep 30, 2024

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
Copy link
Member

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
Copy link
Member

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

@ramkrushan-kaito
Copy link
Author

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

@christocracy
Copy link
Member

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
Copy link
Author

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
Copy link
Member

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"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants