Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'camera.takePictureAsync') React-Native expo-camera - react-native

I am trying to create a function that will access my device's camera, and will allow me to take a picture, but I get the above error. I modeled this similar to requesting access to the camera roll and it works fine, but I cannot get it to work for the camera.
What may be causing this? Below is some of my code:
import * as ImagePicker from 'expo-image-picker' //I am using expo
import {Camera} from 'expo-camera'
export default function Photo(){
// Image Picker function start
useEffect(() => {
(async ()=> {
if (Platform.OS != 'web'){
const ( status !== 'granted') {
if(status !== 'granted) {
alert('Camera roll required to upload photo from your library');
}
}
})();
},[]);
//Image Picker function end
const camera = useRef(null) //added this
const takePicture = async () => { // added this
useEffect(() => {
(async () => {
if (Platform.OS !== 'web'){
const { status1 } = await Camera.requestPermissionsAsync();
if (status1 !== 'granted'){
alert('Camera required to take a photo');
}
} //added this
},
})();
}, [])
}
<Camera //added this
ref = { camera }
onGoogleVisionBarcodesDetected = {({barcodes}) => {
console.log(barcodes)
}}
/> //added this
<View style = {[ styles.button, {justifyContent: 'center', borderRadius: 20, backgroundColor: '#fff', paddingTop: 10, width: width*0.5, alignItems: 'center' } ]}>
<TouchableOpacity
color='#fff'
onPress = { ()=> takePicture () }
>
<Text style = {[ styles.button, {}]}>Take Photo </Text>
</TouchableOpacity>
</View>

This might help
import React, { useRef } from 'react'
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'
import { RNCamera } from 'react-native-camera'
function PlayWithCamera() {
const camera = useRef(null);
const takePicture = async () => {
const result1 = await camera.takePictureAsync();
....
};
return (
<View style={styles.container}>
<RNCamera
ref={camera}
.....
onGoogleVisionBarcodesDetected={({ barcodes }) => {
console.log(barcodes)
}}
/>
<View ... >
<TouchableOpacity
onPress={() => takePicture() } // change here
>
......
</TouchableOpacity>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: 'black',
},
preview: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
},
capture: {
flex: 0,
backgroundColor: '#fff',
borderRadius: 5,
padding: 15,
paddingHorizontal: 20,
alignSelf: 'center',
margin: 20,
},
})
export default PlayWithCamera

Related

React Native: Camera from "expo-camera" stop running when face is not ever detected

