Camera access and photo library with Expo. Covers taking photos, picking from gallery, image manipulation, and permissions. Use when building features that involve photos, camera, or image uploads.
4a:Tc17,
npx expo install expo-camera expo-image-picker expo-media-library expo-file-system
Add to app.json or app.config.ts:
{
"expo": {
"plugins": [
[
"expo-camera",
{ "cameraPermission": "Allow $(PRODUCT_NAME) to access your camera." }
],
[
"expo-image-picker",
{ "photosPermission": "Allow $(PRODUCT_NAME) to access your photos." }
]
]
}
}
The most common pattern:
import * as ImagePicker from 'expo-image-picker';
async function pickImage() {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ['images'],
allowsEditing: true,
aspect: [1, 1],
quality: 0.8,
});
if (!result.canceled) {
const imageUri = result.assets[0].uri;
// Use imageUri for display or upload
return imageUri;
}
}
import * as ImagePicker from 'expo-image-picker';
async function takePhoto() {
// Request camera permission
const { status } = await ImagePicker.requestCameraPermissionsAsync();
if (status !== 'granted') {
Alert.alert('Permission needed', 'Camera access is required to take photos.');
return;
}
const result = await ImagePicker.launchCameraAsync({
allowsEditing: true,
aspect: [1, 1],
quality: 0.8,
});
if (!result.canceled) {
return result.assets[0].uri;
}
}
import storage from '@react-native-firebase/storage';
async function uploadImage(uri: string, userId: string): Promise<string> {
const filename = `${userId}/${Date.now()}.jpg`;
const ref = storage().ref(`images/${filename}`);
await ref.putFile(uri);
const downloadUrl = await ref.getDownloadURL();
return downloadUrl;
}
async function addPhoto() {
// 1. Pick image
const uri = await pickImage();
if (!uri) return;
// 2. Show loading state
setUploading(true);
// 3. Upload to Firebase Storage
const downloadUrl = await uploadImage(uri, auth().currentUser.uid);
// 4. Save reference to Firestore
await firestore().collection('photos').add({
userId: auth().currentUser.uid,
imageUrl: downloadUrl,
createdAt: firestore.FieldValue.serverTimestamp(),
});
setUploading(false);
}
import { Image } from 'react-native';
// From local URI (before upload)
<Image source={{ uri: localUri }} style={{ width: 200, height: 200 }} />
// From Firebase Storage URL (after upload)
<Image source={{ uri: downloadUrl }} style={{ width: 200, height: 200 }} />
quality: 0.8 or lower. Full-quality photos are huge.ref.putFile(uri).on('state_changed', ...) for upload progress.expo-image (fast cached image component) instead of Image for lists.