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
Related
i am new in react-native and I want download multiple data in FlatList using URL with progress bar separate for its item download process ...in single file its process and progress working fine but when I try to download multiple file that time its not working.
download multyple files hangs full mobile screen and not able to use any other options from screen
how to do download from URL and display percentage in list
const DATA = [
{
id: '0',
file_title: 'zero Item',
download_file_url: 'http://212.183.159.230/50MB.zip',
},
{
id: '1',
file_title: 'First Item',
download_file_url: 'http://212.183.159.230/50MB.zip',
},]
<FlatList
data={DATA}
horizontal={false}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
const renderItem = ({item}) => (
<Item title={item.file_title} downloadUrl={item.download_file_url} />
);
const Item = ({title, downloadUrl}) => (
<View>
<DownloadItem title={title} downloadUrl={downloadUrl} />
</View>
);
i also declare seprate component for download
const DownloadItem = ({title, downloadUrl}) => {
const [downloadProgress, setDownloadProgress] = useState(0);
return (
<View>
<View style={style.parentView}>
<View
style={{
height: 55,
width: 55,
borderRadius: 2,
alignItems: 'center',
backgroundColor: rendomRGB(),
}}>
<Text style={style.extensionTxt}>
{getFirstCharacterOfExtensionFromURL(downloadUrl)}
</Text>
</View>
<View>
<Text style={style.fileTitle}>{title}</Text>
<Text style={style.fileDesc}>{title}</Text>
<View style={style.progressView}>
<Progress.Bar
style={style.fileDesc}
progress={downloadProgress}
width={200}
/>
<TouchableOpacity
onPress={() => startDownloadZip(title, downloadUrl)}>
<Image
style={style.imgCloseResume}
source={require('../../assets/close.png')}
/>
</TouchableOpacity>
</View>
</View>
</View>
<View style={style.deviderView}></View>
</View>
);
function startDownloadZip(title, downloadUrl) {
const appParentPath = RNFS.DocumentDirectoryPath;
const appFolderPath = appParentPath + '/MyFiles';
RNFS.mkdir(appFolderPath)
.then(success => {
console.log('Folder created!', success);
background: true,
RNFS.downloadFile({
fromUrl: `${downloadUrl}`,
toFile: `${appFolderPath + '/' + title}`,
progress: (res: DownloadProgressCallbackResult) => {
let progressPercent = res.bytesWritten / res.contentLength; // to calculate in percentage
setDownloadProgress(progressPercent);
},
})
.promise.then(responce => {
console.log('file download ', responce);
})
.catch(err => {
console.log('download error', err);
});
})
.catch(err => {
console.log('mkdir error ', err);
});
}
};
You can create a standalone component for your renderItem in which you can call the download progress. I attach an example below.
function ParentComp() {
return <FlatList renderItem={({item}) => <ChildComponent item={item} />} />
}
function ChildComponent({item}) {
const [progress, setProgress] = useState(0)
"here comes your RNFS logic"
return <ProgressBar value={progress} />
}
Good day,
I have had an issue recently whereby I have been running an SQL script in an app I have developed. The app uses a Transient database and has been working absolutely flawlessly for some time.
What I originally wanted to happen is that the app uses fetch process to perform a listing of a related servers contents and presents them into a Fragment (However I didn't get this far) . I was in the middle of the development of the code when the DB got a little strange.
Seemingly overnight I seem to have lost control of the database, for a reason that I cannot fathom, the database is automatically and repeatedly inserting hundreds off nulls into the db and I have no idea why. I have checked, double checked, triple checked the code and isolated code blocks that I think could be causing the problem to no avail. The only change I have made recently before the issue occurred is inserting a Fragment into the page.
The App uses an old Todo list to access the SQL server. I believe the open database code could be the problem and have moved it slightly to try and alleviate the issue
Here is my code
import React, { Fragment, useState } from 'react';
import { ScrollView, StyleSheet, Text, TextInput, Button,TouchableOpacity, View,Image, CheckBox, Alert } from 'react-native';
import Constants from 'expo-constants';
import * as SQLite from 'expo-sqlite';
import { enableProdMode } from '#angular/core';
import {fetch} from 'node-fetch';
let ref = React.createRef()
function performGetRequest(){
const db = SQLite.openDatabase('db.db')
const getPage= {
getServerPage :(
fetch('TEST SERVER CURRENTLY DOWN')
.then(res => res.text())
.then(json=> console.log(json)))
}
}
const db = SQLite.openDatabase('db.db')
const list = {
Page :(
<Fragment>
TEST
</Fragment>
)
}
function Items({ done: doneHeading, onPressItem }) {
const [items, setItems] = React.useState(null);
React.useEffect(() => {
db.transaction(tx => {
tx.executeSql(
`select * from items where done = ?;`,
[doneHeading ? 1 : 0],
(_, { rows: { _array } }) => setItems(_array)
);
});
}, []);
const heading = doneHeading ? "Completed" : "Todo";
return null;
return (
<View style={styles.sectionContainer}>
<Text style={styles.sectionHeading}>{heading}</Text>
{items.map(({ id, done, value }) => (
<TouchableOpacity
key={id}
onPress={() => onPressItem && onPressItem(id)}
style={{
backgroundColor: done ? "#000000" : "#fff",
borderColor: "#000",
borderWidth: 1,
padding: 8
}}
>
<Text style={{ color: done ? "#fff" : "#000" }}>{value}</Text>
</TouchableOpacity>
))}
</View>
);}
function App() {
const [text, setText] = React.useState(null)
const [forceUpdate, forceUpdateId] = useForceUpdate()
React.useEffect(() => {
db.transaction(tx => {
tx.executeSql(
"create table if not exists items (id integer primary key not null, done int, value text);"
);
});
}, []);
const add = (text) => {
// is text empty?
if (text === null || text === "") {
return false;
}
}
db.transaction(
tx => {
tx.executeSql("insert into items (done, value) values (0, ?)", []);
tx.executeSql("select * from items", [], (_, { rows }) =>
console.log(JSON.stringify(rows))
);
},
null,
forceUpdate
);
let ref = React.createRef();
const Home: React.FC = () => {
let cancelToken: any = axios.CancelToken;
let source = cancelToken.source();
useEffect(() => {
(async () => {
try {
const data = await axios.get("https://Kitchkar.pagekite.me/music", {
cancelToken: source.token
});
}catch (error) {
if (axios.isCancel(error)) {
console.log('Request canceled', error.message);
} else {
// handle error
console.log(error);
}
}
})();
return () => {
//when the component unmounts
console.log("component unmounted");
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
}
}, []); //End UseEffect
};
return (
<View style={styles.container}>
<Text style={styles.heading}>Page Listing</Text>
<View style={styles.flexRow}>
<TextInput
onChangeText={text => setText(text)}
onSubmitEditing={() => {
add(text);
setText(null);
}}
placeholder="what do you need to do?"
style={styles.input}
value={text}
/>
</View>
<View style={{ width: 200}}>
<Button
title="Enter!"
color="gold"
width="100"
height="100"
onpress={(performGetRequest)}/>
</View>
<Text style={styles.heading}>server contents</Text>
<Text style={styles.heading}>{getPage.getServerPage}</Text>
<Text style={styles.heading}></Text>
<Items
key={`forceupdate-todo-${forceUpdateId}`}
done={false}
onPressItem={id =>
db.transaction(
tx => {
tx.executeSql(`update items set done = 1 where id = ?;`, [
id
]);
},
null,
forceUpdate
)
}
/>
<ScrollView style={styles.container}>
<Image source={require('Substitute any image here')}/>
<View style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'flex-start',
}}>
<View style={{width: 200, height: 200, backgroundColor: 'yellow'}} />
<View style={{width: 200, height: 200, backgroundColor: 'orange'}} />
<View style={{width: 200, height: 200, backgroundColor: 'gold'}} />
</View>
<Text style={styles.heading}>Search History</Text>
<Items
done
key={`forceupdate-done-${forceUpdateId}`}
onPressItem={id =>
db.transaction(
tx => {
tx.executeSql(`delete from items where id = ?;`, [id]);
},
null,
forceUpdate
)
}
/>
<Text style={styles.heading}>Search History</Text>
</ScrollView>
</View>
);
}
function useForceUpdate() {
const [value, setValue] = useState(0);
return [() => setValue(value + 1), value];
}
db.transaction(
tx => {
tx.executeSql("select * from items", [], (_, { rows }) =>
tx.executeSql("insert into items (done, value) values (0, ?)", [console.log(JSON.stringify(rows))]));
}
);
const styles = StyleSheet.create({
container: {
color:"#FFD700",
},
button: {
width: "200",
height:"100",
},
heading: {
color: "#FFD700",
fontSize: 20,
fontWeight: "bold",
textAlign: "center"
},
flexRow: {
flexDirection: "row"
},
input: {
color:"#FFD700",
borderColor: "#FFD700",
borderRadius: 4,
borderWidth: 1,
flex: 1,
height: 48,
margin: 16,
padding: 8
},
})
export default App;
const db = SQLite.openDatabase('db.db') should be const db = SQLite.openDatabase("db.db");
I am new to react-native and I am trying to implement an image slider that displays images fetched from an API.
I have tried a couple of solutions to no avail.
Here is the code, it currently works for static images but I need a solution to display images from an API.
Here is the code
// Carousel.js
import * as React from "react";
import { StyleSheet, View, ScrollView, Dimensions, Image } from "react-native";
const DEVICE_WIDTH = Dimensions.get("window").width;
class Carousel extends React.Component {
scrollRef = React.createRef();
constructor(props) {
super(props);
this.state = {
selectedIndex: 0,
// images: null
};
this.scrollRef = React.createRef();
}
componentDidMount = () => {
setInterval(() => {
this.setState(
prev => ({
selectedIndex:
prev.selectedIndex === this.props.images.length - 1
? 0
: prev.selectedIndex + 1
}),
() => {
this.scrollRef.current.scrollTo({
animated: true,
x: DEVICE_WIDTH * this.state.selectedIndex,
y: 0
});
}
);
}, 3000);
};
componentWillUnmount(){
clearInterval()
}
setSelectedIndex = event => {
const contentOffset = event.nativeEvent.contentOffset;
const viewSize = event.nativeEvent.layoutMeasurement;
// Divide the horizontal offset by the width of the view to see which page is visible
const selectedIndex = Math.floor(contentOffset.x / viewSize.width);
this.setState({ selectedIndex });
};
render() {
const { images } = this.props;
const { selectedIndex } = this.state;
return (
<View style={{ height: "100%", width: "100%" }}>
<ScrollView
horizontal
pagingEnabled
onMomentumScrollEnd={this.setSelectedIndex}
ref={this.scrollRef}
>
{images.map(image => (
<Image
style={styles.backgroundImage}
source={{ uri: image }}
key={image}
/>
))}
</ScrollView>
<View style={styles.circleDiv}>
{images.map((image, i) => (
<View
style={[
styles.whiteCircle,
{ opacity: i === selectedIndex ? 0.5 : 1 }
]}
key={image}
active={i === selectedIndex}
/>
))}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
backgroundImage: {
height: "100%",
width: Dimensions.get("window").width
},
}
);
export { Carousel };
// App.js
import React, { useEffect, useState } from 'react'
import { Platform, StyleSheet, Text, View } from "react-native";
import { Carousel } from "./Carousel";
const images = [
"https://images.unsplash.com/photo-1508138221679-760a23a2285b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"https://images.unsplash.com/photo-1485550409059-9afb054cada4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=701&q=80",
"https://images.unsplash.com/photo-1519125323398-675f0ddb6308?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80",
"https://images.unsplash.com/photo-1429087969512-1e85aab2683d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80",
"https://images.unsplash.com/photo-1505678261036-a3fcc5e884ee?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80"
];
const App = () => {
// const APP_KEY = "*****";
// const [images, setImages] = useState([]);
// useEffect( () => {
// getData();
// }, []);
// const getData = async () => {
// const response = await fetch(`API URL*********&apiKey=${APP_KEY}`);
// const data = await response.json();
// setImages(data.articles.urlToImage);
// }
return (
<View style={styles.container}>
<Carousel images={images} />
</View>
);
}
export default App
In the App.js file, I commented out how I was trying to achieve this.
Please assist.
I am answering my own question. The issue was I was not correctly targeting the images from the API like so:
source={{ uri: image.urlToImage }}
This is the final code:
Carousel.js
const { images } = this.props;
const { selectedIndex } = this.state;
console.warn(images)
return (
<View style={{ height: "100%", width: "100%" }}>
<ScrollView
horizontal
pagingEnabled
onMomentumScrollEnd={this.setSelectedIndex}
ref={this.scrollRef}
>
{images.map(image => (
<Image
style={styles.backgroundImage}
source={{ uri: image.urlToImage }}
key={image}
/>
))}
</ScrollView>
<View style={styles.circleDiv}>
{images.map((image, i) => (
<View
style={[
styles.whiteCircle,
{ opacity: i === selectedIndex ? 0.5 : 1 }
]}
key={image}
active={i === selectedIndex}
/>
))}
</View>
</View>
);
}
App.js
import React, { useEffect, useState } from 'react'
import { Platform, StyleSheet, Text, View, Image } from "react-native";
import { Carousel } from "./Carousel";
const App = () => {
const APP_KEY = "********";
const [images, setImages] = useState([]);
useEffect( () => {
getData();
}, []);
const getData = async () => {
const response = await fetch(`API URL*******&apiKey=${APP_KEY}`);
const data = await response.json();
setImages(data);
}
return (
<View style={styles.container}>
<Carousel images={images}/>
</View>
);
}
export default App
var { height, width } = Dimensions.get("window");
const DEVICE_HEIGHT: height,
const DEVICE_WIDTH: width,
//Call the API and store the data in state let's say imageData and use that staet to render the images.
<ImageCarousel
ref={c => {
this._carousel = c;
}}
data={this.state.imageData} //This is the data of your API
parallaxFactor={2}
activeSlideAlignment="center"
renderItem={({ item, index }) =>
this._renderItem({ item, index, showDescLockedImage })
}
sliderWidth={CONST.DEVICE_WIDTH / 1}
sliderHeight={CONST.DEVICE_HEIGHT / 1.5}
activeAnimationType="spring"
itemHeight={CONST.DEVICE_HEIGHT / 1.5}
itemWidth={CONST.DEVICE_WIDTH / 1.8}
layout={"default"}
slideStyle={{
alignContent: "center",
justifyContent: "center",
elevation: 5
}}
onSnapToItem={this.changeIndex}
/>
I'm working on a news app, and this is the news details screens, it renders all the news details but i want to render the next news below this one when the end is reached. I can manage to get the new news details by using isCloseToBottom method and i can render the new news but the old one get replaced, but i don't want the old news to disappear. Is there any workaround for this?
class NewsDetails extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: false,
loaded: false,
article: {},
request_control:1
};
}
componentWillMount() {
const { params } = this.props.navigation.state;
console.log(params.id);
axios
.get(`${URL_NEWS_DETAILS}/${params.id}`)
.then(response =>
this.setState({
article: response.data,
loaded: true,
})
)
.catch(error => console.log(error));
}
_onRefresh=()=>{
this.setState({refreshing: true})
axios.get(`${URL_NEWS_DETAILS}/210971`) //test with constant id
.then(response =>
this.setState({
article: response.data,
loaded: true,
})
)
.catch(error => console.log(error));
this.setState({refreshing: false});
};
renderNext=()=>{
if(this.state.request_control===1) {
this.setState({request_control: 0});
axios.get(`${URL_NEWS_DETAILS}/210971`) //test with constant id
.then(response => {
this.setState({
request_control:1,
article: response.data,
loaded: true
})
},
)
.catch(error => {
this.setState({ loaded: true})
console.log(error)
})
}
};
render() {
if (this.state.loaded) {
return (
<View style={styles.container}>
<ScrollView showsVerticalScrollIndicator={false}
onScroll={({nativeEvent}) => {
if (isCloseToBottom(nativeEvent)) {
this.renderNext()
}
}}
scrollEventThrottle={400}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh.bind(this)}
/>
}>
<Text style={styles.title}>
{this.state.article.title.rendered.replace("–", "-")}
</Text>
<View
style={{ marginTop: 10, marginBottom: 10, flexDirection: 'row', alignItems: 'center' }}>
<Image
style={{ width: 18, height: 18 }}
source={require('../../img/icon.png')}
/>
<Text style={{ fontFamily: 'Open Sans Bold', fontSize: 14 }}>
{' '}
{this.state.article.author}
</Text>
<Text style={{ fontFamily: 'Open Sans Regular', fontSize: 13 }}>
{' '}
në{' '}
</Text>
{this.state.article.categories.map(category => {
return (
<Text
style={{
fontFamily: 'Open Sans Regular',
fontSize: 13,
color: '#F33A22',
}}>
{category.name},{' '}
</Text>
);
})}
</View>
<Lightbox underlayColor="white">
<Image
style={styles.image}
source={{ uri: this.state.article.featured_image_url }}
/>
</Lightbox>
<HTMLView
value={'<div>' + this.state.article.content.raw + '</div>'}
renderNode={Platform.OS === 'android' ? this.renderNode : null}
stylesheet={htmlStyles}
/>
{/*HERE I NEED TO RENDER A NEW NEWS BELOW THE MAIN ONE, */}
{/*TO CREATE AN EFFECT LIKE USED IN WEB THAT DISPLAYS NEWS AFTER NEWS*/}
</ScrollView>
</View>
);
} else return <Spinner />;
}
}
Your state article is replaced by the new one when you call renderNext, so the old one get replaced. To fix that, just change like
renderNext=()=>{
if(this.state.request_control===1) {
this.setState({request_control: 0});
axios.get(`${URL_NEWS_DETAILS}/210971`) //test with constant id
.then(response => {
this.setState({
request_control:1,
article: [...this.state.article, ...response.data],
loaded: true
})
},
)
.catch(error => {
this.setState({ loaded: true})
console.log(error)
})
}
};
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" />