react-native-image-picker vs expo ImagePicker - react-native

I have tried many attempts to get react-native-image-picker up and working with my RN app. I am using Expo and VS Code and am not running the app with Xcode or Android Studio. There seems to be many options to getting the camera roll available in an app and I am not sure which is the best path to take. None seem to be working for me so I would like to pick the best path and focus on making that one route work.
I am following the documentation: https://github.com/react-native-community/react-native-image-picker
Things I have tried:
React Native Camera Roll
Expo ImagePicker
expo-image-picker
react-native-image-picker
react-images-upload
react-native-photo-upload
My code:
import React, {useState, useEffect} from 'react';
import {StyleSheet, View, TextInput, TouchableOpacity, Text, CameraRoll } from 'react-native'
import ImagePicker from 'react-native-image-picker';
// import * as ImagePicker from 'expo-image-picker';
import Constants from 'expo-constants';
const PicturesScreen = ({navigation}) => {
const [pictures, setPictures] = useState([]);
getPermissionAsync = async () => {
if (Constants.platform.ios) {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (status !== 'granted') {
alert('Sorry, we need camera roll permissions to make this work!');
}
}
};
useEffect(() => {
getPermissionAsync();
}, []);
selectPhotoTapped = () => {
const options = {
quality: 1.0,
maxWidth: 500,
maxHeight: 500,
storageOptions: {
skipBackup: true,
},
};
ImagePicker.showImagePicker(options, response => {
if (response.didCancel) {
console.log('User cancelled photo picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
let source = {uri: response.uri};
console.log('source: ' + source);
// You can also display the image using data:
// let source = { uri: 'data:image/jpeg;base64,' + response.data };
setPictures({
picture: source
});
}
});
};
return (
<View style = {styles.container}>
<TouchableOpacity style = {styles.buttonContainerPhoto} onPress={()=> selectPhotoTapped()}>
<Text style={styles.buttonText} >
Upload Photos
</Text>
</TouchableOpacity>
<TouchableOpacity style = {styles.buttonContainer} onPress={()=> navigation.navigate('NextScreen')}>
<Text style={styles.buttonText} >
Next
</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
...
}
});
export default PicturesScreen;
I have made sure to link the packages, I have also uninstalled and reinstalled and started from scratch a few times. I have downgraded the version to make it work but I still continue to get one of these error messages:
react-native-image-picker: NativeModule.ImagePickerManager is null
or
Can not read property 'showImagePicker' of undefined.
or
undefined is not an object(evaluating 'imagepickerManager.showimagepicker')
Is it causing issues because I am using Expo? Should I just be using CameraRoll with react-native?

Use expo-image-picker if you're using Expo.
Anything that requires the use of react-native link will not work with Expo, unless stated that it is already included in Expo.

I was stuck with the same issue, and now I have resolved this. React native cli and expo cli both have some package differences. Similarly image-picker for both works differently.
For expo cli, you can check the documentation here: https://docs.expo.io/versions/latest/sdk/imagepicker/#__next
You can try for uploading image via camera using ImagePicker.launchCameraAsync and from photo library using ImagePicker.launchImageLibraryAsync.
While in react-native cli I was able to write a single function to choose from both camera and photo library but could not find a way for the same in expo yet.

Related

react-native-fs - Error: Attempt to invoke virtual method 'byte[] java.lang.String.getBytes()' on a null object reference

I was try to pick a photo with react-native-image-picker, this works. So I tried to get the photo path that I choose with image picker and store a copy in diferent path with react-native-fs.
But when I try this second step I receive a error.
[Error: Attempt to invoke virtual method 'byte[] java.lang.String.getBytes()' on a null object reference]
I dont know if its a wrong configuration on /android for react-native-fs works, or any else
import React, { useState } from 'react';
import {
Text,
View,
Image,
Button,
Alert
} from 'react-native';
import RNFS from 'react-native-fs'
const path = RNFS.ExternalDirectoryPath + '/test.jpeg';
import {launchImageLibrary} from 'react-native-image-picker';
const App = () => {
const [uri, setUri] = useState('d')
return (
<>
<Text>jhhhh{uri}</Text>
<Image
style={{width: 100, height: 100}}
source={{uri:uri}}
/>
<Button
onPress={()=>{
launchImageLibrary( { mediaType: 'photo', includeBase64: true }, result => {
console.log(result.assets[0].uri)
setUri(result.assets[0].uri)
console.log( RNFS.ExternalDirectoryPath )
RNFS.writeFile(path,result.base64, 'base64')
.then(
() => Alert(path)
).catch(e => console.log(e))
} )
}}
title="GO"
/>
</>
)
};
export default App;
note: I noticed that the recent version of react already does auto linkg and the react-native-fs doc says to do this manually, so I skipped the last step.
When I did the last step it returned with an error saying the import was about writing itself.
Edit:
DocumentDirectoryPath or ExternalDirectoryPath I received the same error

Is there a Share library like this one out there? for React native