I am newer for using react-native, and wanna try to create a camera with filter. I'm blocked in step to recognize face. Have success to draw rectangle when face detected, but the problem is once it goes out of detection. The camera stop running as it fixes on the last real-time capture
Here is my code:
import { useState, useEffect, useRef } from 'react'
import { Camera } from 'expo-camera'
import * as MediaLibrary from 'expo-media-library'
import { Text, StyleSheet, View, TouchableOpacity } from 'react-native'
import Button from './Button'
import { Ionicons } from '#expo/vector-icons'
import * as FaceDetector from 'expo-face-detector'
export default function PCamera() {
const cameraRef = useRef(undefined)
const [faceDetected, setFaceDetected] = useState([])
const [lastImage, setImage] = useState(undefined)
const [hasUsePermssion, setUsePermission] = useState(false)
const [type, switchToType] = useState(Camera.Constants.Type.front)
const takePicture = async () => {
if (cameraRef) {
try {
const options = {
quality: 1,
base64: true,
exif: false,
}
const data = await cameraRef.current.takePictureAsync(options)
setImage(data.uri)
console.log(data)
} catch (err) {
console.error(err)
}
}
}
const swithMode = () => {
switchToType(
type === Camera.Constants.Type.front
? Camera.Constants.Type.back
: Camera.Constants.Type.front
)
}
const handleFacesDetected = ({ faces }) => {
setFaceDetected(faces)
}
useEffect(() => {
;(async () => {
const { status } = await Camera.requestCameraPermissionsAsync()
if (status === 'granted') {
setUsePermission(true)
}
})()
}, [])
if (hasUsePermssion === null) {
return <View />
}
if (hasUsePermssion === false) {
return <Text>No access to camera</Text>
}
return (
<View style={styles.cameraContainer}>
<View style={styles.overlay}>
<Camera
ref={cameraRef}
style={styles.camera}
type={type}
onFacesDetected={handleFacesDetected}
faceDetectorSettings={{
mode: FaceDetector.FaceDetectorMode.fast,
detectLandmarks: FaceDetector.FaceDetectorLandmarks.all,
runClassifications:
FaceDetector.FaceDetectorClassifications.none,
minDetectionInterval: 100,
tracking: true,
}}
>
{faceDetected.length > 0 &&
faceDetected.map((face) => (
<View
key={face.faceID}
style={{
position: 'absolute',
borderWidth: 2,
borderColor: 'red',
left: face.bounds.origin.x,
top: face.bounds.origin.y,
width: face.bounds.size.width,
height: face.bounds.size.height,
}}
/>
))}
</Camera>
</View>
<View style={styles.optionsContainer}>
<View>
<TouchableOpacity onPress={swithMode}>
<Text>
<Ionicons
name="camera-reverse-outline"
size={24}
color="black"
/>
</Text>
</TouchableOpacity>
</View>
<Button
icon="camera"
title="Take Photo"
onPress={takePicture}
style={styles.button}
/>
<View>
<Text>...</Text>
</View>
</View>
</View>
)}
const styles = StyleSheet.create({
cameraContainer: {flex: 1,
},
overlay: {
flex: 6,
borderBottomStartRadius: 75,
borderBottomEndRadius: 75,
overflow: 'hidden',
},
camera: {
flex: 1,
},
optionsContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
},
})
N.B: Don't take care of the Button, it's a custom component and works well

expo ImageManipulator returning [TypeError: undefined is not an object (evaluating '_expo.ImageManipulator.manipulate')]

for some reason
const manipResult = await ImageManipulator.manipulate(
image,
[{ resize: { width: 640, height: 480 } }],
{ format: 'jpg' }
);
returns [TypeError: undefined is not an object (evaluating '_expo.ImageManipulator.manipulate')]
which is weird because it worked one time and then this started to be returned by react native whenever it runs this line of code. so basically what im trying to do is resize the image and then send it to an api but for some reason it won't work and keeps giving this error even though data.uri isn't undefined
whole code
import React, { useState, useEffect, useRef } from 'react';
import { Text, View, StyleSheet, TouchableOpacity, Image } from 'react-native';
import Constants from 'expo-constants';
import { Camera, CameraType } from 'expo-camera';
import * as MediaLibrary from 'expo-media-library';
import { MaterialIcons } from '#expo/vector-icons';
import Button from './src/components/Button';
import axios from 'axios'
import { Buffer } from "buffer";
import * as FS from "expo-file-system";
import { ImageManipulator } from 'expo';
export default function App() {
const [hasCameraPermission, setHasCameraPermission] = useState(null);
const [image, setImage] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
const [flash, setFlash] = useState(Camera.Constants.FlashMode.off);
const cameraRef = useRef(null);
useEffect(() => {
(async () => {
MediaLibrary.requestPermissionsAsync();
const cameraStatus = await Camera.requestCameraPermissionsAsync();
setHasCameraPermission(cameraStatus.status === 'granted');
})();
}, []);
const takePicture = async () => {
if (cameraRef) {
try {
const data = await cameraRef.current.takePictureAsync();
console.log(data);
const manipResult = await ImageManipulator.manipulate(
data.uri,
[{ resize: { width: 640, height: 480 } }],
{ format: 'jpg' }
);
setImage(manipResult0);
} catch (error) {
console.log(error);
}
}
};
uriToBase64 = async (uri) => {
let base64 = await FS.readAsStringAsync(uri, {
encoding: FS.EncodingType.Base64,
});
return base64;
};
toServer = async (mediaFile) => {
const url = "api url";
let response = await FS.uploadAsync(url, mediaFile.uri, {
headers: {
"content-type": "image/jpeg",
},
httpMethod: "POST",
uploadType: FS.FileSystemUploadType.BINARY_CONTENT,
});
console.log(response);
};
const savePicture = async () => {
if(image) {
try {
const asset= await MediaLibrary.createAssetAsync(image);
await toServer({
type:"image",
base64: uriToBase64(image),
uri: image,
});
setImage(null);
console.log('saved successfully');
} catch (error) {
console.log(error);
}
}
};
if (hasCameraPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={styles.container}>
{!image ? (
<Camera
style={styles.camera}
type={type}
ref={cameraRef}
flashMode={flash}
>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: 30,
}}
>
<Button
title=""
icon="retweet"
onPress={() => {
setType(
type === CameraType.back ? CameraType.front : CameraType.back
);
}}
/>
<Button
onPress={() =>
setFlash(
flash === Camera.Constants.FlashMode.off
? Camera.Constants.FlashMode.on
: Camera.Constants.FlashMode.off
)
}
icon="flash"
color={flash === Camera.Constants.FlashMode.off ? 'gray' : '#fff'}
/>
</View>
</Camera>
) : (
<Image source={{ uri: image }} style={styles.camera} />
)}
<View style={styles.controls}>
{image ? (
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: 50,
}}
>
<Button
title="Re-take"
onPress={() => setImage(null)}
icon="retweet"
/>
<Button title="Save" onPress={savePicture} icon="check" />
</View>
) : (
<Button title="Take a picture" onPress={takePicture} icon="camera" />
)}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#000',
padding: 8,
},
controls: {
flex: 0.5,
},
button: {
height: 40,
borderRadius: 6,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
text: {
fontWeight: 'bold',
fontSize: 16,
color: '#E9730F',
marginLeft: 10,
},
camera: {
flex: 5,
borderRadius: 20,
},
topControls: {
flex: 1,
},
});

