Implementing Camera Access, Photo Capture, and Image Saving in React Native
Setting Up Camera Functionality in React Native
Project Initialization
To begin, create a new React Native project with the folowing command:
npx react-native init CameraApp --version 0.70.6
Dependency Installation
Add the required packages to your project:
// package.json
"dependencies": {
"@react-native-camera-roll/camera-roll": "^7.4.2",
"react-native-vision-camera": "2.15.4"
}
Install the packages using:
yarn add @react-native-camera-roll/camera-roll
yarn add react-native-vision-camera@2.15.4
Android Configuration
Update the AndroidManifest.xml file to include camera permissions:
<manifest>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:requestLegacyExternalStorage="true"
...
>
</application>
</manifest>
iOS Configuration
Add camera permissions to Info.plist:
<key>NSCameraUsageDescription</key>
<string>App requires camera access to take photos</string>
<key>NSMicrophoneUsageDescription</key>
<string>App requires microphone access for camera functionality</string>
Camera Implementation
Here's the complete implementation for the camera functionality:
import { useCameraDevices, Camera } from 'react-native-vision-camera'
import React, { useRef, useEffect, useState } from 'react'
import { PermissionsAndroid, Text, View, Button, Alert, Platform } from 'react-native'
import { CameraRoll } from "@react-native-camera-roll/camera-roll"
const CameraComponent = () => {
const cameraRef = useRef(null)
const [cameraPermission, setCameraPermission] = useState(false)
const [selectedDevice, setSelectedDevice] = useState(null)
const [devices, setDevices] = useState([])
useEffect(() => {
initializeCamera()
}, [])
const initializeCamera = async () => {
// Request camera permissions
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
{
title: 'Camera Access Required',
message: 'This app needs to access your camera to take photos.',
buttonNeutral: 'Ask Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
setCameraPermission(true)
// Get available camera devices
const availableDevices = useCameraDevices()
setDevices(availableDevices)
// Set default to back camera
if (availableDevices.back) {
setSelectedDevice(availableDevices.back)
}
} else {
setCameraPermission(false)
}
}
const switchCamera = () => {
if (selectedDevice === devices.back) {
setSelectedDevice(devices.front)
} else {
setSelectedDevice(devices.back)
}
}
const capturePhoto = async () => {
if (cameraRef.current && selectedDevice) {
try {
const capturedImage = await cameraRef.current.takePhoto()
console.log('Photo captured:', capturedImage)
saveToGallery(capturedImage)
} catch (error) {
console.error('Photo capture failed:', error)
}
}
}
const saveToGallery = async (image) => {
const imagePath = Platform.OS === 'android' ? 'file://' + image.path : image.path
CameraRoll.saveToCameraRoll(imagePath, 'photo')
.then(() => {
Alert.alert('Success', 'Photo saved to gallery')
})
.catch((error) => {
Alert.alert('Error', 'Failed to save photo')
})
}
return (
<view flex:="" style="{{">
{cameraPermission && selectedDevice ? (
<view>
<camera device="{selectedDevice}" height:="" isactive="{true}" photo="{true}" ref="{cameraRef}" style="{{" width:=""></camera>
<button onpress="{capturePhoto}" title="Capture"></button>
<button onpress="{switchCamera}" title="Switch Camera"></button>
</view>
) : (
<text>Camera permission not granted</text>
)}
</view>
)
}
export default CameraComponent
Base64 Image Saving
For saving imagess from base64 strings:
import RNFS from 'react-native-fs';
import { CameraRoll } from '@react-native-camera-roll/camera-roll';
import { Platform, PermissionsAndroid } from 'react-native';
const saveBase64Image = async (base64Image) => {
const imageData = base64Image.split('data:image/png;base64,')[1]
const timestamp = new Date().getTime()
const fileName = `${timestamp}photo.png`
if (Platform.OS === 'android') {
const storagePath = `${RNFS.ExternalDirectoryPath}/${fileName}`
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE
])
await RNFS.writeFile(storagePath, imageData, 'base64')
await CameraRoll.saveToCameraRoll('file://' + storagePath)
} else {
const storagePath = `${RNFS.DocumentDirectoryPath}/${fileName}`
await RNFS.writeFile(storagePath, imageData, 'base64')
await CameraRoll.saveToCameraRoll(storagePath)
}
}
export { saveBase64Image }