I have been seeing this Share library in many new Apps and I was wondering if there is one like it already. if not, how does one trigger opening WhatsApp and Facebook in React Native? thank you
You can use import { Share} from 'react-native'
import React from 'react';
import { Share, View, Button } from 'react-native';
const ShareExample = () => {
const onShare = async () => {
try {
const result = await Share.share({
message:
'React Native | A framework for building native apps using React',
});
if (result.action === Share.sharedAction) {
if (result.activityType) {
// shared with activity type of result.activityType
} else {
// shared
}
} else if (result.action === Share.dismissedAction) {
// dismissed
}
} catch (error) {
alert(error.message);
}
};
return (
<View style={{ marginTop: 50 }}>
<Button onPress={onShare} title="Share" />
</View>
);
};
export default ShareExample;
or
react-native-share library
npm i react-native-share --save to get your desired result.
One solution is to use Linking.openURL and social_icon together
(A) For social icons, you may install and use by referring to this official link:
https://reactnativeelements.com/docs/social_icon/
(B) For opening social media / email, etc thru Linking.openURL, the following are some examples:
Linking.openURL('fb://page/PAGE_ID');
Linking.openURL('http://instagram.com/_u/USER_NAME');
Linking.openURL('http://instagram.com/_p/PICTURE');
Linking.openURL('mailto:support#example.com')
Note: you have to import Linking , such as follows:
import { Button, Linking, View } from 'react-native';

React native camera not working as expected with expo

I want to make a qrcode reader with react native,and i'm using expo.I'm following the guide based on the official documentation here : react-native-qrcode-scanner
I've installed react-native-camera succesfully by running npm install react-native-camera --save and the following is the commande react-native link react-native-camera in the console,and it gives me the following error:
By reading the doc if find that many things depend on react-native link like react-native link react-native-qrcode-scanner
react-native link react-native-permissions an also after that there are some configurations like <uses-permission android:name="android.permission.VIBRATE"/> that i cannot do because i don't use react-native-cli.
Expo already has what you want. expo-barcode-scanner
If your version of Expo is 33, you should download it individually.
You can run expo install expo-barcode-scanner
You must request permission to access the user's camera before attempting to get it. To do this, you will want to use the Permissions API. You can see this in practice in the following example.
Basic Example
import * as React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import Constants from 'expo-constants';
import * as Permissions from 'expo-permissions';
import { BarCodeScanner } from 'expo-barcode-scanner';
export default class BarcodeScannerExample extends React.Component {
state = {
hasCameraPermission: null,
scanned: false,
};
async componentDidMount() {
this.getPermissionsAsync();
}
getPermissionsAsync = async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA);
this.setState({ hasCameraPermission: status === 'granted' });
};
render() {
const { hasCameraPermission, scanned } = this.state;
if (hasCameraPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasCameraPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View
style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-end',
}}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : this.handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
/>
{scanned && (
<Button title={'Tap to Scan Again'} onPress={() => this.setState({ scanned: false })} />
)}
</View>
);
}
handleBarCodeScanned = ({ type, data }) => {
this.setState({ scanned: true });
alert(`Bar code with type ${type} and data ${data} has been scanned!`);
};
}
props
onBarCodeScanned (function)
Callback that is invoked when a bar code has been successfully scanned. The callback is provided with an object of the shape { type: BarCodeScanner.Constants.BarCodeType, data: string }, where the type refers to the bar code type that was scanned and the data is the information encoded in the bar code (in this case of QR codes, this is often a URL). See BarCodeScanner.Constants.BarCodeType for supported values.
barCodeTypes (Array)
An array of bar code types. Usage: BarCodeScanner.Constants.BarCodeType.<codeType> where codeType is one of the listed above. Default: all supported bar code types. For example:
barCodeTypes={[BarCodeScanner.Constants.BarCodeType.qr]}
type (string)
-- Camera facing. Use one of BarCodeScanner.Constants.Type. Use either Type.front or Type.back. Same as Camera.Constants.Type. Default: Type.back.
Note: Passing undefined to the onBarCodeScanned prop will result in no scanning. This can be used to effectively "pause" the scanner so that it doesn't continually scan even after data has been retrieved.
if you are using expo, you will have npx. You can run any react-native command with npx. Hence:
npx react-native link react-native-camera

undefined is not an object (evaluating '_expo.Permission.askAsync')