Trying to send image to heroku api but keep getting error 400

I'm trying to make an app that takes a picture and then returns the list of objects detected on that image. the code below is the whole code i'm using. i've changed the url of the api to 'insert api url here' just incase some troll find this post and spams the api with requests but i've made sure that the api url i'm using the correct one as i've tested it on postman and just copy pasted the api url.
import React, { useState, useEffect, useRef } from "react";
import { Text, View, StyleSheet, TouchableOpacity, Image } from "react-native";
import Constants from "expo-constants";
import { Camera, CameraType } from "expo-camera";
import * as MediaLibrary from "expo-media-library";
import { MaterialIcons } from "#expo/vector-icons";
import Button from "./src/components/Button";
import axios from "axios";
export default function App() {
const [hasCameraPermission, setHasCameraPermission] = useState(null);
const [image, setImage] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
const [flash, setFlash] = useState(Camera.Constants.FlashMode.off);
const cameraRef = useRef(null);
useEffect(() => {
(async () => {
MediaLibrary.requestPermissionsAsync();
const cameraStatus = await Camera.requestCameraPermissionsAsync();
setHasCameraPermission(cameraStatus.status === "granted");
})();
}, []);
const takePicture = async () => {
if (cameraRef) {
try {
const data = await cameraRef.current.takePictureAsync();
console.log(data);
setImage(data.uri);
} catch (error) {
console.log(error);
}
}
};
const savePicture = async () => {
if (image) {
try {
const asset = await MediaLibrary.createAssetAsync(image);
axios
.post("insert api url here", {
Imagee: image,
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
alert("done");
setImage(null);
console.log("saved successfully");
} catch (error) {
console.log(error);
}
}
};
if (hasCameraPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={styles.container}>
{!image ? (
<Camera
style={styles.camera}
type={type}
ref={cameraRef}
flashMode={flash}
>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
paddingHorizontal: 30,
}}
>
<Button
title=""
icon="retweet"
onPress={() => {
setType(
type === CameraType.back ? CameraType.front : CameraType.back
);
}}
/>
<Button
onPress={() =>
setFlash(
flash === Camera.Constants.FlashMode.off
? Camera.Constants.FlashMode.on
: Camera.Constants.FlashMode.off
)
}
icon="flash"
color={flash === Camera.Constants.FlashMode.off ? "gray" : "#fff"}
/>
</View>
</Camera>
) : (
<Image source={{ uri: image }} style={styles.camera} />
)}
<View style={styles.controls}>
{image ? (
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
paddingHorizontal: 50,
}}
>
<Button
title="Re-take"
onPress={() => setImage(null)}
icon="retweet"
/>
<Button
type="submit"
title="Save"
onPress={savePicture}
icon="check"
/>
</View>
) : (
<Button title="Take a picture" onPress={takePicture} icon="camera" />
)}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
paddingTop: Constants.statusBarHeight,
backgroundColor: "#000",
padding: 8,
},
controls: {
flex: 0.5,
},
button: {
height: 40,
borderRadius: 6,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
},
text: {
fontWeight: "bold",
fontSize: 16,
color: "#E9730F",
marginLeft: 10,
},
camera: {
flex: 5,
borderRadius: 20,
},
topControls: {
flex: 1,
},
});
The part where it makes a post request the code snippet below.
so what i'm trying to do is store the uri of the image using state and then sending that uri
to the api using axios. i've made sure that the api is working on postman before testing it on my react native code but somehow i keep getting
[AxiosError: Request failed with status code 400]
I searched online as to what error 400 means and it says that it is an error caused by an invalid request which i find weird as the url is correct and i've done what every blog post or documentation axios has on post request has shown me.
const savePicture = async () => {
if (image) {
try {
const asset = await MediaLibrary.createAssetAsync(image);
axios
.post("insert api url here", {
Imagee: image,
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
alert("done");
setImage(null);
console.log("saved successfully");
} catch (error) {
console.log(error);
}
}
};

How to get all the pdf files available in internal storage of android in react native

I am using react-native-fs for reading files in device's external storage. I want to get all pdf books stored in an android device and list them in the screen. Searched in google, read docs in react-native-fs but not succeed getting all pdf books. please help if something wrong with my code.
What I'm doing wrong?
Here is my code.
import React, { useState, useEffect } from 'react';
import {
Alert,
StyleSheet,
Text,
View,
Dimensions,
ImageBackground,
ScrollView,
PermissionsAndroid,
ActivityIndicator,
} from 'react-native';
import RNFS from 'react-native-fs';
import BookOffline from '../components/BookOffline';
const MyBooks = ({ navigation }) => {
// collecting data from device
const [books, setBooks] = useState([])
const [bookList, setBookList] = useState([]);
useEffect(() => {
getPermission();
}, []);
const getPermission = async () => {
try {
PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE
).then(granted => {
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
readStorage();
} else {
//If permission denied then show alert
Alert.alert('Not Granted storage_permission');
navigation.goBack();
}
});
} catch (err) {
//To handle permission related issue
console.log('error', err);
}
};
const readStorage = async () => {
let list2 = [];
await RNFS.readDir(RNFS.ExternalStorageDirectoryPath) // On Android, use "RNFS.DocumentDirectoryPath" (MainBundlePath is not defined)
.then(result => {
result.forEach((item, index) => {
// console.log(index, item)
if (item.name.endsWith('.pdf')) {
setBooks([...books, item])
}
else if (item.isDirectory()) {
RNFS.readDir(item.path)
.then(result => {
list2 = result.filter((item) => item.name.endsWith('.pdf'))
setBooks([...books, ...list2])
}).catch((error) => {
console.log(error)
})
}
});
setBookList(books)
console.log("bookList", bookList)
})
.catch(error => {
console.log(error);
});
};
return bookList.length == 0 ? (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Loading...</Text>
<ActivityIndicator size="large" />
</View>
) : (
<View style={{ justifyContent: 'center', alignItems: 'center' }}>
<ImageBackground
source={require('../assets/images/tech-dark-design.jpg')}
resizeMode="cover"
style={{ width: '100%' }}>
<ScrollView style={styles.images}>
{bookList.map((item, index) => {
return <BookOffline data={item} key={index} />;
})}
</ScrollView>
</ImageBackground>
</View>
);
};
export default MyBooks;
const styles = StyleSheet.create({
container: {
height: Dimensions.get('window').height - 110,
// padding: 5,
},
list: {
width: '100%',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.2,
shadowRadius: 1.41,
elevation: 2,
marginBottom: 1,
},
});

