Restrict expo-camera hardware pictureSize to prevent fatal native OutOfMemoryError crashes on high-res tablets
This commit is contained in:
@@ -73,6 +73,7 @@ export default function CameraScreen({
|
|||||||
const [countdown, setCountdown] = useState<number | string>('');
|
const [countdown, setCountdown] = useState<number | string>('');
|
||||||
const [isCapturing, setIsCapturing] = useState<boolean>(false);
|
const [isCapturing, setIsCapturing] = useState<boolean>(false);
|
||||||
const [hasStarted, setHasStarted] = useState<boolean>(false);
|
const [hasStarted, setHasStarted] = useState<boolean>(false);
|
||||||
|
const [pictureSize, setPictureSize] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
// Burst mode state
|
// Burst mode state
|
||||||
const [burstIndex, setBurstIndex] = useState<number>(0);
|
const [burstIndex, setBurstIndex] = useState<number>(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
|
// Cancel capture process
|
||||||
const handleLocalCancel = async () => {
|
const handleLocalCancel = async () => {
|
||||||
if (burstTimerRef.current) clearTimeout(burstTimerRef.current);
|
if (burstTimerRef.current) clearTimeout(burstTimerRef.current);
|
||||||
@@ -503,6 +538,8 @@ export default function CameraScreen({
|
|||||||
ref={expoCameraRef}
|
ref={expoCameraRef}
|
||||||
style={styles.cameraPreview}
|
style={styles.cameraPreview}
|
||||||
facing="front"
|
facing="front"
|
||||||
|
pictureSize={pictureSize}
|
||||||
|
onCameraReady={handleCameraReady}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
Reference in New Issue
Block a user