i don't know what's the problem exactly but when i click on the button to choose image that erreur fire in the console
here's my code
_checkPermissions = async () => {
try {
const { status } = await Permission.askAsync(Permission.CAMERA);
this.setState({ camera: status });
const { statusRoll } = await Permission.askAsync(Permission.CAMERA_ROLL);
this.setState({ cameraRoll: statusRoll });
} catch (err) {
console.log(err);
}
};
findNewImage = async () => {
try {
this._checkPermissions();
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: "Images",
allowsEditing: true,
quality: 1
});
if (!result.cancelled) {
this.setState({
image: result.uri
});
} else {
console.log("cancel");
}
} catch (err) {
// console.log(err);
}
};
to me what solved it was importing the permissions and imagePicker like this:
import * as Permissions from 'expo-permissions';
import * as ImagePicker from 'expo-image-picker';
instead of this:
import Permissions from 'expo-permissions';
import ImagePicker from 'expo-image-picker';
And that's basically because there is no default export
It is getAsync(), not askAsync()
https://docs.expo.io/versions/latest/sdk/permissions/
I know I'm a little late to the party, but I feel it's important to show a way that is currently working (as of 2022) and also askAsync is deprecated ...
Getting image from (native) CAMERA
TL;DR: Even though we want "camera", we will actually use expo-image-picker FOR THE CAMERA (yes, you read right!)
I REPEAT: DO NOT USE expo-camera FOR CAMERA!
REMEMBER: USE ImagePickerExpo.requestCameraPermissionsAsync()AND ImagePickerExpo.launchCameraAsync() NOT Camera....!
So install it first: expo install expo-image-picker
Then import everything, from it under 1 alias, I like to use ImagePickerExpo because ImagePicker itself is confusing since it can mean more libraries, + import all needed for this code - you can replace Button with any other button/pressable that supports onPress (to use react-native-elements, you need to install it with yarn add react-native-elements)
Create displaying component
Create a state & setter to save current image source
Create a function that requests the permissions and opens the camera
Return the coponent with button binding onPress on function from 5. and Image that is displayed from the state from 4. but only when available.
working & tested(so far on android in expo go) code:
import React, { useState } from 'react';
import { View, Image, Alert, StyleSheet } from 'react-native';
import { Button } from 'react-native-elements';
import * as ImagePickerExpo from 'expo-image-picker';
const MyCameraComponent = () => {
const [selectedImage, setSelectedImage] = useState(null);
const openCameraWithPermission = async () => {
let permissionResult = await ImagePickerExpo.requestCameraPermissionsAsync();
if (permissionResult.granted === false) {
Alert.alert("For this to work app needs camera roll permissions...");
return;
}
let cameraResult = await ImagePickerExpo.launchCameraAsync({
// ...
});
console.log(cameraResult);
if (cameraResult.cancelled === true) {
return;
}
setSelectedImage({ localUri: cameraResult.uri });
};
return (
<View>
<Button title='Take a photo' onPress={openCameraWithPermission}></Button>
{(selectedImage !== null) && <Image
source={{ uri: selectedImage.localUri }}
style={styles.thumbnail}
/>}
</View>
);
}
const styles = StyleSheet.create({
thumbnail: {
width: 300,
height: 300,
resizeMode: "contain"
}
});
export default MyCameraComponent;
Note that I had to style the Image for it to display, it didn't display to me without proper styling which I find misleading, but I guess that's the react native way...
BTW: This also works in Android emulator (besides expo go in real Android device)
It also works on snack on desktop but only when you choose android (or Web) - https://snack.expo.dev/#jave.web/expo-camera-from-expo-image-picker
Getting image from (native) gallery (not camera)
In case you're wondering how to do the same for gallery, the code is basically the same, you just need a different callback function for the button that uses requestMediaLibraryPermissionsAsync / launchImageLibraryAsync instead of the camera ones.
let openImagePickerAsync = async () => {
let permissionResult = await ImagePickerExpo.requestMediaLibraryPermissionsAsync();
if (permissionResult.granted === false) {
Alert.alert("For this to work app needs media library/gallery permissions...");
return;
}
let pickerResult = await ImagePickerExpo.launchImageLibraryAsync({
presentationStyle: 0, // without this iOS was crashing
});
console.log(pickerResult);
if (pickerResult.cancelled === true) {
return;
}
setSelectedImage({ localUri: pickerResult.uri });
}

I got a warning and couldn't use FontAwesome in React Native on Expo

Now I am trying to use FontAwesome in React Native App on Expo.
I followed the flow about how to use custom font through Expo on Expo document but these icons couldn't work and I couldn't see any fonts.
Fortunately I don't have any error but warning.
This is my code below.
Please teach me.
Thank you.
import { Font } from 'expo';
import { fontAwesome } from '../../assets/fonts/fa-solid-900.ttf';
class Help extends React.Component {
state = {
fontLoaded: false,
};
async componentDidMount() {
await Font.loadAsync({
FontAwesome: fontAwesome,
});
this.setState({ fontLoaded: true });
}
renderHelpLists() {
return HelpLists.map((value, index) => {
return (
<TouchableOpacity
key={index}
style={styles.helpListsBox}
>
<Text style={styles.helpListText}>
{value.name}
</Text>
{
this.state.fontLoaded ? (
<Text style={styles.rightIcon}>
{'\f054'}
</Text>
) : null
}
</TouchableOpacity>
);
});
}
const styles=Stylesheet.create({
rightIcon: {
fontFamily: 'FontAwesome',
},
})
I'm not yet familiar with using Font Awesome by importing TTF files in React Native.
However, could you try using the Font Awesome React Native component?
See https://github.com/fortawesome/react-native-fontawesome
I solved this problem with import Icon from 'react-native-vector-icons/FonteAwesome'.
However I am not sure how to use Expo-Icons.