Camera is not running - android

I’m trying to make a prototype application that over and over
1- record a video with the camera for x seconds
2- displays this video
For this I use the components Camera from expo-camera and Video from expo-av
For this I have two views :
I use in my code the stateSequence property and the sequencer() function which displays alternately the view with the Camera component which films for x seconds , and the video view which allows me to display the video.
Sequencer() is triggered with setInterval( this.sequencer , 10000) found in the componentWillMount()
I can switch alternately from a View with the Camera component to a View with the Video component.
To record a video with the Camera component I use recordAsync(), but I get the following error:
Unhandled promise rejection: Error: Camera is not running
I’m using an android phone for my tests.
Can’t you help me
this is my code
import { StyleSheet, Text, View ,TouchableOpacity} from 'react-native';
import * as Permissions from 'expo-permissions';
import { Camera } from 'expo-camera';
import { Video } from 'expo-av';
import { Logs } from 'expo';
export default class SequenceViewer extends Component {
constructor(props) {
super(props);
this.state = {
stateSequence: "SHOOT ",
hasCameraPermission: null,
type: Camera.Constants.Type.front,
}
this.recordVideo = this.recordVideo.bind(this)
}
sequencer = () => {
if(this.state.stateSequence==="WATCH"){
this.setState({ stateSequence: "SHOOT",})
this.recordVideo(); // Error message Camera is not running
} else {
this.setState({stateSequence: "WATCH"})
}
}
async componentWillMount() {
let rollStatus = await Permissions.askAsync(Permissions.CAMERA_ROLL);
let cameraResponse = await Permissions.askAsync(Permissions.CAMERA)
if (rollStatus.status=='granted'){
if (cameraResponse.status == 'granted' ){
let audioResponse = await Permissions.askAsync(Permissions.AUDIO_RECORDING);
if (audioResponse.status == 'granted'){
this.setState({ permissionsGranted: true });
setInterval( this.sequencer , 10000);
}
}
}
}
recordVideo = async () => {
if(this.state.cameraIsRecording){
this.setState({cameraIsRecording:false})
this.camera.stopRecording();
}
else {
this.setState({cameraIsRecording:true})
if (this.camera) {
let record = await this.camera.recordAsync(quality='480p',maxDuration=5,mute=true).then( data =>{
this.setState( {recVideoUri :data.uri})
})
}
}
};
render() {
const { hasCameraPermission } = this.state
if(this.state.stateSequence=="WATCH")
{
return(
<View style={styles.container}>
<Video
source={{ uri:this.state.recVideoUri }}
rate={1.0}
volume={1.0}
isMuted={false}
resizeMode="cover"
shouldPlay
isLooping
style={{ width: 300, height: 300 }}
ref={(ref) => { this.player = ref }}
/>
</View>
)
} else
{
return(
<View style={{ flex: 1 }}>
<Camera style={{ flex: 1 }} type={this.state.type} ref={ref => {this.camera = ref; }}></Camera>
</View>
)
}
}
}
const styles = StyleSheet.create({
viewerText: {
fontSize: 20,
fontWeight: 'bold',
},
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Thank you

I had the same problem, my solution was by default camera type have to be "back" and you could change to "front" by:
componentDidMount = () => {
this.props.navigation.addListener('didFocus', async () => {
await setTimeout(() => {
this.setState({ cameraType: Camera.Constants.Type.front })
}, 100)
});
}

I was getting the "Camera is not running" error when i changed screens. So for functional components instead of withNavigationFocus(Camera) use this method:
import { useIsFocused } from '#react-navigation/native';
function MyComponent() {
const isFocused = useIsFocused()
return (
<View>
{ isFocused && <RNCamera /> }
</View>
)
}

Related

how to reject or answer an incoming call witihn react native app with custom buttons(can i use react-native-call-keep)

I am using react-native-call-detection package to save incoming call number (and send it on server later), I also want to reject/answer the incoming call based on the pressed button (based on server response later).
what package should I use to do it? I just found react-native-call-keep but all examples gave fake phone number to the functons and I don't know how to use its functions or how to get my call uuid.I just know there is reject/answer call function and I should call addEventListener functions before calling functions.
here is my current code:
import React, {useEffect, useState} from 'react';
import RNCallKeep from 'react-native-callkeep';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
TouchableHighlight,
PermissionsAndroid,
} from 'react-native';
import CallDetectorManager from 'react-native-call-detection';
import RNCallKeep from 'react-native-callkeep';
export default class MasterScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
featureOn: false,
incoming: false,
number: null,
};
}
componentDidMount() {
this.askPermission();
this.startListenerTapped();
this.setupCallKeep();
}
setupCallKeep() {
const options = {
android: {
alertTitle: 'Permissions Required',
alertDescription:
'This application needs to access your phone calling accounts to make calls',
cancelButton: 'Cancel',
okButton: 'ok',
imageName: 'ic_launcher',
additionalPermissions: [PermissionsAndroid.PERMISSIONS.READ_CONTACTS],
},
};
try {
RNCallKeep.setup(options);
RNCallKeep.setAvailable(true); // Only used for Android, see doc above.
} catch (err) {
console.error('initializeCallKeep error:', err.message);
}
}
askPermission = async () => {
try {
const permissions = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.READ_CALL_LOG,
PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE,
]);
console.log('Permissions are:', permissions);
} catch (err) {
console.warn(err);
}
};
startListenerTapped = () => {
this.setState({featureOn: true});
this.callDetector = new CallDetectorManager(
(event, phoneNumber) => {
console.log(event);
if (event === 'Disconnected') {
this.setState({incoming: false, number: null});
} else if (event === 'Incoming') {
this.setState({incoming: true, number: phoneNumber});
} else if (event === 'Offhook') {
this.setState({incoming: true, number: phoneNumber});
} else if (event === 'Missed') {
this.setState({incoming: false, number: null});
}
},
true,
() => {},
{
title: 'Phone State Permission',
message:
'This app needs access to your phone state in order to react and/or to adapt to incoming calls.',
},
);
};
stopListenerTapped = () => {
this.setState({featureOn: false});
this.callDetector && this.callDetector.dispose();
};
render() {
return (
<View style={styles.body}>
<Text>incoming call number: {this.state.number}</Text>
<TouchableOpacity
onPress={/*what to do */} style={{
width: 200,
height: 200,
justifyContent: 'center',
}}><Text>answer</Text></TouchableOpacity>
<TouchableOpacity
onPress={/*what to do */} style={{
width: 200,
height: 200,
justifyContent: 'center',
}}>
<Text>reject</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
body: {
backgroundColor: 'honeydew',
justifyContent: 'center',
alignItems: 'center',
flex: 1,
},
text: {
padding: 20,
fontSize: 20,
},
button: {},
});`
Use RNCallKeep.rejectCall. Like so
<TouchableOpacity
onPr ess={() => RNCallKeep.rejectCall(uuid)}
st yle={{
width: 200,
height: 200,
justifyContent: 'center',
}}
>
<Text>reject</Text>
</TouchableOpacity>

How to grant camera permission in react native expo app (android)

My code is :
import React, { useEffect } from "react";
import * as ImagePicker from "expo-image-picker";
import Screen from "./app/components/Screen";
export default function App() {
async function permisionFunction() {
const result = await ImagePicker.getCameraPermissionsAsync();
if (!result.granted) {
console.log(result);
alert("need access to gallery for this app to work");
}
}
useEffect(() => {
permisionFunction();
}, []);
return <Screen></Screen>;
}
I denied the permissions for camera when it was promted for the first time.
Now whenever I opens the app always need access to gallery for this app to work this message is shown up. for android.
I tried by giving all the permissions to the expo app in settings but still same msg appears.
How can I solve this.
Use expo-cameramodule to access device camera.
I have curated the working example of small app with which you can access pictures from gallery as well as device camera.
Working App: Expo Snack
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, Button, Image } from 'react-native';
import { Camera } from 'expo-camera';
import * as ImagePicker from 'expo-image-picker';
export default function Add({ navigation }) {
const [cameraPermission, setCameraPermission] = useState(null);
const [galleryPermission, setGalleryPermission] = useState(null);
const [camera, setCamera] = useState(null);
const [imageUri, setImageUri] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
const permisionFunction = async () => {
// here is how you can get the camera permission
const cameraPermission = await Camera.requestPermissionsAsync();
setCameraPermission(cameraPermission.status === 'granted');
const imagePermission = await ImagePicker.getMediaLibraryPermissionsAsync();
console.log(imagePermission.status);
setGalleryPermission(imagePermission.status === 'granted');
if (
imagePermission.status !== 'granted' &&
cameraPermission.status !== 'granted'
) {
alert('Permission for media access needed.');
}
};
useEffect(() => {
permisionFunction();
}, []);
const takePicture = async () => {
if (camera) {
const data = await camera.takePictureAsync(null);
console.log(data.uri);
setImageUri(data.uri);
}
};
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
});
console.log(result);
if (!result.cancelled) {
setImageUri(result.uri);
}
};
return (
<View style={styles.container}>
<View style={styles.cameraContainer}>
<Camera
ref={(ref) => setCamera(ref)}
style={styles.fixedRatio}
type={type}
ratio={'1:1'}
/>
</View>
<Button title={'Take Picture'} onPress={takePicture} />
<Button title={'Gallery'} onPress={pickImage} />
{imageUri && <Image source={{ uri: imageUri }} style={{ flex: 1 }} />}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
cameraContainer: {
flex: 1,
flexDirection: 'row',
},
fixedRatio: {
flex: 1,
aspectRatio: 1,
},
button: {
flex: 0.1,
padding: 10,
alignSelf: 'flex-end',
alignItems: 'center',
},
});
It's mention in doc Configuration.
In managed apps, Camera requires Permissions.CAMERA. Video recording requires Permissions.AUDIO_RECORDING.
I have the same problem... I'm using expo SDK 42 and after a denied answer the permissions request does not trigger again anymore.
Anyway, You have some mistakes in your code, you have to watch the status property of the permissions response.
this is how to check the response status
const requestPermissions = async () => {
try {
const {
status,
} = await ImagePicker.requestMediaLibraryPermissionsAsync();
console.log('status lib', status);
setHasPickerPermission(status === 'granted');
} catch (error) {
console.log('error', error);
}
try {
const { status } = await ImagePicker.requestCameraPermissionsAsync();
console.log('status camera', status);
setHasCameraPermission(status === 'granted');
} catch (error) {
console.log('error', error);
}
};
useEffect(() => {
requestPermissions();
}, []);
If the user has denied the camera permission the first time, the second time you request permission with requestCameraPermissionsAsync() the answer will always be "denied" unless the user manually changes the permission in the app settings.
import { Linking } from "react-native";
import { useCameraPermissions } from "expo-image-picker";
export default function App() {
const [status, requestPermissions] = useCameraPermissions();
const requestPermissionAgain = () => {
Linking.openSettings();
}
useEffect(() => {
if (!status?.granted) requestPermissions();
}, []);
}

React native Image uploading not uploading the images

I am developing an app That contain an image uploader. I found some code on internet that can upload image. And it worked partially. Which means When i press the choose image button, it opens gallery and i am able to select and crop image. And after cropping when i select ok nothing happen. It just show the image and its not uploading to the firebase cloud. Here is my code.
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Button,
Image,
ActivityIndicator,
TouchableOpacity
} from 'react-native';
import * as firebase from 'firebase';
import RNFetchBlob from 'react-native-fetch-blob';
import ImagePicker from 'react-native-image-crop-picker';
export default class RNF extends Component {
constructor (props) {
super(props);
this.state = {
loading: false,
dp: null
};
}
openPicker () {
this.setState({ loading: true });
const Blob = RNFetchBlob.polyfill.Blob;
const fs = RNFetchBlob.fs;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;
// const { uid } = this.state.user
const uid = '12345';
ImagePicker.openPicker({
width: 300,
height: 300,
cropping: true,
mediaType: 'photo'
}).then(image => {
const imagePath = image.path;
let uploadBlob = null;
const imageRef = firebase.storage().ref(uid).child('dp.jpg');
let mime = 'image/jpg';
fs.readFile(imagePath, 'base64')
.then((data) => {
// console.log(data);
return Blob.build(data, { type: `${mime};BASE64` });
})
.then((blob) => {
uploadBlob = blob;
return imageRef.put(blob, { contentType: mime });
})
.then(() => {
uploadBlob.close();
return imageRef.getDownloadURL();
})
.then((url) => {
let userData = {};
// userData[dpNo] = url
// firebase.database().ref('users').child(uid).update({ ...userData})
let obj = {};
obj['loading'] = false;
obj['dp'] = url;
this.setState(obj);
})
.catch((error) => {
console.log(error);
});
})
.catch((error) => {
console.log(error);
});
}
render () {
const dpr = this.state.dp ? (<TouchableOpacity onPress={ () => this.openPicker() }><Image
style={{ width: 100, height: 100, margin: 5 }}
source={{ uri: this.state.dp }}
/></TouchableOpacity>) : (<Button
onPress={ () => this.openPicker() }
title={ 'Change Picture' }
/>);
const dps = this.state.loading ? <ActivityIndicator animating={this.state.loading} /> : (<View style={styles.container}>
<View style={{ flexDirection: 'row' }}>
{ dpr }
</View>
</View>);
return (
<View style={styles.container}>
{ dps }
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5
}
});
AppRegistry.registerComponent('RNF', () => RNF);

Expo Camera recordAsync promise not resolving

Im starting to develop a mobile application with expo/react native, but I'm having some problems handling the camera object:
I have a camera object that I start recording (recordAsync) at componentDidMount and I stop it (stopRecording) at componentWillUnmount. however the promise is never resolved (neither the then, catch no finally are called)
am I doing something wrong?
here's the code:
import { Camera, Permissions } from 'expo';
import React from 'react';
export default class CameraReaction extends React.Component {
constructor(props){
super(props)
this.takeFilm = this.takeFilm.bind(this)
this.isFilming=false
this.cameraScreenContent = this.renderCamera()
}
componentDidMount(){
if (this.props.shouldrecording && !this.isFilming ){
this.takeFilm()
}
}
componentWillUnmount(){
this.camera.stopRecording()
}
saveMediaFile = async video => {
console.log("=======saveMediaFile=======");
}
renderCamera = () => {
let self = this
return (
<View style={{ flex: 1 }}>
<Camera
ref={ref => {self.camera=ref}}
style={styles.camera}
type='front'
whiteBalance='off'
ratio='4:3'
autoFocus='off'
>
</Camera>
</View>
);
}
takeFilm(){
let self = this
try{
self.camera.recordAsync()
.then(data => {
self.saveMediaFile(data),
self.isFilming=false
})
.catch(error => {console.log(error)})
this.isFilming = true
}
catch(e){
this.isFilming = false
}
};
render() {
return <View style={styles.container}>{this.cameraScreenContent}</View>;
}
}
anyone has any clue of what I'm doing wrong?
thanks in advance
I finally realised that we can't start recording directly when a component is rendered. An by 'directly' I mean without any further action from the user. If I do it in two steps (p.e. waiting for the user to click somewhere), if works perfectly. But I don't see any reference to this behaviour / limitation in the documentation.
The working code bellow:
import React from 'react';
import { StyleSheet, Text, View , TouchableOpacity} from 'react-native';
import { Camera, Permissions} from 'expo';
export default class App extends React.Component {
constructor(props){
super(props)
this.camera=undefined
this.state = {permissionsGranted:false,bcolor:'red'}
this.takeFilm = this.takeFilm.bind(this)
}
async componentWillMount() {
let cameraResponse = await Permissions.askAsync(Permissions.CAMERA)
if (cameraResponse.status == 'granted'){
let audioResponse = await Permissions.askAsync(Permissions.AUDIO_RECORDING);
if (audioResponse.status == 'granted'){
this.setState({ permissionsGranted: true });
}
}
}
takeFilm(){
let self = this;
if (this.camera){
this.camera.recordAsync().then(data => self.setState({bcolor:'green'}))
}
}
render() {
if (!this.state.permissionsGranted){
return <View><Text>Camera permissions not granted</Text></View>
} else {
return (
<View style={{flex: 1}}>
<View style={{ flex: 1 }}>
<Camera ref={ref => this.camera = ref} style={{flex: 0.3}} ></Camera>
</View>
<TouchableOpacity style={{backgroundColor:this.state.bcolor, flex:0.3}} onPress={() => {
if(this.state.cameraIsRecording){
this.setState({cameraIsRecording:false})
this.camera.stopRecording();
}
else{
this.setState({cameraIsRecording:true})
this.takeFilm();
}
}} />
</View>)
}
}
}

How to fetch random image from camera-roll using react native?

I have requirement where i need to get a random image every time when i click an button. I don't want picker to come up for the camera-roll with images, instead random image should selected from the camera folder and display in the image view.
I have followed the official FB tutorial of camera roll. Please find the code as below
_handleButtonPress = () => {
CameraRoll.getPhotos({
first: 20,
assetType: 'Photos',
})
.then(r => {
this.setState({ photos: r.edges });
})
.catch((err) => {
});
};
But this code will select the recently clicked images and display in the picker. Instead of to randomly select the uri of the image and display in the imageview. Any help is appreciated.
Regards,
Sharath
You essentially have the photos and all the necessary metadata once you set the state: this.setState({ photos: r.edges })
All you have to do is pick a random image from there. Here's how I did it:
import React, { Component } from 'react';
import {
StyleSheet,
View,
Image,
CameraRoll,
Button
} from 'react-native';
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
img: null
}
}
getRandomImage = () => {
const fetchParams = {
first: 25,
}
CameraRoll.getPhotos(fetchParams)
.then(data => {
const assets = data.edges
const images = assets.map((asset) => asset.node.image)
const random = Math.floor(Math.random() * images.length)
this.setState({
img: images[random]
})
})
.catch(err => console.log)
}
render() {
return (
<View style={styles.container}>
{ this.state.img ?
<Image
style={styles.image}
source={{ uri: this.state.img.uri }}
/>
: null
}
<Button title="Get Random Image from CameraRoll" onPress={this.getRandomImage}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
image: {
width: '100%',
height: '75%',
margin: 10,
}
});

Categories

Resources