当用户在使用应用程序时禁用 GPS 位置共享时使用 expo 提醒用户

Using expo to alert user when he disabled GPS location sharing while using app

我正在开发一个基于 google 地图的应用程序。我正在使用 watchPositionAsync() 监视用户的位置。我想提醒用户,如果他在使用该应用程序时禁用位置共享,则他需要启用位置共享。就像在 google 地图导航中一样。

因此,如果我正在游览,并且如果我从移动下拉菜单中禁用位置共享,我想提示一个启用它的警报,因为如果没有用户的当前位置,导航将无法工作。

这段代码的问题是:

当我第一次使用此组件并接受位置共享时,如果稍后我在使用该应用程序时禁用位置共享,则不会收到提醒。我需要在某处使用 setLocationEnabled(true); 但我不知道在哪里

当我第一次进入这个组件并第一次拒绝位置共享时,如果我再次启用位置共享就不会被检测到。

import React, { useState, useEffect } from "react";
import { Alert, StyleSheet, Text, View } from "react-native";
import * as Location from "expo-location";

export default function App() {
  const [location, setLocation] = useState(null);
  const [watchId, setWatchId] = useState(null);
  const [locationEnabled, setLocationEnabled] = useState(false);

  useEffect(() => {
    (async () => {
      await Location.hasServicesEnabledAsync();
      setLocationEnabled(true);
      console.log("location enabled");
    })();
  }, []);

  useEffect(() => {
    Location.watchPositionAsync(
      {
        accuracy: Location.Accuracy.Highest,
        distanceInterval: 1,
        timeInterval: 10000,
      },
      (pos) => {
        setLocation(pos.coords);
      }
    )
      .then((locationWatcher) => {
        //set locationwatcher for removing
        setWatchId(locationWatcher);
      })
      .catch((err) => {
        setLocationEnabled(false);
        console.log("watchpositon error: ", err.message);
      });

    return () => {
      watchId && watchId.remove();
    };
  }, []);

  useEffect(() => {
    if (!locationEnabled) Alert.alert("You need to enable location sharing");
  }, [locationEnabled]);

  return (
    <View style={styles.container}>
      <Text style={styles.paragraph}>{JSON.stringify(location)}</Text>
    </View>
  );
}

您基本上需要检测用户是否返回您的应用(从后台返回)并在发生这种情况时重新检查权限。为此,请使用 AppState from react-native:

const [appState, setAppState] = useState(AppState.currentState);

useEffect(() => {
  // handler for app state changes
  const handleAppStateChange = async (nextAppState: AppStateStatus) => {
    setAppState(nextAppState);
  };

  // register the handler to listen for app state changes
  AppState.addEventListener('change', handleAppStateChange);

  // unsubscribe
  return () => AppState.removeEventListener('change', handleAppStateChange);
}, []);

useEffect(() => {
  // checks that app state changed to 'active' - user comes back from background or inactive state
  // note -- this will also trigger the first time you enter the screen
  if (appState === 'active') {
    // check location permission
    const locationPermission = await Location.requestPermissionsAsync();
    if (locationPermission.status !== 'granted') {
      // TODO: alert user about missing location permission
    }
  }
}, [appState]);

最后我使用了setInterval() hook。 这是一个例子:

  useEffect(() => {
    const interval = setInterval(() => {
      (async () => {
          const res = await Location.hasServicesEnabledAsync();
          if(!res) Alert.alert("No location")
        }
      })();
    }, 5000);
    return () => clearInterval(interval);
  }, []);