From cb453bf2008c7e4d62a0b993ee1b325e905b286d Mon Sep 17 00:00:00 2001 From: orfelorfel23 Date: Sun, 31 May 2026 20:25:33 +0200 Subject: [PATCH] Restrict expo-camera hardware pictureSize to prevent fatal native OutOfMemoryError crashes on high-res tablets --- src/screens/CameraScreen.tsx | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/screens/CameraScreen.tsx b/src/screens/CameraScreen.tsx index 6d5a89c3..7f908a87 100644 --- a/src/screens/CameraScreen.tsx +++ b/src/screens/CameraScreen.tsx @@ -73,6 +73,7 @@ export default function CameraScreen({ const [countdown, setCountdown] = useState(''); const [isCapturing, setIsCapturing] = useState(false); const [hasStarted, setHasStarted] = useState(false); + const [pictureSize, setPictureSize] = useState(undefined); // Burst mode state const [burstIndex, setBurstIndex] = useState(0); @@ -158,6 +159,40 @@ export default function CameraScreen({ }; }, []); + // Set safe picture size to avoid OOM + const handleCameraReady = async () => { + if (expoCameraRef.current) { + try { + const sizes = await expoCameraRef.current.getAvailablePictureSizes(); + if (sizes && sizes.length > 0) { + console.log('Available camera sizes:', sizes); + const parsedSizes = sizes.map(s => { + const parts = s.split('x'); + if (parts.length === 2) { + const w = parseInt(parts[0], 10); + const h = parseInt(parts[1], 10); + return { size: s, pixels: w * h, w, h }; + } + return { size: s, pixels: 0, w: 0, h: 0 }; + }).filter(s => s.pixels > 0); + + parsedSizes.sort((a, b) => a.pixels - b.pixels); + // Find the smallest size that has at least 1920 width or height (approx 2MP) + const optimal = parsedSizes.find(s => Math.max(s.w, s.h) >= 1920); + + if (optimal) { + console.log('Setting optimal pictureSize to prevent OOM:', optimal.size); + setPictureSize(optimal.size); + } else if (parsedSizes.length > 0) { + setPictureSize(parsedSizes[parsedSizes.length - 1].size); + } + } + } catch (e) { + console.warn('Failed to fetch picture sizes:', e); + } + } + }; + // Cancel capture process const handleLocalCancel = async () => { if (burstTimerRef.current) clearTimeout(burstTimerRef.current); @@ -503,6 +538,8 @@ export default function CameraScreen({ ref={expoCameraRef} style={styles.cameraPreview} facing="front" + pictureSize={pictureSize} + onCameraReady={handleCameraReady} /> )}