Может кто-нибудь понять, что я здесь пропустил? Заранее большое спасибо.
Вот мой код:
Код: Выделить всё
import React, { useState, useEffect } from 'react';
import { Text, View, Button } from 'react-native';
import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';
import * as Haptics from 'expo-haptics';
const DESTINATION_COORDS = {
latitude: 44.0041179865438,
longitude: -121.68169920997431,
};
const BACKGROUND_LOCATION_TASK = 'background-location-task-buzz-v2';
TaskManager.defineTask(BACKGROUND_LOCATION_TASK, async ({ data, error }) => {
if (error) {
console.error('Background location task error:', error.message);
return;
}
const { locations } = data;
if (locations && locations.length > 0) {
const { latitude, longitude } = locations[0].coords;
const distance = calculateDistance(
latitude,
longitude,
DESTINATION_COORDS.latitude,
DESTINATION_COORDS.longitude
);
if (distance < 10) {
await triggerHaptics();
console.log('found it.', Date.now());
}
}
});
const calculateDistance = (lat1, lon1, lat2, lon2) => {
const R = 6371; // Radius of the earth in km
const dLat = deg2rad(lat2 - lat1); // deg2rad below
const dLon = deg2rad(lon2 - lon1);
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2)
;
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const d = R * c; // Distance in km
return d * 1000; // Convert to meters
};
const deg2rad = (deg) => {
return deg * (Math.PI / 180);
};
const triggerHaptics = async () => {
await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
};
const BuzzOnArrival = () => {
const [currentLocation, setCurrentLocation] = useState(null);
const [distanceToDestination, setDistanceToDestination] = useState(null);
useEffect(() => {
// Start background location updates when component mounts
Location.startLocationUpdatesAsync(BACKGROUND_LOCATION_TASK, {
accuracy: Location.Accuracy.BestForNavigation,
timeInterval: 10000, // Check every 10 seconds
distanceInterval: 0,
showsBackgroundLocationIndicator: true,
});
// Clean up function to stop background location updates when component unmounts
return () => {
Location.stopLocationUpdatesAsync(BACKGROUND_LOCATION_TASK);
};
}, []);
useEffect(() => {
// Fetch current location every second
const interval = setInterval(() => {
fetchCurrentLocation();
}, 1000);
// Clean up function to clear the interval when component unmounts
return () => clearInterval(interval);
}, []);
const requestPermissions = async () => {
const { status: foregroundStatus } = await Location.requestForegroundPermissionsAsync();
if (foregroundStatus === 'granted') {
const { status: backgroundStatus } = await Location.requestBackgroundPermissionsAsync();
if (backgroundStatus === 'granted') {
await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
accuracy: Location.Accuracy.Balanced,
});
}
}
};
const fetchCurrentLocation = async () => {
const location = await Location.getCurrentPositionAsync({});
setCurrentLocation(location.coords);
// Calculate distance to destination
const distance = calculateDistance(
location.coords.latitude,
location.coords.longitude,
DESTINATION_COORDS.latitude,
DESTINATION_COORDS.longitude
);
setDistanceToDestination(distance);
};
const handleButtonPress = async () => {
await triggerHaptics();
};
return (
Listening for arrival...
{currentLocation && (
Current Location: {currentLocation.latitude}, {currentLocation.longitude}
)}
Destination: {DESTINATION_COORDS.latitude}, {DESTINATION_COORDS.longitude}
Distance to Destination: {distanceToDestination?.toFixed(2)} meters
);
};
export default BuzzOnArrival;
Код: Выделить всё
{
"name": "geocaster",
"version": "1.0.0",
"main": "expo-router/entry",
"scripts": {
"start": "expo start",
"android": "expo run:android",
"ios": "expo run:ios",
"web": "expo start --web"
},
"dependencies": {
"@gorhom/bottom-sheet": "^4.6.1",
"@react-native-async-storage/async-storage": "1.21.0",
"@reduxjs/toolkit": "^2.0.1",
"@supabase/supabase-js": "^2.39.3",
"base64-arraybuffer": "^1.0.2",
"expo": "~50.0.2",
"expo-av": "~13.10.3",
"expo-background-fetch": "^11.8.1",
"expo-camera": "~14.0.1",
"expo-constants": "~15.4.5",
"expo-crypto": "~12.8.0",
"expo-file-system": "~16.0.6",
"expo-haptics": "~12.8.1",
"expo-image-picker": "~14.7.1",
"expo-linking": "~6.2.2",
"expo-location": "~16.5.2",
"expo-media-library": "~15.9.1",
"expo-notifications": "~0.27.5",
"expo-router": "~3.4.4",
"expo-secure-store": "~12.8.1",
"expo-sensors": "~12.9.1",
"expo-status-bar": "~1.11.1",
"expo-task-manager": "~11.7.0",
"expo-updates": "~0.24.12",
"expo-web-browser": "~12.8.2",
"firebase": "^10.7.1",
"geolib": "^3.3.4",
"jszip": "^3.10.1",
"jszip-utils": "^0.1.0",
"lucide-react-native": "^0.314.0",
"pullstate": "^1.25.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.73.2",
"react-native-draggable-flatlist": "^4.0.1",
"react-native-easy-grid": "^0.2.2",
"react-native-gesture-handler": "^2.16.0",
"react-native-maps": "1.8.0",
"react-native-paper": "^5.12.1",
"react-native-progress": "^5.0.1",
"react-native-reanimated": "^3.8.1",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
"react-native-snap-carousel": "^3.9.1",
"react-native-svg": "14.1.0",
"react-native-web": "~0.19.6",
"react-redux": "^9.1.0",
"redux": "^5.0.1"
},
"devDependencies": {
"@babel/core": "^7.20.0"
},
"private": true
}
Код: Выделить всё
{
"expo": {
...
"ios": {
...,
"infoPlist": {
"UIBackgroundModes": ["location", "fetch"],
"NSLocationAlwaysAndWhenInUseUsageDescription": "Placeholder",
"NSLocationAlwaysUsageDescription": "Placeholder",
"NSLocationWhenInUseUsageDescription": "Placeholder",
}
},
...,
"plugins": [
"expo-router",
"expo-secure-store",
[
"expo-location",
{
"locationAlwaysAndWhenInUsePermission": "Placeholder",
"isAndroidBackgroundLocationEnabled": true,
"isIosBackgroundLocationEnabled": true
}
],
],
...
}
}
Код: Выделить всё
NSLocationUsageDescription
Use of location for determining waypoints and proximity
NSLocationWhenInUseUsageDescription
Use of location for determing waypoints and proximity
NSMicrophoneUsageDescription
The Microphone will be used to record videos for waypoints.
NSMotionUsageDescription
The of motion sensors required for the compass.
NSPhotoLibraryUsageDescription
The photo library can be used to select images and videos for upload.
NSUserActivityTypes
$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route
UIBackgroundModes
location
fetch
Я ожидаю, что он гудит, когда я приближаюсь к DESTINATION_COORDS примерно на десять метров, независимо от того, есть ли у меня приложение на переднем плане ИЛИ в фоновом режиме.
Сейчас оно гудит только тогда, когда приложение находится на переднем плане и компонент активно отображается на экране.
Подробнее здесь: https://stackoverflow.com/questions/784 ... und-on-ios