How to find the size of recorded video file in expo?

I am working with the expo. I'm using an expo-camera to record video. I'm getting the URI of the video. But I want to calculate the size of the video before I upload it (over 5MB will be banned). I can only get the URI of the video. So, how to get the size of the video? I have also done googling but didn't find any relevant answer.
Component File
import React, { Component } from "react";
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp,
} from "react-native-responsive-screen";
import { Camera } from "expo-camera";
export default class Recordvideo extends React.Component {
// Local State
state = {
video: null,
picture: null,
recording: false,
hasPermission: null,
setHasPermission: "",
};
// Getting camera permission
componentDidMount = async () => {
const { status } = await Camera.requestPermissionsAsync();
if (status === "granted") {
this.setState({ hasPermission: true });
}
};
// Getting Video URI After Recording Completed
_saveVideo = async () => {
const { video } = this.state;
console.log(video);
this.props.navigation.push("Post", {
VIDEOURL: video.uri,
VIDEOID: 1,
mod: true,
});
};
// Stop Recording Function
_StopRecord = async () => {
this.setState({ recording: false }, () => {
this.cam.stopRecording();
});
};
// Start Recording Function
_StartRecord = async () => {
if (this.cam) {
this.setState({ recording: true }, async () => {
const video = await this.cam.recordAsync();
this.setState({ video });
});
}
};
// Toogle function for start/stop recording
toogleRecord = () => {
const { recording } = this.state;
if (recording) {
this._StopRecord();
} else {
this._StartRecord();
}
};
// Render function
render() {
const { recording, video } = this.state;
if (this.state.hasPermission === null) {
return <View />;
}
if (this.state.hasPermission === false) {
return (
<View
style={{ flex: 1, alignItems: "center", justifyContent: "center" }}
>
<Text>No access to camera</Text>
</View>
);
}
// return statement
return (
<View style={styles.responsiveBox}>
<Camera
ref={(cam) => (this.cam = cam)}
style={{
justifyContent: "flex-end",
alignItems: "center",
flex: 1,
width: "100%",
}}
>
// on Completing Video button, firing _saveVideo Function
{video && (
<TouchableOpacity
onPress={this._saveVideo}
style={{
padding: 20,
width: "100%",
backgroundColor: "#fff",
}}
>
<Text style={{ textAlign: "center" }}>Complete</Text>
</TouchableOpacity>
)}
// on Toggle VideoRecording for start/stop video recording button, firing _toogleRecord Function
<TouchableOpacity
onPress={this.toogleRecord}
style={{
padding: 20,
width: "100%",
backgroundColor: recording ? "#ef4f84" : "#4fef97",
}}
>
<Text style={{ textAlign: "center" }}>
{recording ? "Stop" : "Record"}
</Text>
</TouchableOpacity>
</Camera>
</View>
);
}
}
// Styles
const styles = StyleSheet.create({
responsiveBox: {
width: wp("100%"),
height: hp("100%"),
alignItems: "center",
justifyContent: "center",
},
});
if you are using expo , you can try FileSystem
import * as FileSystem from 'expo-file-system';
getFileSize = async fileUri => {
let fileInfo = await FileSystem.getInfoAsync(fileUri);
return fileInfo.size;
};
else install react-native-fs and use the stat method (to get the file size)
getFileSize = async fileUri => {
let fileInfo = await stat(fileUri);
return fileInfo.size;
};