使用expo实时后台定位 - React Native

问题描述 投票:0回答:1

我有一个应用程序,我需要跟踪车辆,为此,我有一个使用expo的反应本机应用程序,但我很难在后台跟踪车辆(当应用程序最小化时)并获取此数据使用网络套接字发送到我的后端。

我的组件,没有返回,因为这部分不重要:

import AsyncStorage from "@react-native-async-storage/async-storage";
import { useNavigation } from "@react-navigation/native";
import { LinearGradient } from "expo-linear-gradient";
import React, { useEffect, useState } from "react";
import dayjs from "dayjs";
import {
  KeyboardAvoidingView,
  Linking,
  ScrollView,
  Text,
  View,
} from "react-native";
import { Button } from "react-native-elements";
import Ionicons from "react-native-vector-icons/Ionicons";
import * as Location from "expo-location";
import * as TaskManager from "expo-task-manager";
import io from "socket.io-client";

import api from "../../../services/api";
import Theme from "../../../utils/globalTheme";
import styles from "./styles";

import CustomStatusBar from "../../../components/CustomStatusBar";
import DeclineButton from "../../../components/DeclineButton";
import FormButton from "../../../components/FormButton";
import FormInput from "../../../components/FormInput";
import ImageInputWithoutName from "../../../components/ImageInputWithoutName";
import Loading from "../../../components/Loading";
import ToastMessage from "../../../components/ToastMessage";
import { money } from "../../../utils/globalFunctions";

const LOCATION_TASK_NAME = "background-location-task";
let backgroundSubscription = null;

const socket = io("https://mysocketurl.com", {
  autoConnect: true,
  reconnection: true,
  reconnectionAttempts: Infinity,
  reconnectionDelay: 5000,
});

const FreightInProgress = () => {
  const navigation = useNavigation();

  const [position, setPosition] = useState(null);
  const [userId, setUserId] = useState(null);
  const [user, setUser] = useState("");

  const [freight, setFreight] = useState();
  const [aduanas, setAduanas] = useState([]);
  const [loading, setLoading] = useState(true);
  const [inProgress, setInProgress] = useState(false);

  const [canhotoPhoto, setCanhotoPhoto] = useState(null);

  useEffect(() => {
    const requestPermissions = async () => {
      const { granted } = await Location.requestBackgroundPermissionsAsync();
      if (!granted) {
        console.log("background location tracking not granted");
        return;
      }
    };
    requestPermissions();

    AsyncStorage.getItem("userId").then((userId) => {
      const id = JSON.parse(userId);
      setUserId(id);
    });

    AsyncStorage.getItem("user").then((user) => {
      const userJson = JSON.parse(user);
      setUser(userJson.nome);
    });
  }, []);

  TaskManager.defineTask(
    "background-location-task",
    async ({ data, error }) => {
      if (error) {
        console.error(error);
        return;
      }
      if (data) {
        const { locations } = data;
        const location = locations[0];
        setPosition(location);
        if (location) {
          socket.emit("coords", {
            latitude: location.coords.latitude,
            longitude: location.coords.longitude,
            usuario_id: userId,
            userName: user,
            freight: freight,
          });
        }
      }
    }
  );

  const finishFreight = async () => {
    if (canhotoPhoto != null) {
      try {
        const body = {
          canhoto: canhotoPhoto,
        };

        const resp = await api.put(
          `/freights/proofOfDelivery/${freight.id}`,
          body
        );

        if (resp.status == 200) {
          await api.put(`/freights/${freight.id}/status`, {
            status: "Concluído",
          });
          stopBackgroundUpdate();
          setCanhotoPhoto(null);
          navigation.navigate("Perfil");
          ToastMessage({
            type: "success",
            title: "Sucesso!",
            message: "Frete concluído!",
          });
        } else {
          ToastMessage({
            type: "error",
            title: "Erro!",
            message: "Erro ao enviar canhoto!",
          });
        }
      } catch (error) {
        console.log(error);
        ToastMessage({
          type: "error",
          title: "Erro ao iniciar frete!",
          message: "Tente novamente!",
        });
      }
    } else if (canhotoPhoto == null) {
      ToastMessage({
        type: "error",
        title: "Erro!",
        message: "Favor mandar canhoto!",
      });
    }
  };

  const stopBackgroundUpdate = () => {
    backgroundSubscription?.remove();
    setPosition(null);
  };

  const startBackground = async () => {
    const { granted } = await Location.requestBackgroundPermissionsAsync();
    if (!granted) {
      console.log("background location tracking not granted");
      return;
    }

    backgroundSubscription?.remove();

    backgroundSubscription = await Location.startLocationUpdatesAsync(
      "background-location-task",
      {
        accuracy: Location.Accuracy.BestForNavigation,
      }
    );
  };

  const getFreightById = async (driverId) => {
    try {
      const resp = await api.get(`/drivers/${driverId}/withFreight`);
      console.log(resp.data);
      if (resp.data.status == 1) {
        setInProgress(true);
      } else {
        setInProgress(false);
      }
      setFreight(resp.data);
      setAduanas(resp.data.Frete_Endereco.slice(1, -1));
      setLoading(false);
    } catch (error) {
      console.log(error);
      setFreight(undefined);
      setInProgress(false);
      setLoading(false);
    }
  };

  const handleStart = async () => {
    try {
      await api.put(`/freights/${freight.id}/status`, {
        status: "Andamento",
      });
      setInProgress(true);
      startBackground();
      ToastMessage({
        type: "success",
        title: "Sucesso!",
        message: "Frete iniciado!",
      });
    } catch (error) {
      console.log(error);
      ToastMessage({
        type: "error",
        title: "Erro ao iniciar frete!",
        message: "Tente novamente!",
      });
    }
  };

  const handleDeleteApplication = async () => {
    try {
      const body = {
        motorista_id: driverId,
      };
      const resp = await api.put(`/freights/application/exclude/${id}`, body);
      ToastMessage({
        type: "success",
        title: "Sucesso!",
        message: resp.data.message,
      });
      navigation.navigate("Candidaturas");
    } catch (error) {
      ToastMessage({
        type: "error",
        title: "Erro!",
        message: error.response.data.message,
      });
    }
  };

  const OpenURLButton = ({ url, title }) => {
    const handlePress = async () => {
      const supported = await Linking.canOpenURL(url);

      if (supported) {
        await Linking.openURL(url);
      } else {
        Alert.alert(`Não foi possível abrir a URL.`);
      }
    };

    return (
      <Button
        onPress={handlePress}
        title={title}
        buttonStyle={styles.linkButton}
        titleStyle={styles.linkButtonTitle}
      />
    );
  };

  useEffect(() => {
    navigation.addListener("focus", async () => {
      setLoading(true);
      await AsyncStorage.getItem("user").then((user) => {
        const userJson = JSON.parse(user);
        getFreightById(userJson.id);
      });
    });
  }, []);

return ("... my component here")
};

export default FreightInProgress;

我在上面尝试了这段代码,在前台,位置效果很好

javascript react-native websocket expo location
1个回答
0
投票

我在这方面遇到了其他麻烦(这就是我正在搜索该主题的原因),但您的 TaskManager.defineTask 应该在全局范围内声明,在 FreightInProcess 之外。希望这会有所帮助,尽管该帖子很旧......

© www.soinside.com 2019 - 2024. All rights reserved.