最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Native Expo Background Tasks continuously - Stack Overflow

programmeradmin1浏览0评论

I am currently developing an app where a user connects a bluetooth Beacon. When the distance (RSSI) gets to low an alarm (playing a loud sound) is triggered.

Now I have a question regarding background tasks:

The user should be able to lock his phone (single click on the PWR Button). Then, the app should still check if the RSSI is to low and play the sound when its triggered.

Is there a way to implement this in react native with expo? Learned React Native a few weeks ago so I am glad for any help ^^

Here is my code so far:

import React, { useState, useEffect } from "react";
import { SafeAreaView, StyleSheet, Text, TouchableOpacity, View, Image, Alert } from "react-native";
import useBLE from "./useBLE";
import Slider from "@react-native-community/slider";
import { LinearGradient } from 'expo-linear-gradient';
import CheckBox from '@react-native-community/checkbox';
import useAudioPlayer from './useAudioPlayer';
import useLocation from "./useLocation";

const audioSource = require('./img/alert.mp3');

const HomeScreen = () => {
  const { playSound, stopSound } = useAudioPlayer(audioSource);
  let { location } = useLocation();
  const {
    requestPermissions,
    scanForPeripherals,
    stopScan,
    setConnectedDevice,
    setDeviceSearching,
    connectedDevice,
    deviceSearching,
    rssi,
  } = useBLE();
  const [rssiAlert, setRssiAlert] = useState<boolean>(false);
  const [countdown, setCountdown] = useState<number | null>(null);
  const [startCountdown, setStartCountdown] = useState<boolean>(false);
  const [rssiTreshold, setRssiTrheshold] = useState<number>(-70);
  const [showMetaData, setShowMetaData] = useState<boolean>(false);


  useEffect(() => {
    if (rssi < rssiTreshold) {
      setStartCountdown(true);
    } else {
      setStartCountdown(false);
      setRssiAlert(false);
      setCountdown(null);
    }
  }, [rssi, rssiTreshold]);

  useEffect(() => {
    if (startCountdown) {
      setCountdown(5);
      const interval = setInterval(() => {
        setCountdown((prev) => {
          if (prev !== null && prev > 0) {
            return prev - 1;
          } else {
            clearInterval(interval);
            setRssiAlert(true);
            playSound();
            console.log(location);
            return null;
          }
        });
      }, 1000);

      return () => clearInterval(interval);
    }
  }, [startCountdown]);

  const handleScan = async () => {
    const isPermissionsEnabled = await requestPermissions();
    if (isPermissionsEnabled) {
      scanForPeripherals();
    }
  };

  const getBarColor = () => {
    if (rssi >= -50) return "green";
    if (rssi >= -70) return "yellow";
    return "red";
  };

  const resetApp = () => {
    stopScan();
    setConnectedDevice(null);
    setStartCountdown(false);
    setRssiAlert(false);
    setDeviceSearching(false);
    stopSound();
  }

  return (
    <LinearGradient
      colors={['#d9a7c7', '#fffcdc']}
      style={styles.container}
    >
      <SafeAreaView style={{ flex: 1 }}>
        <View style={styles.contentWrapper}>
          {connectedDevice ? (
            <>
              <Text style={styles.titleText}>Beacon verbunden!</Text>
              <Text style={styles.titleSubText}>Du reitest jetzt sicher!</Text>

              {rssiAlert ? <Image style={styles.unicornImage} source={require('./img/unicorn_smiling.png')} />
                : (<Image style={styles.unicornImage} source={require('./img/unicorn_smiling.png')} />)}


              {showMetaData ? (<>
                <Text style={styles.rssiText}>RSSI: {rssi}</Text>
                <View style={[styles.rssiBar, { width: `${100 + rssi}%`, backgroundColor: getBarColor() }]} />

                <Text style={styles.sliderLabel}>Schwellenwert: {rssiTreshold}</Text>
                <Slider
                  style={styles.slider}
                  minimumValue={-100}
                  maximumValue={-30}
                  step={1}
                  value={rssiTreshold}
                  onValueChange={setRssiTrheshold}
                  minimumTrackTintColor="red"
                  maximumTrackTintColor="gray"
                />

                {rssi < rssiTreshold && countdown !== null && (
                  <Text style={styles.countdownText}>Alarm in {countdown} Sekunden...</Text>
                )}
              </>) : (<></>)}

              {rssiAlert && <Text style={styles.alertText}>Ein Alarm wurde ausgelöst!</Text>}
              {location && <Text style={styles.alertText}>Deine Koordinaten: {location.coords.latitude}-{location.coords.longitude}</Text>}
            </>
          ) : (
            <>
              <Text style={styles.titleText}>Bitte verbinde einen Beacon!</Text>
              <Image style={styles.unicornImage} source={require('./img/unicorn_scanning.png')} />
              {deviceSearching ? <Text>Suche Beacon...</Text> : null}
            </>
          )}
        </View>

        <TouchableOpacity
          onPress={connectedDevice ? resetApp : handleScan}
          style={[styles.ctaButton]}
        >
          <Text style={styles.ctaButtonText}>
            {connectedDevice ? "Abbrechen" : "Beacon suchen"}
          </Text>
        </TouchableOpacity>

        <View style={styles.metaData}>
          <Text>Zeige Metadaten?</Text>
          <CheckBox
            value={showMetaData}
            onValueChange={(newValue: boolean) => setShowMetaData(newValue)}
          />
        </View>
      </SafeAreaView>
    </LinearGradient>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  connectedBackground: {
    backgroundColor: "#90EE90",
  },
  contentWrapper: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
  },
  titleText: {
    fontSize: 30,
    fontWeight: "bold",
    textAlign: "center",
    marginHorizontal: 20,
    color: "black"
  },
  titleSubText: {
    fontSize: 25,
    textAlign: "center",
    marginHorizontal: 20,
    color: "black"
  },
  pulse: {
    marginTop: 200,
  },
  unicornImage: {
    marginTop: 20,
    height: 220,
    width: 250
  },
  rssiText: {
    fontSize: 25,
    marginTop: 15,
  },
  alertText: {
    fontSize: 20,
    color: "red",
    marginTop: 10,
  },
  countdownText: {
    fontSize: 18,
    color: "orange",
    marginTop: 10,
  },
  rssiBar: {
    height: 20,
    borderRadius: 10,
    marginTop: 10,
    width: "50%",
  },
  sliderLabel: {
    fontSize: 18,
    marginTop: 20,
  },
  slider: {
    width: 200,
    height: 40,
  },
  ctaButton: {
    backgroundColor: "#FF6060",
    justifyContent: "center",
    alignItems: "center",
    height: 50,
    marginHorizontal: 20,
    marginBottom: 20,
    borderRadius: 8,
  },
  ctaButtonText: {
    fontSize: 18,
    fontWeight: "bold",
    color: "white",
  },
  metaData: {
    justifyContent: "center",
    alignItems: "center",
    flexDirection: "row"
  }
});

export default HomeScreen;
enter code here
发布评论

评论列表(0)

  1. 暂无评论