expo-camera & expo-image-picker
Fluxos de captura, permissões e prévias seguras em memória - o cookbook de câmera para aplicativos Expo SDK 57 que anexam fotos a formulários, perfis e relatórios de campo.
Busque em todas as páginas da documentação
Fluxos de captura, permissões e prévias seguras em memória - o cookbook de câmera para aplicativos Expo SDK 57 que anexam fotos a formulários, perfis e relatórios de campo.
Cartão de receita de referência rápida - pronto para copiar e colar.
npx expo install expo-camera expo-image-picker// app.config.ts
export default {
plugins: [
[
"expo-camera",
{
cameraPermission:
"Permita que o InspectPro fotografe equipamentos para ordens de serviço.",
microphonePermission:
"Permita que o InspectPro grave áudio com inspeções em vídeo.",
recordAudioAndroid: true,
},
],
[
"expo-image-picker",
{
photosPermission:
"Permita que o InspectPro anexe fotos existentes da sua biblioteca.",
},
],
],
};import * as ImagePicker from "expo-image-picker";
export async function pickImageFromLibrary() {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== "granted") return null;
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ["images"],
allowsEditing: true,
quality: 0.7,
exif: false,
});
if (result.canceled) return null;
return result.assets[0];
}Quando usar isso:
expo-camera (módulo BarcodeScanner).Quando evitar:
Prévia da câmera com portão de permissão, fallback da biblioteca e URI de prévia com escala reduzida.
npx expo install expo-camera expo-image-picker expo-image-manipulator// src/media/CaptureSheet.tsx
import { useRef, useState } from "react";
import { Image, Pressable, Text, View } from "react-native";
import { CameraView, useCameraPermissions } from "expo-camera";
import * as ImageManipulator from "expo-image-manipulator";
import * as ImagePicker from "expo-image-picker";
async function pickImageFromLibrary() {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== "granted") return null;
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ["images"],
allowsEditing: true,
quality: 0.7,
});
if (result.canceled) return null;
return result.assets[0];
}
type Props = {
onCaptured: (uri: string) => void;
};
export function CaptureSheet({ onCaptured }: Props) {
const cameraRef = useRef<CameraView>(null);
const [permission, requestPermission] = useCameraPermissions();
const [previewUri, setPreviewUri] = useState<string | null>(null);
if (!permission?.granted) {
return (
<View style={{ padding: 24, gap: 12 }}>
<Text>Fotografe etiquetas de equipamento para trilhas de auditoria.</Text>
<Pressable onPress={requestPermission}>
<Text style={{ color: "#2563eb" }}>Permitir câmera</Text>
</Pressable>
<Pressable
onPress={async () => {
const asset = await pickImageFromLibrary();
if (asset) await setDownscaledPreview(asset.uri);
}}
>
<Text>Escolher da biblioteca em vez disso</Text>
</Pressable>
</View>
);
}
async function setDownscaledPreview(uri: string) {
const manipulated = await ImageManipulator.manipulateAsync(
uri,
[{ resize: { width: 1280 } }],
{ compress: 0.75, format: ImageManipulator.SaveFormat.JPEG }
);
setPreviewUri(manipulated.uri);
}
async function takePhoto() {
const photo = await cameraRef.current?.takePictureAsync({
quality: 0.8,
skipProcessing: false,
});
if (photo?.uri) await setDownscaledPreview(photo.uri);
}
return (
<View style={{ flex: 1 }}>
{previewUri ? (
<View style={{ flex: 1, gap: 12, padding: 16 }}>
<Image
source={{ uri: previewUri }}
style={{ flex: 1, borderRadius: 8 }}
resizeMode="contain"
/>
<Pressable onPress={() => onCaptured(previewUri)}>
<Text style={{ fontWeight: "600" }}>Usar foto</Text>
</Pressable>
<Pressable onPress={() => setPreviewUri(null)}>
<Text>Retirar</Text>
</Pressable>
</View>
) : (
<CameraView ref={cameraRef} style={{ flex: 1 }} facing="back">
<Pressable onPress={takePhoto} style={{ margin: 24, padding: 16 }}>
<Text style={{ color: "#fff" }}>Capturar</Text>
</Pressable>
</CameraView>
)}
</View>
);
}O que isso demonstra:
useCameraPermissions para portão de permissão com fallback da biblioteca.takePictureAsync com limite de qualidade antes da passagem do manipulador.expo-image-manipulator redimensiona para 1280px de largura - prévia segura em memória.| Módulo | Melhor para | Permissão |
|---|---|---|
expo-camera | Prévia ao vivo, scan de código de barras, vídeo | Câmera (+ microfone para vídeo) |
expo-image-picker | UI de seleção da galeria / sistema | Biblioteca de fotos |
| Ambos | Fluxos de avatar com "Tirar foto" + "Escolher existente" | Solicitar apenas o que o usuário seleciona |
Arriscado: armazenar URI completa 4032×3024 no estado React + renderizar <Image />
Mais seguro: manipulateAsync → largura máxima 1280, JPEG 0.75
Upload: arquivo separado de resolução total em disco se o backend exigir - transmitir via FileSystemImage do React Native decodifica o bitmap completo - reduza a escala antes da prévia.previewUri após a conclusão do upload - libere referências de arquivo.expo-file-system File para corpos de upload - veja ./expo-file-system.md.const video = await cameraRef.current?.recordAsync({
maxDuration: 60,
});File.createUploadTask.<CameraView
barcodeScannerSettings={{ barcodeTypes: ["qr"] }}
onBarcodeScanned={({ data }) => handleScan(data)}
/>onBarcodeScanned dispara rapidamente.| API | Módulo | Propósito |
|---|---|---|
CameraView | expo-camera | Componente de prévia ao vivo |
useCameraPermissions | expo-camera | Hook de permissão |
takePictureAsync | expo-camera | Captura de imagem estática |
launchImageLibraryAsync | image-picker | Seleção da galeria |
launchCameraAsync | image-picker | Intenção da câmera do sistema |
manipulateAsync | image-manipulator | Redimensionar/comprimir |
<Image>.launchImageLibraryAsync falha. Correção: requestMediaLibraryPermissionsAsync.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
expo-camera | Overlay personalizado, escaneamento | Anexo simples de um único tiro |
launchCameraAsync | UX da câmera nativa é suficiente | Branding de visualizador personalizado |
expo-document-picker | PDFs e documentos | Apenas fotos |
| Native vision-camera | Processadores de quadro avançados | Fluxos de captura padrão |
npx expo install expo-camera expo-image-pickerAdicione strings de permissão ao plugin de configuração e reconstrua se as permissões nativas mudaram.
expo-file-system File.createUploadTask ou fetch com corpo de blob File.Platform.OS e ofereça entrada de arquivo na web.Versões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026