Displaying video in React-Native - react-native

I am trying to display a video in react-native. But having some issues. 'till now this what I did: I install react-native-video. and also linked it.
And this is the codes:
import React, {Component} from 'react';
import {
AppRegistry,
Platform,
StyleSheet,
Text,
View,
ScrollView,
TouchableOpacity,
Button,
Alert} from 'react-native';
import Video from 'react-native-video';
export default class App extends Component<Props> {
Open() {
}
render() {
return (
<View style={styles.container}>
<Text>
Open the video
</Text>
<Button
onPress={this.Open}
title="Press Me"
/>
<Video
source={{ uri:"https://www.youtube.com/watch?v=HIB8RBhPkBA"}}
resizeMode={"cover"}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor : 'white',
alignItems: 'center',
justifyContent: 'center'
},
});
There is no error in the emulator. But also there is no video too. Is there anything that I did wrong about setup?

unfortunately, react-native-video will not work since the source uri is a link to the youtube page. unless you can procure the video as an asset and append its extension to its url (...video.mp4), it should work. see this.
for a quick fix, you can use the webview component to embed the link.

For displaying youtube videos, you can use this package instead
react-native-youtube
API
import YouTube from 'react-native-youtube'
<YouTube
videoId="KVZ-P-ZI6W4" // The YouTube video ID
play={true} // control playback of video with true/false
fullscreen={true} // control whether the video should play in fullscreen or inline
loop={true} // control whether the video should loop when ended
onReady={e => this.setState({ isReady: true })}
onChangeState={e => this.setState({ status: e.state })}
onChangeQuality={e => this.setState({ quality: e.quality })}
onError={e => this.setState({ error: e.error })}
style={{ alignSelf: 'stretch', height: 300 }}
/>
For getting the youtube id from the url, you can use
var video_id = window.location.search.split('v=')[1];
var ampersandPosition = video_id.indexOf('&');
if(ampersandPosition != -1) {
video_id = video_id.substring(0, ampersandPosition);
}

Related

White blank screen when load website WebView React Native

i have a problem when i want to send data of a URL so when you go to the next page your show the spesific url, im using expo cli not react native cli
website.tsx
import React, { useState } from "react";
import { Dimensions } from "react-native";
import { Div, Text } from "react-native-magnus";
import WebView from "react-native-webview";
const Website = ({YOUR_URL}) => {
return (
<WebView
rautomaticallyAdjustContentInsets={false}
source={{uri: YOUR_URL}}
style={{marginTop: 20, height: "100%", width: "100%"}}
onLoad={console.log("Loaded")}
startInLoadingState={true}
javaScriptEnabled={true}
/>
);
};
export default Website;
and this is my button to send the data
<Button w={wp(40)} h={hp(5.5)} ml={hp(2)}
onPress={() => navigation.navigate('Website', {YOUR_URL:data?.external_link})}
// onPress={() => Linking.openURL(data?.external_link)}
>
<Text allowFontScaling={false} fontSize={16} color="#fff">
Selengkapnya
</Text>
if you can help me, thank you very much
For me it worked by passing it precise values for width and height for Webview component and not percentage values. For managing the different display sizes I think you should use "scale".

What is the best way to indicate loading while a video is loading on Expo React Native app?

I wanted to ask what would be the best way to handle loading for videos on Expo / React Native.
Expo has good documentation on the Video and AV components to handle video / audio:
https://docs.expo.io/versions/latest/sdk/video/
https://docs.expo.io/versions/latest/sdk/av/
I've tried two things so far: '
Using posterSource in a Video component. The problem here is that the poster image doesn't format properly.
This is what my Video component looks like:
const videoStyle = { width: '100%', height: '100%', display: display};
return (
<Video
ref={playbackObject}
source={{uri: source}}
posterSource={require('path/to/file')}
rate={1.0}
volume={1.0}
isMuted={isMuted}
resizeMode="cover"
usePoster={true}
shouldPlay={shouldPlay}
onPlaybackStatusUpdate={_onPlaybackStatusUpdate}
progressUpdateIntervalMillis={50}
isLooping
style={videoStyle}
posterStyle={videoStyle}
>
</Video>
)
I’ve also tried using playbackStatus to see if the video is loaded or buffering and have an activity indicator when the video is loaded or buffering, but because I use states, there is some lag.
My implementation for (2) looks like this:
const [loaded, setLoaded] = useState(false);
const _onPlaybackStatusUpdate = playbackStatus => {
if(playbackStatus.isBuffering){
if(loaded){
setLoaded(false);
}
} else {
if(!loaded){
setLoaded(true);
}
}
}
If loaded = true, we do not show an activity indicator. Else, we do show an activity indicator. The main problem here is there is a lag, which is not great UI.
So with that in mind, what would be people’s recommendation of handling loading for videos? Thanks!!
What you can do is to render an <ActivityIndicator /> as background and when it finishes loading the asset, it will get behind the video (or you could just check if the asset was loaded or not -> optionally rendering it inside <Video />.
<Video
ref={handleVideoRef}
>
<ActivityIndicator size="large" />
</Video>
const handleVideoRef = async component => {
const playbackObject = component;
if (playbackObject) {
await playbackObject.loadAsync(
{ uri: currentVideoURI },
);
}
};
here's my solution for that :
Video component has onLoadStart and onReadyForDisplay props, which indicate when the loading starts and when it's finished.
So we could create a custom component, which would support loading indicator using the Video component imported from expo. So in the end, this would looksomething like this :
import React, {useState} from "react";
import { ActivityIndicator } from "react-native";
import { Video } from "expo-av";
const AppVideo = ({style, ...rest}) => {
return (
<View style={style}>
{isPreloading &&
<ActivityIndicator
animating
color={"gray"}
size="large"
style={{ flex: 1, position:"absolute", top:"50%", left:"45%" }}
/>
}
<Video
{...rest}
onLoadStart={() => setIsPreloading(true)}
useNativeControls
onReadyForDisplay={() => setIsPreloading(false)}
resizeMode="contain"
isLooping
/>
</View>
);
}
export default AppVideo;

React native access front camera

I am using "react-native camera" library to access the camera. So here is my code
.
import React, { Component } from "react";
import {
AppRegistry,
Dimensions,
StyleSheet,
Text,
TouchableHighlight,
View
} from "react-native";
import Camera from "react-native-camera";
import { RNCamera, FaceDetector } from "react-native-camera";
export default class App extends Component<Props> {
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)}>
take photo
</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
}
});
Here i am able to access the back camera and whenever i am clicking on take photo, it capture image and show that instantly. But i need two changes here.
Using this code, the back camera is getting accessed but i want to access the front camera.
Also, the image i captured, should not be shown instantly. I want a button , and whenever i click on that button, it navigates to different page and show all the images there.
Is it possible in react native ?? If yes, then please suggest me the changes that i require to make in this code
To answer your second question specifically, you have two options.
A) After taken the photo, store it as base64 uri into your state or redux, then whenever you need it, display the base64 uri as a image.
B) Utilize the package react-native-fs to access file system, storing the taken photo in iOS as cache, and retrieving it whenever needed.
Based on personal experience dealing with it, I would recommend option A
To switch your camera to back camera to front camera there exists a prop in Camera component called mirrorMode, if it is true it will show the front camera, otherwise, it will be the default mode that is back camera:
<Camera
...
mirrorImage={this.state.mirrorMode}
>
You can create a state and a button that change the state to switch between that 2 cameras.

