The below libraries are used in React Native development for handling document picking, permissions, image cropping, file system operations, and image compression. Here's a brief explanation of each:
react-native-document-picker: This library provides a React Native wrapper for native document picker functionality, allowing users to pick documents from their device.
react-native-permissions: This library facilitates handling runtime permissions in React Native applications. It allows you to check and request permissions.
react-native-image-crop-picker: A popular library for picking and cropping images. It simplifies the process of selecting and manipulating images in a React Native app.
react-native-fs: This library provides a set of file system utilities for React Native, allowing you to perform file-related operations such as reading, writing, and deleting files.
react-native-device-info: A library to get information about the device the app is running on. getSystemVersion specifically retrieves the system version.
react-native-compressor: This library allows you to compress images in a React Native app. It provides a simple interface for compressing images efficiently.
INSTALLATION:
yarn add react-native-document-picker react-native-permissions react-native-image-crop-picker react-native-fs react-native-device-info react-native-compressor && cd ios && pod install
or
npm i react-native-document-picker react-native-permissions react-native-image-crop-picker react-native-fs react-native-device-info react-native-compressor && cd ios && pod install
Configuration:
Android
- Add permissions in
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
iOS
- In
Podfile
add (ref.):
def node_require(script)
# Resolve script with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
"require.resolve(
'#{script}',
{paths: [process.argv[1]]},
)", __dir__]).strip
end
node_require('react-native/scripts/react_native_pods.rb')
node_require('react-native-permissions/scripts/setup.rb')
# ⬇️ uncomment wanted permissions
setup_permissions([
# 'AppTrackingTransparency',
# 'Bluetooth',
# 'Calendars',
# 'CalendarsWriteOnly',
'Camera',
# 'Contacts',
# 'FaceID',
# 'LocationAccuracy',
# 'LocationAlways',
# 'LocationWhenInUse',
'MediaLibrary',
# 'Microphone',
# 'Motion',
# 'Notifications',
'PhotoLibrary',
# 'PhotoLibraryAddOnly',
# 'Reminders',
# 'Siri',
# 'SpeechRecognition',
# 'StoreKit',
])
- In
info.plist
add these permission:
<key>NSCameraUsageDescription</key>
<string>Camera permission required.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Galley permission required.</string>
Picker.jsx
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
const YourComponent = () => {
const onPressItem = async (_, index) => {
setTimeout(async () => {
if (index === 0) {
const response = await requestDocumentWithPermission();
alert(JSON.stringify(response));
}
if (index === 1) {
const response = await requestGalleryWithPermission();
alert(JSON.stringify(response));
}
if (index === 2) {
const response = await requestCameraWithPermission();
alert(JSON.stringify(response));
}
}, 1000);
};
return (
<View>
<TouchableOpacity onPress={() => onPressItem(_, 0)} style={styles.button}>
<Text style={styles.buttonText}>Open Document</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => onPressItem(_, 1)} style={styles.button}>
<Text style={styles.buttonText}>Open Gallery</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => onPressItem(_, 2)} style={styles.button}>
<Text style={styles.buttonText}>Open Camera</Text>
</TouchableOpacity>
</View>
);
};
const styles = {
button: {
backgroundColor: '#3498db',
padding: 10,
marginVertical: 10,
borderRadius: 5,
alignItems: 'center',
},
buttonText: {
color: '#fff',
fontSize: 16,
},
};
export default YourComponent;
pickerHelper.js
import DocumentPicker, { types } from 'react-native-document-picker';
import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions';
import ImageCropPicker from 'react-native-image-crop-picker';
import RNFS from 'react-native-fs';
import { getSystemVersion } from 'react-native-device-info';
import { Image } from 'react-native-compressor';
const requestDocumentWithPermission = async () => {
try {
if (Platform.OS === 'android') {
// In android 13 no permission is needed
const deviceVersion = getSystemVersion();
let granted = PermissionsAndroid.RESULTS.DENIED;
if (deviceVersion >= 13) {
granted = PermissionsAndroid.RESULTS.GRANTED;
} else {
granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE
);
}
if (granted) {
return pickDocument();
}
} else {
// Handle iOS permissions if needed
return pickDocument();
}
} catch (error) {
console.log('Error checking/requesting permissions:', error);
return null;
}
};
const pickDocument = async () => {
try {
const result = await DocumentPicker.pick({
// allowMultiSelection: false,
type: [DocumentPicker.types.pdf],
});
if (result) {
console.log('Picked document:0', result);
const { name, size, type, uri } = result[0];
if (size > FILE_MAX_SIZE) {
Alert.alert('File Size Limit Exceeded', 'Please select a file up to 2 MB.');
} else {
return {
name,
type,
uri,
size,
};
}
}
} catch (err) {
if (DocumentPicker.isCancel(err)) {
// User cancelled the document picker
console.log('Document picker cancelled by user');
} else {
// Handle other errors
console.log('Error picking document:', err);
}
return null;
}
};
const requestCameraWithPermission = async () => {
try {
const cameraPermission = await check(PERMISSIONS.ANDROID.CAMERA);
if (cameraPermission === RESULTS.GRANTED) {
console.log('Camera permission already granted');
return pickImageFromCamera();
}
const cameraPermissionResult = await request(PERMISSIONS.ANDROID.CAMERA);
if (cameraPermissionResult === RESULTS.GRANTED) {
console.log('Camera permission granted');
return pickImageFromCamera();
}
console.log('Camera permission denied');
} catch (error) {
console.log('Error checking/requesting camera permission:', error);
return null;
}
};
const requestGalleryWithPermission = async () => {
try {
if (Platform.OS === 'android') {
const deviceVersion = getSystemVersion();
let granted = PermissionsAndroid.RESULTS.DENIED;
if (deviceVersion >= 13) {
granted = PermissionsAndroid.RESULTS.GRANTED;
} else {
granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE
);
}
if (granted) {
return pickImageFromGallery();
}
} else {
// On iOS, permissions are typically not required for accessing the photo library
console.log('iOS platform: No specific permissions required for media library');
return pickImageFromGallery();
}
} catch (error) {
console.log('Error checking/requesting storage permission:', error);
return null;
}
};
function getFileExtension(uri) {
const lastDotIndex = uri.lastIndexOf('.');
if (lastDotIndex !== -1) {
return uri.slice(lastDotIndex + 1);
}
return null; // or an appropriate default value
}
const pickImageFromCamera = async () => {
try {
const image = await ImageCropPicker.openCamera({
// width: 300,
// height: 400,
cropping: true,
multiple: false,
mediaType: 'photo',
});
if (image) {
const pathCompressed = await Image.compress(image?.path, {
// compress image below 2mb
maxWidth: 1500,
maxHeight: 1000,
});
const imageCompressed = await RNFS.stat(pathCompressed);
console.log('Picked image from gallery:0', image);
if (imageCompressed.size > FILE_MAX_SIZE) {
Alert.alert('File Size Limit Exceeded', 'Please select a file up to 2 MB.');
} else {
// The picked document is available in the 'result' object
return {
name: image?.filename || `image_${Date.now()}.${getFileExtension(imageCompressed?.path)}`,
type: image?.mime,
uri: imageCompressed?.path,
size: imageCompressed?.size,
};
}
}
} catch (error) {
console.log('Error picking image from camera:', error);
return null;
}
};
const pickImageFromGallery = async () => {
try {
const image = await ImageCropPicker.openPicker({
// width: 300,
// height: 400,
// cropping: true,
multiple: false,
mediaType: 'photo',
});
if (image) {
const pathCompressed = await Image.compress(image?.path, {
maxWidth: 1500,
maxHeight: 1000,
});
const imageCompressed = await RNFS.stat(pathCompressed);
console.log('Picked image from gallery:0', image, imageCompressed);
if (imageCompressed.size > FILE_MAX_SIZE) {
Alert.alert('File Size Limit Exceeded', 'Please select a file up to 2 MB.');
} else {
// The picked document is available in the 'result' object
return {
name: image?.filename || `image_${Date.now()}.${getFileExtension(imageCompressed?.path)}`,
type: image?.mime,
uri: imageCompressed?.path,
size: imageCompressed?.size,
};
}
}
} catch (error) {
console.log('Error picking image from gallery:', error);
return null;
}
};
const uploadFileImageOrPdf = async (fileBlob, isFromImagePicker = true) => {
try {
const formData = new FormData();
if (isFromImagePicker) {
formData.append('file', {
uri: fileBlob?.path,
type: fileBlob?.mime,
name: fileBlob?.filename, // Adjust the filename as needed
});
} else {
formData.append('file', {
uri: fileBlob[0]?.uri,
type: fileBlob[0]?.type,
name: fileBlob[0]?.name, // Adjust the filename as needed
});
}
const response = await fetch('YOUR_API_ENDPOINT', {
method: 'POST',
body: formData,
headers: {
'Content-Type': 'multipart/form-data',
// You may need to include additional headers depending on your API requirements
},
});
const responseData = await response.json();
console.log('File upload response:', responseData);
} catch (error) {
console.log('File upload error:', error);
}
};
export {
requestDocumentWithPermission,
requestCameraWithPermission,
requestGalleryWithPermission,
};
Top comments (0)