javascript 摄像机未准备好在react native中进行前台服务

3lxsmp7m  于 2023-01-08  发布在  Java
关注(0)|答案(1)|浏览(194)

我试图在前台拍照。例如,当用户在另一个程序中拍照。当我们在应用程序中一切都运行良好,但当我关闭应用程序,而前台服务处于活动状态时,相机停止工作,并给出此错误:

`WARN  Possible Unhandled Promise Rejection (id: 3):
session/camera-not-ready: [session/camera-not-ready] The Camera is not ready yet! Wait for the onInitialized() callback!`

我正在使用这个前台服务:https://notifee.app/react-native/docs/android/foreground-service和摄像头:https://github.com/mrousavy/react-native-vision-camera

    • 以下是我的代码:**
import React, {useRef, useState, useEffect} from 'react';
import {
  Button,
  PermissionsAndroid,
  SafeAreaView,
  StatusBar,
  StyleSheet,
  Text,
  View,
  LoadingView,
  ActivityIndicator,
  Image,
  TouchableOpacity,
} from 'react-native';
import {useCameraDevices, Camera} from 'react-native-vision-camera';
import {useIsForeground} from './hooks/useIsForeground';
import RNFS from 'react-native-fs';
import notifee, {AndroidColor} from '@notifee/react-native';

const HelloWorldApp = () => {
  const isAppForeground = useIsForeground();
  console.log('In Foreground?: ', isAppForeground);

  const cameraRef = useRef(null);
  const [finalPath, setPhotoPath] = useState('');

  const devices = useCameraDevices();
  const device = devices.front;

  useEffect(() => {
    console.log('useEffect');
    notifee.registerForegroundService(() => {
      console.log('registerForegroundService');
      return new Promise(() => {
        setInterval(() => {
          console.log('setInterval');
          const snapShotTaker = async () => {
            const snapshot = await cameraRef.current.takeSnapshot({
              quality: 20,
              skipMetadata: true,
            });
            console.log(snapshot);
            //const path = RNFS.ExternalDirectoryPath + '/photo-X.jpg';
            //await RNFS.moveFile(snapshot.path, path);
            setPhotoPath('file://' + snapshot.path);
            console.log(finalPath);
          };
          snapShotTaker();
        }, 2000);
      });
    });
  }, []);

  if (device == null) {
    return <ActivityIndicator style={styles.indicator} size="large" />;
  }

  async function onDisplayNotification() {
    // Request permissions (required for iOS)
    await notifee.requestPermission();

    // Create a channel (required for Android)
    const channelId = await notifee.createChannel({
      id: 'default',
      name: 'Default Channel',
    });

    // Display a notification
    await notifee.displayNotification({
      title: 'Foreground service',
      body: 'This notification will exist for the lifetime of the service runner',
      android: {
        channelId,
        asForegroundService: true,
        color: AndroidColor.RED,
        colorized: true,
      },
    });
  }

  return (
    <View style={styles.container}>
      <Camera
        ref={cameraRef}
        style={styles.camera}
        device={device}
        isActive={true}
      />
      <Image
        source={{uri: finalPath + '?' + new Date()}}
        style={[styles.image]}
      />

      <TouchableOpacity style={styles.button} onPress={onDisplayNotification}>
        <Text>Start F Service</Text>
      </TouchableOpacity>
    </View>
  );
};
ui7jx7zq

ui7jx7zq1#

您需要等待摄像头初始化为错误状态。根据视觉摄像头文档,您可以传递一个函数给onInitialized prop,并在调用该函数时开始拍摄快照。您可以通过存储一个默认值为false的布尔状态,在onInitialized prop回调函数中将该状态的值设置为true,以及在调用takeSnapshot方法之前在snapShotTaker函数中检查该状态的值是否为真。

import React, {useRef, useState, useEffect} from 'react';
import {
  Button,
  PermissionsAndroid,
  SafeAreaView,
  StatusBar,
  StyleSheet,
  Text,
  View,
  LoadingView,
  ActivityIndicator,
  Image,
  TouchableOpacity,
} from 'react-native';
import {useCameraDevices, Camera} from 'react-native-vision-camera';
import {useIsForeground} from './hooks/useIsForeground';
import RNFS from 'react-native-fs';
import notifee, {AndroidColor} from '@notifee/react-native';

const HelloWorldApp = () => {
  const isAppForeground = useIsForeground();
  console.log('In Foreground?: ', isAppForeground);

  const cameraRef = useRef(null);
  const [finalPath, setPhotoPath] = useState('');

  // Store a boolean state to indicate if the camera is ready
  const [isCameraReady, setIsCameraReady] = useState(false);

  const devices = useCameraDevices();
  const device = devices.front;

  useEffect(() => {
    console.log('useEffect');
    notifee.registerForegroundService(() => {
      console.log('registerForegroundService');
      return new Promise(() => {
        setInterval(() => {
          console.log('setInterval');
          const snapShotTaker = async () => {
            // Run the takeSnapshot method only if the camera is ready
            if (isCameraReady) {
              const snapshot = await cameraRef.current.takeSnapshot({
                quality: 20,
                skipMetadata: true,
              });
              console.log(snapshot);
              //const path = RNFS.ExternalDirectoryPath + '/photo-X.jpg';
              //await RNFS.moveFile(snapshot.path, path);
              setPhotoPath('file://' + snapshot.path);
              console.log(finalPath);
            }
          };
          snapShotTaker();
        }, 2000);
      });
    });
  }, []);

  if (device == null) {
    return <ActivityIndicator style={styles.indicator} size="large" />;
  }

  async function onDisplayNotification() {
    // Request permissions (required for iOS)
    await notifee.requestPermission();

    // Create a channel (required for Android)
    const channelId = await notifee.createChannel({
      id: 'default',
      name: 'Default Channel',
    });

    // Display a notification
    await notifee.displayNotification({
      title: 'Foreground service',
      body: 'This notification will exist for the lifetime of the service runner',
      android: {
        channelId,
        asForegroundService: true,
        color: AndroidColor.RED,
        colorized: true,
      },
    });
  }

  return (
    <View style={styles.container}>
      <Camera
        ref={cameraRef}
        style={styles.camera}
        device={device}
        isActive={true}

        // Set the camera to ready once it's initialized
        onInitialized={() => setIsCameraReady(true)}
      />
      <Image
        source={{uri: finalPath + '?' + new Date()}}
        style={[styles.image]}
      />

      <TouchableOpacity style={styles.button} onPress={onDisplayNotification}>
        <Text>Start F Service</Text>
      </TouchableOpacity>
    </View>
  );
};

相关问题