How to change uri value of Video component dynamically

I am working with react native, and I am using a video component from the expo. during this how I can change the value for URI attribute dynamically
(As you mentioned in the comment that you already solved the problem and want to play youtube videos)
You can use WebView to play Youtube video.
Working demo: https://snack.expo.io/Syhzx-VvX
Here is the sample code:
import React, { Component } from 'react';
import { StyleSheet, View, WebView, Platform } from 'react-native';
export default class App extends Component<{}> {
render() {
return (
<View style={{ height: 300 }}>
<WebView
style={ styles.WebViewContainer }
javaScriptEnabled={true}
domStorageEnabled={true}
source={{uri: 'https://www.youtube.com/embed/YE7VzlLtp-4' }}
/>
</View>
);
}
}
const styles = StyleSheet.create({
WebViewContainer: {
marginTop: (Platform.OS == 'android') ? 20 : 0,
}
});
Otherwise if you don't want to use WebView, use a third party package like react-native-youtube

React Native Camera Roll

Haven't noticed much sample code/guides on how to use the CameraRoll library from React Native, I found the example in the docs a bit "vague" and confusing.
First time I'm using any of the API's so I do not fully understand how I'm suppose to use the library either. So far I've imported it like:
import {
AppRegistry,
Image,
StyleSheet,
TextInput,
Navigator,
CameraRoll,
Alert,
TouchableHighlight,
Button,
Text,
View
} from 'react-native';
quite confused with "Linking" etc, but as far as I know, this should be all I need to do in order to use the lib.
And how do I use it for something as simple as to open the gallery on the click of a button and let the user choose an image that should then be displayed in the app.
Thanks in advance, hope someone has some code to clarify this.
Here is some sample code that will grab the first 25 photos from your camera roll and display them in a ScrollView. I modified this from an example I found online here
import React, { Component, PropTypes } from 'react'
import {
CameraRoll,
Image,
ScrollView,
StyleSheet,
TouchableHighlight,
View,
} from 'react-native';
class CameraRollView extends Component {
constructor(props) {
super(props)
var controls = props.controls
this.state = {
images: [],
selected: '',
fetchParams: { first: 25 },
groupTypes: 'SavedPhotos',
}
this._storeImages = this._storeImages.bind(this)
this._logImageError = this._logImageError.bind(this)
this._selectImage = this._selectImage.bind(this)
}
componentDidMount() {
// get photos from camera roll
CameraRoll.getPhotos(this.state.fetchParams, this._storeImages, this._logImageError);
}
// callback which processes received images from camera roll and stores them in an array
_storeImages(data) {
const assets = data.edges;
const images = assets.map( asset => asset.node.image );
this.setState({
images: images,
});
}
_logImageError(err) {
console.log(err);
}
_selectImage(uri) {
// define whatever you want to happen when an image is selected here
this.setState({
selected: uri,
});
console.log('Selected image: ', uri);
}
render() {
return (
<View style={{flex: 1, backgroundColor: 'white'}}>
<ScrollView style={styles.container}>
<View style={styles.imageGrid}>
{ this.state.images.map(image => {
return (
<TouchableHighlight onPress={() => this._selectImage(image.uri)}>
<Image style={styles.image} source={{ uri: image.uri }} />
</TouchableHighlight>
);
})}
</View>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
imageGrid: {
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center'
},
image: {
width: 100,
height: 100,
margin: 10,
},
});
export default CameraRollView
Hmm, the package you are seeking is probably react-native-image-picker. It allows you to take a photo or select one from your native device gallery.
LINK: https://github.com/react-community/react-native-image-picker
In response to the linking issue. When you save a package using:
npm install --save react-native-image-picker
What is happening here is the --save part prepares the packages dependencies to be connected to native iOS and Android. This linking is done using the command react-native link.
In some cases packages require some manual linking aswell (for example, this package requires a small amount of native iOS and Android configuration)