🐛 [Android] isActive change doesn't happen fast enough causing device/camera-already-in-use error when switching to native camera app
What's happening?
I have the isActive prop set to appState === 'active' as recommended in the documentation. However, when switching from my app with Camera on the screen to a native camera app that is already in the background (switching through recently opened apps screen), I encounter this error:
Camera.onError(device/camera-already-in-use): The given Camera Device is already in use! [device/camera-already-in-use: The given Camera Device is already in use!]
If I wait on the recently opened apps screen until I see that isActive is set to false in the log (which takes around a second) before switching to the native camera app, no error occurs.
Additionally, conditionally rendering the Camera component based on the appState value prevents the issue, but it degrades the user experience. Therefore, I prefer to keep using the isActive prop.
Also note that the camera is working perfectly fine despite this error, it just spams our logging service.
It seems that the camera remains active slightly longer than it should. Ideally, it should pause immediately when the app goes into the background, which as it seems, is currently not happening.
Relevant log output
05-22 15:23:04.940 6364 6364 I CameraView: Updating CameraSession...
05-22 15:23:04.940 6364 24503 I ReactNativeJNI: Memory warning (pressure level: TRIM_MEMORY_UI_HIDDEN) received by JS VM, ignoring because it's non-severe
05-22 15:23:04.942 6364 24503 I ReactNativeJS: 'error', { [device/camera-already-in-use: The given Camera Device is already in use!]
05-22 15:23:04.942 6364 24503 I ReactNativeJS: name: 'device/camera-already-in-use',
05-22 15:23:04.942 6364 24503 I ReactNativeJS: _code: 'device/camera-already-in-use',
05-22 15:23:04.942 6364 24503 I ReactNativeJS: _message: 'The given Camera Device is already in use!',
05-22 15:23:04.942 6364 24503 I ReactNativeJS: _cause: undefined }
Camera Device
{
"formats": [],
"sensorOrientation": "landscape-left",
"hardwareLevel": "full",
"maxZoom": 8,
"minZoom": 1,
"maxExposure": 20,
"supportsLowLightBoost": false,
"neutralZoom": 1,
"physicalDevices": [
"wide-angle-camera"
],
"supportsFocus": true,
"supportsRawCapture": false,
"isMultiCam": false,
"minFocusDistance": 10,
"minExposure": -20,
"name": "0 (BACK) androidx.camera.camera2",
"hasFlash": true,
"hasTorch": true,
"position": "back",
"id": "0"
}
Device
Samsung S21
VisionCamera Version
4.0.4
Can you reproduce this issue in the VisionCamera Example app?
I didn't try (⚠️ your issue might get ignored & closed if you don't try this)
Additional information
- [ ] I am using Expo
- [ ] I have enabled Frame Processors (react-native-worklets-core)
- [X] I have read the Troubleshooting Guide
- [X] I agree to follow this project's Code of Conduct
- [X] I searched for similar issues in this repository and found none.
Please try to reproduce this in VisionCamera Example, I remember testing this and this worked fine before.
Just fyi this is still a issue, tried to switch the camera frequently and switch to app and then came back to my RN app got this error
device/camera-already-in-use: The given Camera Device is already in use!
Hey! I also still have this issue. RNVC v4.6.1, Here are my logs from Sentry
08:20:53 CameraView: invokeOnAverageFpsChanged(0.0)
08:20:54 CameraView: invokeOnAverageFpsChanged(0.0)
08:20:55 CameraView: invokeOnAverageFpsChanged(0.0)
08:20:56 CameraView: invokeOnAverageFpsChanged(0.0)
...
08:21:02 CameraView: invokeOnAverageFpsChanged(0.0)
08:21:02 CameraSession: Output orientation changed! LANDSCAPE_RIGHT
08:21:02 CameraView: invokeOnOutputOrientationChanged(LANDSCAPE_RIGHT)
08:21:02 CameraSession: Output orientation changed! PORTRAIT
08:21:02 CameraView: invokeOnOutputOrientationChanged(PORTRAIT)
08:21:03 CameraView: invokeOnAverageFpsChanged(0.0)
...
08:21:10 CameraView: invokeOnAverageFpsChanged(0.0)
08:21:11 CameraSession: Output orientation changed! LANDSCAPE_RIGHT
08:21:11 CameraView: invokeOnOutputOrientationChanged(LANDSCAPE_RIGHT)
08:21:11 CameraSession: Output orientation changed! PORTRAIT
08:21:11 CameraView: invokeOnOutputOrientationChanged(PORTRAIT)
08:21:11 CameraSession: Output orientation changed! LANDSCAPE_RIGHT
08:21:11 CameraView: invokeOnOutputOrientationChanged(LANDSCAPE_RIGHT)
08:21:11 CameraSession: Output orientation changed! PORTRAIT
08:21:11 CameraView: invokeOnOutputOrientationChanged(PORTRAIT)
08:21:11 CameraView: invokeOnAverageFpsChanged(0.0)
08:21:11 CameraSession: Output orientation changed! LANDSCAPE_LEFT
08:21:11 CameraView: invokeOnOutputOrientationChanged(LANDSCAPE_LEFT)
08:21:11 CameraSession: Output orientation changed! PORTRAIT
08:21:11 CameraView: invokeOnOutputOrientationChanged(PORTRAIT)
08:21:12 CameraView: invokeOnAverageFpsChanged(0.0)
08:21:13 CameraView: invokeOnAverageFpsChanged(0.0)
08:21:13 CameraView: Updating CameraSession...
08:21:13 CameraSession: Camera State: OPENING (has error: true)
08:21:13 CameraView: invokeOnStopped()
08:21:13 CameraView: invokeOnError(...):
08:21:13 CameraSession: configure { ... }: Waiting for lock...
08:21:13 CameraSession: configure { ... }: Updating CameraSession Configuration... Difference(deviceChanged=false, outputsChanged=false, sidePropsChanged=false, isActiveChanged=true, orientationChanged=false, locationChanged=false)
08:21:13 CameraSession: Camera Lifecycle changed to STARTED!
08:21:13 CameraSession: Camera Lifecycle changed to CREATED!
08:21:13 CameraSession: configure { ... }: Completed CameraSession Configuration! (State: CREATED)
I am also getting this issue on android
I still have this issue using a Pixel 6 Pro with react-native 0.77.1 and react-native-vision-camera 4.6.4.
I'm using the camera in my react-native app and while isActive is true I switch to recently opened app to another app using the camera and I get this error.
Hello everyone. I recently noticed this error. The steps to trigger the error are as follows.
- Go to a page that uses the react-native-vision-camera component in your own application.
- On your Android phone, put the application in the background and open the phone's own camera application or any other application that uses the camera.
- Switch from open applications to your own application again. Now you are getting the error.
To solve this problem, listening to the AppState state and updating the "isActive" parameter in the Camera component solves this problem. I am leaving an example usage below.
UseForeground Hook:
import {useCallback, useEffect, useState} from 'react';
import {AppState, AppStateStatus} from 'react-native';
export const useForeground = () => {
const [foreground, setForeground] = useState(true);
const onChange = useCallback((state: AppStateStatus) => {
switch (state) {
case 'active':
setForeground(true);
break;
case 'inactive':
case 'background':
setForeground(false);
break;
case 'unknown':
case 'extension':
default:
break;
}
}, []);
useEffect(() => {
const listener = AppState.addEventListener('change', onChange);
return () => {
listener && listener.remove();
};
}, [onChange]);
return foreground;
};
Camera Usage:
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';
import {Camera, CameraProps, useCameraDevice} from 'react-native-vision-camera';
import {useIsFocused} from '@react-navigation/native';
import {useForeground} from '@utils/hooks/useForeground.ts';
const GtCamera = ({...props}: Partial<CameraProps>, ref: any) => {
const device = useCameraDevice('back');
const focused = useIsFocused();
const foreground = useForeground();
// Use if Focused and Foregrounded.
const isActive = focused && foreground;
if (!device) {
return (
<View style={[styles.wrapper]}>
<Text>Camera Error</Text>
</View>
);
}
return (
<View style={[styles.wrapper]}>
<Camera
ref={ref}
device={device}
isActive={isActive}
style={StyleSheet.absoluteFill}
{...props}
/>
</View>
);
};
const styles = StyleSheet.create({
wrapper: {
flex: 1,
position: 'relative',
backgroundColor: '#000',
},
});