This should be included in the react-native APIs but I cannot seem to find any API included out of the box.
I want to open up the camera on the click of a button. I can see some APIs just for iOS but react-native should make things cross-platform.
Does anyone know how to access the camera (not the gallery) using react-native?
You might like to use react-native-camera module for this.
Here's an example usage of the library:
'use strict';
import React, { Component } from 'react';
import {
AppRegistry,
Dimensions,
StyleSheet,
Text,
TouchableHighlight,
View
} from 'react-native';
import Camera from 'react-native-camera';
class BadInstagramCloneApp extends Component {
render() {
return (
<View style={styles.container}>
<Camera
ref={(cam) => {
this.camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}>
<Text style={styles.capture} onPress={this.takePicture.bind(this)}>[CAPTURE]</Text>
</Camera>
</View>
);
}
takePicture() {
const options = {};
//options.location = ...
this.camera.capture({metadata: options})
.then((data) => console.log(data))
.catch(err => console.error(err));
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
},
preview: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center'
},
capture: {
flex: 0,
backgroundColor: '#fff',
borderRadius: 5,
color: '#000',
padding: 10,
margin: 40
}
});
AppRegistry.registerComponent('BadInstagramCloneApp', () => BadInstagramCloneApp);
Currently react-native-camera is deprecated and if you want to achieve native performance and reach feature support good choice is https://github.com/mrousavy/react-native-vision-camera
Features:
Photo, Video and Snapshot capture
Customizable devices and multi-cameras (smoothly zoom out to "fish-eye" camera)
Customizable FPS
Frame Processors (JS worklets to run QR-Code scanning, facial recognition, AI object detection, realtime video chats, ...)
Smooth zooming (Reanimated)
Fast pause and resume
HDR & Night modes
Example:
function App() {
const devices = useCameraDevices('wide-angle-camera')
const device = devices.back
if (device == null) return <LoadingView />
return (
<Camera
style={StyleSheet.absoluteFill}
device={device}
isActive={true}
/>
)
}
Documentation:
https://mrousavy.com/react-native-vision-camera/docs/guides
In React Native you can access the camera by first installing it using NPM:
npm install react-native-camera --save
react-native link react-native-camera
Then use this in your Component:
takePicture() {
const options = {};
//options.location = ...
this.camera.capture({metadata: options})
.then((data) => console.log(data))
.catch(err => console.error(err));
}
See this github repo for full example:
https://github.com/lwansbrough/react-native-camera
I found react-native-picker image picker handier for my needs, it can be useable for both camera and gallery. for the bellow example you need to install version: "react-native-image-picker": "^3.3.2",
https://www.npmjs.com/package/react-native-image-picker
import React, {useState, useEffect} from 'react';
import {StyleSheet, Text, View, Image} from 'react-native';
import cameraImage from '../../../../assets/icons/camera.png';
import galleryImage from '../../../../assets/icons//gallery.png';
import {TouchableWithoutFeedback} from 'react-native-gesture-handler';
import * as ImagePicker from 'react-native-image-picker';
import {PermissionsAndroid} from 'react-native';
const ImagePicker = () => {
const [responseCamera, setResponseCamera] = React.useState(null);
const [responseGallery, setResponseGallery] = React.useState(null);
const openCameraWithPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
{
title: 'App Camera Permission',
message: 'App needs access to your camera ',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
ImagePicker.launchCamera(
{
mediaType: 'photo',
includeBase64: false,
maxHeight: 200,
maxWidth: 200,
},
(response) => {
console.log(response);
setResponseCamera(response);
setResponseGallery(null);
},
);
} else {
console.log('Camera permission denied');
}
} catch (err) {
console.warn(err);
}
};
return (
<View
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-around',
margin: 4,
}}>
<TouchableOpacity onPress={() => openCameraWithPermission()}>
{responseCamera === null ? (
<Image style={styles.icon} source={cameraImage} />
) : (
<Image style={styles.icon} source={{uri: responseCamera.uri}} />
)}
</TouchableOpacity>
<TouchableOpacity
onPress={() =>
ImagePicker.launchImageLibrary(
{
mediaType: 'photo',
includeBase64: false,
maxHeight: 200,
maxWidth: 200,
},
(response) => {
setResponseGallery(response);
setResponseCamera(null);
},
)
}>
{responseGallery === null ? (
<Image style={styles.icon} source={galleryImage} />
) : (
<Image style={styles.icon} source={{uri: responseGallery.uri}} />
)}
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
icon: {
height: 50,
width: 50,
},
});
export default ImagePicker;
permissions for android:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera" />
Related
I am new to react-native. I would like to open the camera on Pressable onPress event. Can anyone please give me the example of react-native-vision-camera. I have read the document. but really I don't know how to use the component. I have tried find-out the example, but no clue.
because I want to customize the video camera. for example, I want to show 1234 while recording. that's why I will go with react-native-vision-camera. I tried that package. but I couldn't able to open the camera. I am not sure what I am wrong and the documentation is also not clear for me. So I asked for help here. Can anyone please help ?
Upload.js
import React, {
useState,
useEffect,
useRef
} from 'react';
import { Provider as PaperProvider } from 'react-native-paper';
import { Avatar, Button, Card, Title, Chip, Paragraph } from 'react-native-paper';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
useColorScheme,
View,
Image,
ImageBackground,
Pressable,
Dimensions,
PermissionsAndroid,
Platform,
TouchableOpacity
} from 'react-native';
import { Container } from 'native-base';
import Header from '../../Components/Header'
import colors from '../../Themes/Colors';
import Routes from '../../Navigation/Routes';
import useTranslation from '../../i18n';
import { IconX, ICON_TYPE } from '../../Icons';
import { ButtonX } from '../../Components';
import HeaderDoc from '../../Components/HeaderDoc';
import {
launchCamera,
launchImageLibrary
} from 'react-native-image-picker';
import { useStoreActions, useStoreState } from 'easy-peasy';
import { org_id } from '../../Config';
import { Camera, useCameraDevices } from 'react-native-vision-camera';
import ImagePicker from 'react-native-image-crop-picker';
import ApplicantDetails from './ApplicationDetails';
import { CameraComponent } from './CameraComponent';
const UploadDoc = ({ navigation, route }) => {
const { t } = useTranslation();
const isDarkMode = useColorScheme() === 'dark';
const tagList = ['a', 'b', 'c', 'D', 'E', 'F'];
const [fileData, setfileData] = useState('');
const [fileUri, setfileUri] = useState('');
const camera = useRef(null);
useEffect(() => {
(async () => {
const status = await Camera.requestCameraPermission();
setHasPermission(status === 'authorized');
})();
}, []);
return (
<SafeAreaView style={{ flex: 1, backgroundColor: colors.white }}>
<HeaderDoc title={'Upload Documents'} page={'1'} navigation={navigation} />
<View style={{ flex: 1, flexDirection: 'column' }}>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={{ marginBottom: 130, backgroundColor: colors.white }}>
<View style={{ marginHorizontal: 20, marginTop: 10, marginBottom: 50 }}>
<Pressable
style={{width: 100, height: 30, backgroundColor: colors.primary, justifyContent: 'center',alignSelf: 'center',alignItems: 'center'}}
onPress={()=> CameraComponent()}>
<Text style={{color: colors.white}}>Take Photo</Text>
</Pressable>
</View>
</ScrollView>
</View>
</SafeAreaView>
);
};
export default UploadDoc;
CameraComponent.js
import React, {
useState,
useEffect,
useRef
} from 'react';
import {
StyleSheet,
TouchableOpacity,
} from 'react-native';
import {Camera, useCameraDevices} from 'react-native-vision-camera';
export const CameraComponent = () => {
console.log("asmasas")
useEffect(() => {
(async () => {
const newCameraPermission = await Camera.requestCameraPermission()
const newMicrophonePermission = await Camera.requestMicrophonePermission()
})();
},[])
const devices = useCameraDevices()
const device = devices.back
if (device == null) return null;
return (
<Camera
style={StyleSheet.absoluteFill}
device={device}
isActive={true}
photo={true}
/>
)
}
First of all i assume youre using bare react native and not expo
Next then first you have to install the package via npm i or yarn install .
Then ill tell you for android
<uses-permission android:name="android.permission.CAMERA" />
<!-- optionally, if you want to record audio: -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
You have to add these in AndroidManifest.xml
Next get permission status by using
next then in your comp
App.js
export const App = () => {
useEffect(() => {
const newCameraPermission = await Camera.requestCameraPermission()
const newMicrophonePermission = await Camera.requestMicrophonePermission()
},[])
const devices = useCameraDevices()
const device = devices.back
if (device == null) return <LoadingView />
return (
<Camera
style={StyleSheet.absoluteFill}
device={device}
isActive={true}
/>
)
}
Hop it helps
I am fairly new to react native, but I have some experience. I am creating my own app for both ios and android by following along a tutorial that I had already completed and making my own modifications. As I was in the middle of creating an app, I forgot to add a background image. After struggling with this for several days, I'm desperate, so I decided to ask my question on here.
I am trying to add the background image to my App.js file. The image loads properly, but my page content ( which is inside <LifelineNavigator />) is either hidden or has disappeared for android. And for ios, the content seems to be in a small centered flexbox. Also, I am trying to remove the white background.
Any suggestions would definitely help. Thanks so much! God bless!
Here is my code:
import React, { useState } from "react";
import { StyleSheet, View, ImageBackground } from "react-native";
import * as Font from "expo-font";
import AppLoading from "expo-app-loading";
import { enableScreens } from "react-native-screens";
import LifelineNavigator from "./src/navigation/LifelineNavigator";
enableScreens();
const fetchFonts = () => {
return Font.loadAsync({
"Gotham-Medium": require("./src/assets/fonts/Gotham-Font/Gotham-Medium.otf")
const image = {
uri: "https://i.ibb.co/8z6QbTS/Lifeline-Gradient-Background-24.png",
};
const App = () => {
const [fontLoaded, setFontLoaded] = useState(false);
if (!fontLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={() => setFontLoaded(true)}
onError={(err) => console.log(err)}
/>
);
}
return (
<View >
<ImageBackground source={image} style={styles.image}>
<View style={ styles.container }>
<LifelineNavigator />
</View>
</ImageBackground>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
// backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
image: {
width: "100%",
height: "100%" ,
}
});
export default App;
IOS Screenshot
Android Screenshot
import React from "react";
import { ImageBackground, StyleSheet, Text, View } from "react-native";
const image = { uri: "https://reactjs.org/logo-og.png" };
const App = () => (
<View style={styles.container}>
<ImageBackground source={image} resizeMode="cover" style={styles.image}>
<Text style={styles.text}>Inside</Text>
</ImageBackground>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
flex: 1,
justifyContent: "center"
},
text: {
color: "white",
fontSize: 42,
lineHeight: 84,
fontWeight: "bold",
textAlign: "center",
backgroundColor: "#000000c0"
}
});
export default App;
follow this documentation > https://reactnative.dev/docs/imagebackground
it may solve your problem
I'm try to develop a little app for android. One of the functions is to display photos from device. I got the array with photos, but I can't display them. I can see that after fetching photos appears a scroll like there is something on the screen, but I can't see it.
import React, {useEffect, useState} from 'react';
import {
View,
Text,
Image,
FlatList,
PermissionsAndroid,
Platform,
} from 'react-native';
import CameraRoll from '#react-native-community/cameraroll';
const Upload = () => {
const [photos, setPhotos] = useState('');
const getPhotos = () => {
CameraRoll.getPhotos({
first: 500,
assetType: 'Photos',
groupName: 'Camera'
})
.then((res) => {
setPhotos(res.edges);
})
.catch((error) => {
console.log(error);
});
};
useEffect(
() => {console.log('photos', photos)}, [photos]
);
const askPermission = async () => {
if (Platform.OS === 'android') {
const result = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
{
title: 'Permission Explanation',
message: 'ReactNativeForYou would like to access your photos!',
},
);
if (result !== 'granted') {
console.log('Access to pictures was denied');
return;
} else {
getPhotos();
}
} else {
getPhotos();
}
};
useEffect(() => {
askPermission();
}, []);
return(
<View>
<FlatList
data={photos}
numColumns={3}
keyExtractor={(item, index) => index.toString()}
renderItem={({item}) => (
<Image
style={{
width: 30,
height: 30,
}}
source={{uri: item.node.image.uri}}
/>
)}
/>
</View>
)
};
export default Upload;
For test I tryed to some code in return and got next results:
{photos.length !== 0 ? <Image style={{width: 100, height: 100}} source={{uri: 'file:///storage/emulated/0/DCIM/Camera/IMG_20210417_011652.jpg'}} /> : null}
This displays nothing.
{photos.length !== 0 ? <Image style={{width: 100, height: 100}} source={{uri: photos[1].node.image.uri}} /> : null}
This too displays nothing.
{photos.length !== 0 ? <Image style={{width: 100, height: 100}} source={{uri: 'https://miro.medium.com/max/700/1*mk1-6aYaf_Bes1E3Imhc0A.jpeg'}} /> : null}
And this works fine.
Anyone knows how to fix it?
The reason of my problem, as I understood, was in andoid versions. I fixed issue by adding "android:requestLegacyExternalStorage="true"" in AndroidManifest.xml
I'm using an expo-camera for video recording in my react native app. Everything is working great in development but when I generate an APK file so the camera is not recording the video.
I have used the useRef hook is my code which triggers when the start recording button is clicked and fires the startRecord() function which uses
const recordedVideo = await cameraRef.current.recordAsync();.
What i think that maybe cameraRef.current.recordAsync() is not working in the production.
Any Suggestions or solution would be very helpful.
Thanks!
**Video Recording Component**
import React, { useState, useEffect, useRef } from "react";
import { View, Text, TouchableOpacity, StyleSheet, Alert } from "react-native";
// packages
import { Camera } from "expo-camera";
import * as FileSystem from "expo-file-system";
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp,
} from "react-native-responsive-screen";
// Functional Component
const Recordvideo = (props) => {
// Ref
const cameraRef = useRef(null);
// States
const [video, setVideo] = useState(null);
const [recording, setRecording] = useState(false);
const [hasPermission, setHasPermission] = useState(null);
// getting camera permission
useEffect(() => {
getPermission();
}, [getPermission]);
const getPermission = async () => {
const { status } = await Camera.requestPermissionsAsync();
if (status === "granted") {
setHasPermission(true);
}
};
// start/stop video recording
const toogleRecord = () => {
if (recording) {
stopRecord();
} else {
startRecord();
}
};
// start recording
const startRecord = async () => {
if (cameraRef.current) {
setRecording(true);
const recordedVideo = await cameraRef.current.recordAsync();
setVideo(recordedVideo);
}
};
// stop recording
const stopRecord = async () => {
setRecording(false);
cameraRef.current.stopRecording();
};
// saving recorded video
const saveVideo = async () => {
let fileInfo = await FileSystem.getInfoAsync(video.uri);
if (fileInfo.size <= 5242880) {
props.navigation.push("Post", {
VIDEOURL: video.uri,
VIDEOID: 1,
});
} else {
Alert.alert("Video too large please upload a shorter video");
props.navigation.goBack();
}
};
// checking camera permission
if (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={cameraRef}
style={{
justifyContent: "flex-end",
alignItems: "center",
flex: 1,
width: "100%",
}}
>
{video && (
<TouchableOpacity
onPress={saveVideo}
style={{
padding: 20,
width: "100%",
backgroundColor: "#fff",
}}
>
<Text style={{ textAlign: "center", color: "#000" }}>Complete</Text>
</TouchableOpacity>
)}
<TouchableOpacity
onPress={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",
},
});
export default Recordvideo;
Instead of taking useRef take it as state for example:
const [cameraRef , SetCameraRef] = useState()
And call ref inside Camera component like <Camera ref = {setCameraRef(ref)} ..../>
I have this screen in react native
import React, { Component } from 'react';
import { AppRegistry,TouchableOpacity, Text ,Button,Image,TextInput,PropTypes,StyleSheet,View,NavigatorIOS,TouchableHighlight} from 'react-native';
class LoginView extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.title}>
HYGEX
</Text>
<View>
<TextInput
placeholder="Username"
style={styles.formInput}
/>
<TextInput
placeholder="Password"
secureTextEntry={true}
style={styles.formInput1}
/>
<TouchableHighlight style={styles.button}
onPress={() => this.move()}>
<Text style={styles.buttonText}>Login</Text>
</TouchableHighlight>
</View>
</View>
);
}
move() {
//what i can do here to go to Socrce screen ???
}
}
Something like login screen, now when I click into TouchableHighlight
I need to open this screen
'use strict';
import React, { Component } from 'react';
import { AppRegistry, ListView, Text, View } from 'react-native';
class HygexListView extends Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
'John', 'Joel', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin'
])
};
}
render() {
return (
<View style={{flex: 1, paddingTop: 22}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>
</View>
);
}
}
module.exports = HygexListView;
I tried to implement move method but I failed! Any idea why?
Does react-native have a method to change the screen when click into TouchableHighlight?
As others pointed out, you have to use an instance of Navigator to transition between screens. Maybe you can have a look at the example apps in the React Native repo. I also find this router package quite easy to set up, and it also includes an example app that you can use as a starting point.
Edit
As a simple example using react-native-router-flux, you can edit the Example.js file in the Example directory to look like this:
import React, {
Component,
} from 'react';
import {
StyleSheet,
Text,
View,
} from 'react-native';
import LoginView from './LoginView';
import HygexListView from './HygexListView';
import {
Scene,
Router,
Actions,
} from 'react-native-router-flux';
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: 'transparent', justifyContent: 'center',
alignItems: 'center',
},
tabBarStyle: {
backgroundColor: '#eee',
},
tabBarSelectedItemStyle: {
backgroundColor: '#ddd',
},
});
// define this based on the styles/dimensions you use
const getSceneStyle = (/* NavigationSceneRendererProps */ props, computedProps) => {
const style = {
flex: 1,
backgroundColor: '#fff',
shadowColor: null,
shadowOffset: null,
shadowOpacity: null,
shadowRadius: null,
};
if (computedProps.isActive) {
style.marginTop = computedProps.hideNavBar ? 0 : 64;
style.marginBottom = computedProps.hideTabBar ? 0 : 50;
}
return style;
};
class Example extends Component {
render() {
return (
<Router getSceneStyle={getSceneStyle}>
<Scene key="login" component={LoginView} initial={true}/>
<Scene key="hygex" component={HygexListView } />
</Router>
);
}
}
export default Example;
Then, in your component's move function, you have to do the following:
move(){
Actions.hygex(); // This will perform a slide transition, but you can customize it. Have a look at the docs for that.
I have not tested the code, so there might be some typos/missing imports/code, but it should give you an idea of what you have to do.
}
You have to implement a Navigator, which is roughly a component that manages all stuff related to screens, and header bar with back button and etc.
As you are a beginner, I suggest you to look at the docs on this link:
https://facebook.github.io/react-native/docs/navigator.html
Sorry for the short answer, I'm on my phone.
Good luck!
"use strict";
var React = require("react-native");
var {
Component,
StyleSheet,
Text,
TextInput,
TouchableHighlight,
View,
} = React;
var SecureView = require("./SecureView");
class LoginView extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: ""
};
}
render() {
return (
<View style={styles.container}>
<Text style={styles.title}>
Sign In
</Text>
<View>
<TextInput
placeholder="Username"
onChange={(event) => this.setState({username: event.nativeEvent.text})}
style={styles.formInput}
value={this.state.username} />
<TextInput
placeholder="Password"
secureTextEntry={true}
onChange={(event) => this.setState({password: event.nativeEvent.text})}
style={styles.formInput}
value={this.state.password} />
<TouchableHighlight onPress={(this.onSubmitPressed.bind(this))} style={styles.button}>
<Text style={styles.buttonText}>Submit</Text>
</TouchableHighlight>
</View>
</View>
);
}
onSubmitPressed() {
this.props.navigator.push({
title: "Secure Page",
component: SecureView,
passProps: {username: this.state.username, password: this.state.password},
});
}
};
var styles = StyleSheet.create({
container: {
padding: 30,
marginTop: 65,
alignItems: "stretch"
},
title: {
fontSize: 18,
marginBottom: 10
},
formInput: {
height: 36,
padding: 10,
marginRight: 5,
marginBottom: 5,
marginTop: 5,
flex: 1,
fontSize: 18,
borderWidth: 1,
borderColor: "#555555",
borderRadius: 8,
color: "#555555"
},
button: {
height: 36,
flex: 1,
backgroundColor: "#555555",
borderColor: "#555555",
borderWidth: 1,
borderRadius: 8,
marginTop: 10,
justifyContent: "center"
},
buttonText: {
fontSize: 18,
color: "#ffffff",
alignSelf: "center"
},
});
module.exports = LoginView;
You have to use navigator. please read the documentation as mentioned below. and if you will need then i will share you my code.
Here is an example: NavigatorExample