javascript 你能用React Native跟踪后台地理位置吗?

ht4b089n  于 2023-01-01  发布在  Java
关注(0)|答案(5)|浏览(229)

问题

我希望能够跟踪用户的位置,即使应用程序不再在前台(例如,用户已切换到另一个应用程序或切换到主屏幕并锁定他们的手机)。
该用例是用户跟踪跑步。他们可以在跑步开始时打开应用程序并按下"开始",然后切换或最小化应用程序(按下主页按钮)并锁定屏幕。在跑步结束时,他们可以将应用程序带到前台并按下"停止",应用程序将告诉他们跑步的距离。

问题

使用pure react native可以在iOS和Android上跟踪后台地理位置吗?
关于地理定位的React原生文档(https://facebook.github.io/react-native/docs/geolocation)不是很清楚也不是很详细。上面的文档链接避开了iOS上的后台地理定位(没有完全清楚),但没有提到Android。
我用世博会是最好的吗?

rqmkfv5c

rqmkfv5c1#

更新2019年世博会33.0.0:
世博会第一次弃用它的SDK 32.0.0,以满足应用商店的指导方针,但后来reopened it in SDK 33.0.0
自从,他们已经使它超级容易能够实现后台定位。使用这个代码片段,我用来使后台地理定位工作。

import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
import * as TaskManager from 'expo-task-manager';
import * as Location from 'expo-location';

const LOCATION_TASK_NAME = 'background-location-task';

export default class Component extends React.Component {
  onPress = async () => {
    await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
      accuracy: Location.Accuracy.Balanced,
      timeInterval: 5000,
    });
  };

  render() {
    return (
      <TouchableOpacity onPress={this.onPress} style={{marginTop: 100}}>
        <Text>Enable background location</Text>
      </TouchableOpacity>
    );
  }
}

TaskManager.defineTask(LOCATION_TASK_NAME, ({ data, error }) => {
  if (error) {
    alert(error)
    // Error occurred - check `error.message` for more details.
    return;
  }
  if (data) {
    const { locations } = data; 
    alert(JSON.stringify(locations); //will show you the location object
    //lat is locations[0].coords.latitude & long is locations[0].coords.longitude
    // do something with the locations captured in the background, possibly post to your server with axios or fetch API 
  }
});

这段代码运行起来很有魅力。需要注意的一点是,你不能在Expo应用程序中使用地理定位功能。但是,你可以在你的独立版本中使用它。因此,如果你想使用后台地理定位功能,你必须使用这段代码,然后执行expo build:ios并上传到应用程序商店,以便能够获得用户的后台位置。
此外,请注意,您必须包括

"UIBackgroundModes":[
          "location",
          "fetch"
        ]

app.json文件的info.plist部分中。

6ljaweal

6ljaweal2#

Expo团队在SDK 32中发布了一个新特性,允许您在后台跟踪位置。
https://expo.canny.io/feature-requests/p/background-location-tracking

uz75evzq

uz75evzq3#

可以,但不使用Expo,我看到有两个模块:
这是一个商业版本,您必须购买许可证https://github.com/transistorsoft/react-native-background-geolocation
这个https://github.com/mauron85/react-native-background-geolocation

wnavrhmk

wnavrhmk4#

Webkit目前正在评估纯Javascript解决方案。您可以添加您的语音here
有关完整文档的概念验证示例,请参见Brotkrumen

xnifntxz

xnifntxz5#

最流行的RN地理定位库是https://github.com/react-native-geolocation/react-native-geolocation,它很容易支持这一点。我更喜欢这个库而不是其他库,因为它自动处理权限请求等,而且似乎有最简单的API。
就这么办吧:

Geolocation.watchPosition((position)=>{
    const {latitude, longitude} = position.coords;
    // Do something.
})

除了包括后台模式fetchlocation以及相应的使用说明外,不需要其他设置。
我发现这比Expo的API更有用,因为它不需要任何奇怪的顶级代码,也不需要我做任何事情,除了创建一个监视位置处理程序,这真的很好。

编辑2023!

这些天来,我强烈建议使用世博会的库,而不是任何其他社区库(主要是因为我们的应用程序开始崩溃时,android得到了一个操作系统更新b/c的库,我正在使用)。
事实上,如果你不得不在世博会图书馆和非世博会图书馆之间做出选择,那么只要是为了稳定性,就一定要选择世博会图书馆。设置世博会的后台位置监视并没有很好的记录,但我是这样做的,让它在我们的应用程序中工作的:

import { useEffect, useRef } from "react";
import * as Location from "expo-location";
import { LatLng } from "react-native-maps";
import * as TaskManager from "expo-task-manager";
import { LocationObject } from "expo-location";
import { v4 } from "uuid";
type Callback = (coords: LatLng) => void;
const BACKGROUND_TASK_NAME = "background";

const executor: (body: TaskManager.TaskManagerTaskBody<object>) => void = (
  body
) => {
  const data = body.data as unknown as { locations: LocationObject[] };
  const l = data?.locations[0];
  if (!l) return;

  for (const callback of Object.values(locationCallbacks)) {
    callback({
      latitude: l.coords.latitude,
      longitude: l.coords.longitude,
    });
  }
};

TaskManager.defineTask(BACKGROUND_TASK_NAME, executor);

const locationCallbacks: { [key: string]: Callback } = {};
const hasStartedBackgroundTaskRef = {
  hasStarted: false,
};

function startBackgroundTaskIfNecessary() {
  if (hasStartedBackgroundTaskRef.hasStarted) return;
  Location.startLocationUpdatesAsync(BACKGROUND_TASK_NAME, {
    accuracy: Location.Accuracy.Balanced,
  }).catch((e) => {
    hasStartedBackgroundTaskRef.hasStarted = false;
  });
  hasStartedBackgroundTaskRef.hasStarted = true;
}

function addLocationCallback(callback: Callback) {
  const id = v4() as string;
  locationCallbacks[id] = callback;
  return {
    remove: () => {
      delete locationCallbacks[id];
    },
  };
}

export default function useLocationChangeListener(
  callback: Callback | null,
  active: boolean = true
) {
  const callbackRef = useRef<null | Callback>(callback);
  callbackRef.current = callback;

  useEffect(() => {
    if (!active) return;
    if (!callback) return;
    Location.getLastKnownPositionAsync().then((l) => {
      if (l)
        callback({
          latitude: l.coords.latitude,
          longitude: l.coords.longitude,
        });
    });
    startBackgroundTaskIfNecessary();
    const watch = Location.watchPositionAsync({}, (location) => {
      callback({
        latitude: location.coords.latitude,
        longitude: location.coords.longitude,
      });
    });
    const subscription = addLocationCallback(callback);
    return () => {
      subscription.remove();
      watch.then((e) => {
        e.remove();
      });
    };
  }, [callback, active]);

  useEffect(() => {
    if (__DEV__) {
      addLocationCallback((coords) => {
        console.log("Location changed to ");
        console.log(coords);
      });
    }
  }, []);
}

在此之前,你需要请求后台位置权限,顺便说一句。
信任社区库来处理这类事情是相当危险的,因为破坏android操作系统的更新随时都可能发生,而开源维护者可能会也可能不会保持在它的顶部(尽管你也可以或多或少地信任expo)

相关问题