我的 Expo 应用程序遇到了问题,特别是后台位置跟踪和应用程序终止方面的问题,我希望从社区获得一些见解。
问题:
我已经实现了后台位置跟踪,它在前台和后台模式下都运行良好。但是,当我关闭应用程序时,我想完全停止位置跟踪。我有一段代码可以成功停止跟踪,但有一个问题:
停止位置跟踪后,应用程序不会完全终止。当我重新打开应用程序时,它无法正确重新加载状态、资产或其他资源。就像应用程序仍然挂在后台一样。 要正确重置所有内容,我必须手动强制关闭应用程序(例如,将其从应用程序切换器上滑开),这并不理想。
这是我正在使用的代码片段:
import { View, Text, Alert, Linking } from "react-native";
import React, { useEffect } from "react";
import { getDatabase, ref, set } from "firebase/database";
import { getAuth } from "firebase/auth";
import * as Location from "expo-location";
import * as TaskManager from "expo-task-manager";
const FB = getDatabase();
const BACKGROUND_LOCATION_TASK = "background-location-task";
TaskManager.defineTask(BACKGROUND_LOCATION_TASK, async ({ data, error }) => {
const auth = getAuth();
if (error) {
console.error(error);
return;
}
if (data) {
const { locations } = data as any;
const timestamp = new Date().toLocaleString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
hour12: true,
});
console.log(`[${timestamp}] Locations captured in the background`);
try {
await auth.authStateReady().then(() => {
const u = auth.currentUser;
if (u) {
const userLocation = ref(FB, `users/${u.uid}/location`);
set(userLocation, {
latitude: locations[0].coords.latitude,
longitude: locations[0].coords.longitude,
timestamp: Date.now(),
});
} else {
console.log("No user signed in");
}
});
} catch (error) {
console.error("Firebase error:", error);
}
}
});
const RootLayout = () => {
const showPermissionAlert = (message: string) => {
Alert.alert("Permission Required", message, [
{
text: "Cancel",
style: "cancel",
},
{
text: "OK",
onPress: () => {
Linking.openSettings();
},
},
]);
};
const checkAndRestartLocationUpdates = async () => {
const { status: foregroundStatus } =
await Location.requestForegroundPermissionsAsync();
if (foregroundStatus === "granted") {
const { status: backgroundStatus, canAskAgain } =
await Location.requestBackgroundPermissionsAsync();
if (backgroundStatus === "granted") {
await Location.startLocationUpdatesAsync(BACKGROUND_LOCATION_TASK, {
accuracy: Location.Accuracy.High,
timeInterval: 10000,
distanceInterval: 0,
foregroundService: {
notificationTitle: "Guardcon is tracking your location",
notificationBody: "Background location tracking is running",
killServiceOnDestroy: true,
},
});
} else {
if (!canAskAgain) {
showPermissionAlert(
"Please allow background location permissions to use the app"
);
} else {
await Location.requestBackgroundPermissionsAsync();
}
}
} else {
showPermissionAlert("Please allow location permissions to use the app");
}
};
const unregisterLocationTask = async () => {
try {
const isRegistered = await TaskManager.isTaskRegisteredAsync(BACKGROUND_LOCATION_TASK);
if (isRegistered) {
await Location.stopLocationUpdatesAsync(BACKGROUND_LOCATION_TASK);
await TaskManager.unregisterTaskAsync(BACKGROUND_LOCATION_TASK);
await TaskManager.unregisterAllTasksAsync();
console.log('Location Task Unregistered');
}
} catch (error) {
console.error('Error unregistering location task:', error);
}
};
useEffect(() => {
checkAndRestartLocationUpdates();
return () => {
unregisterLocationTask();
};
}, []);
return (
<View>
<Text>RootLayout</Text>
</View>
);
};
export default RootLayout;
这可以停止位置跟踪,但应用程序似乎仍部分处于活动状态,并且重新打开时不会完全重新加载。这发生在构建 apk 中。
我遇到了类似的问题,当我看到你的代码时,我以为这是你的 startLocation 配置,但我测试并工作正常。
就我而言,问题出在导航堆栈级别。我有两个由用户和属性定义的堆栈。但是,即使当我尝试等待完成所有清理工作时,某些状态仍然不干净。在定位任务之前不会发生这种情况。不知何故,让任务在后台运行与应用程序生命周期有关。
我的修复是按用户和属性删除这些堆栈,将它们替换为一个并手动重定向(因此,第一次加载它不依赖于这些身份验证状态)。 希望这可以帮助您找到快速解决方案。