React Native save an image to iOS camera roll - react-native

How can I save an image in react native's tag to iOS camera roll? has a uri source.
CameraRoll class has a method named saveImageWithTag but it's not clear how to use it. I think documentation is not good enough.

I have the same issue, and i check the react native CameraRoll API, it provide a static function
static saveImageWithTag(tag, successCallback, errorCallback)
Help you to save the image to the camera roll / gallery.
1.First, make sure your /node_modules/react-native/Libraries/CameraRoll/RCTCameraRoll.xcodeproj has been correctly linked to your current project.If not, you should do it first by following the official document here. (https://facebook.github.io/react-native/docs/linking-libraries-ios.html#content)
2.Second, get your image source well-prepared.For me, I put it in the project assets-library.
3.Coding like this.In this case, I save my image when componentDidMount execute.
(Here is my reference link: https://thebhwgroup.com/blog/accessing-iphone-camera-roll-images-react-native)
'use strict';
var React = require('react-native');
var {
CameraRoll,
View,
} = React;
var CameraRollTest = React.createClass({
componentDidMount() {
CameraRoll.saveImageWithTag('YOUR_IMAGE_TAG/URI', function(data) {
console.log(data);
}, function(err) {
console.log(err);
});
},
render: function() {
return (
<View>
</View>
);
}
});
module.exports = CameraRollTest;

Related

How to load local audio files dynamically with expo av

i have a bunch of audio files local to my app and i want to load them dynamically based on a component's state, the only way i found to load the audio with expo av is to use "require", but this method keeps returning "invalid call" whenever i try to use a variable of any sort or any template literals in the path string in it.
i tried even storing the paths in a json file and then referrirng to the path directly there and still got the invalid call error.
const { sound } = await Audio.Sound.createAsync(require(audioPaths['paths'][fileKey]), {}, playbackStatusUpdate);
how do you guys go about this issue? my files are local so i can't take advantage of streaming/loading them from network. does expo av offer any alternative to the require method? i need any tips or advice you might have
PS: if you need any more details about the situation please ask me and i will fill you in
Edit: this is how my paths json looks like
{
"paths": [
"../assets/Records/1.mp3",
"../assets/Records/2.mp3",
"../assets/Records/3.mp3",
"../assets/Records/4.mp3"
]
}
The issue is related to audio paths not being declared as System.registerDynamic.
you should define paths in JSON like this
"paths": [
require('./assets/one.mp3'),
require('./assets/two.mp3'),
require('./assets/three.mp3'),
]
}
and call this without require,
const { sound } = await Audio.Sound.createAsync(audioPaths['paths'][fileKey], {}, playbackStatusUpdate);
here is a snack I used
Theoretically when you want to upload files in a react native app, you will use either formData, or fileupload or react-native-fs or expo-file-system.
I recommend you the expo-file-system since you use expo.
See complete implementation here
But saying i have a bunch of audio files local to my app means that your audio files are already uploaded into a directory in your project folder and just you want those audio to be played dynamically using the expo-av Audio.Sound.createAsync() with require(). This is how I would do that:
import * as React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import { Audio } from 'expo-av';
export default function App() {
const [sound, setSound] = React.useState();
async function playSound() {
console.log('Loading Sound');
const { sound } = await Audio.Sound.createAsync( require('./assets/Hello.mp3')
);
setSound(sound);
console.log('Playing Sound');
await sound.playAsync();
}
React.useEffect(() => {
return sound
? () => {
console.log('Unloading Sound');
sound.unloadAsync();
}
: undefined;
}, [sound]);
return (
<View style={styles.container}>
<Button title="Play Sound" onPress={playSound} />
</View>
);
}
This sample is for playing one audio, but in your question you want the audio to be played dynamically. For that you can only use react-native useEffect hook to create a kind of repeatable actions. I would first create a method playSound like this:
playSound = async () => {
await Audio.Sound.createAsync( require('' + source);
};
Here source is the path to an audio sent as variable and you may want to use function goToNext() and resumePlayList() to change the path of source variable like:
const goToNext = () => {
for(let i = 0; i < noGuest; i++){
source = JsonPath[i];
}

how to perform deep linking on React Native Navigation

I have a request to implement deep linking in our React Native application whereby clicking a link will take them directly into the installed app. I am able to successfully direct them to the app. However, it must navigate to a certain page.
To address the problem, I use the code below. If there is a better approach to handle the problem, I would appreciate it if you could share it with me!
const useUrl = async () => {
const url = await Linking.getInitialURL();
if (url) {
Navigation.push(componentId, {
component: {
name: 'screen',
},
});
}
};
react-native and react-navigation both handle this as part of a feature set within the "Linking" that they offer. I can't find a way to handle that with React Native Navigation?
For me, I just add path to my stack navigator in react native like this
Product: {
screen: ProductScreen,
path: 'product/:productId'
},
and make sure your web that handle deep link have a similar path in routing. For example https://yourweb.com/product/:productId
And in your screen file, add this
useEffect(() => {
Linking.addEventListener('url', _handleDeepLink)
return () => {
Linking.removeEventListener('url', _handleDeepLink);
}
}
const _handleDeepLink = (event) => {
if (event) {
const route = event.url.replace(/.*?:\/\//g, '')
const id = route.match(/\/([^\/]+)\/?$/)[1];
if (id !== undefined) {
// do your code here if screen just opened via deep link
}
}
}

How do i get a user to open my react native app from a text message (basically i need to make share profile in my react native app)

## import ##
import {Share, Button } from 'react-native'
Function to share. This function need to have link to a page of this app which will be sent to another user, who can see the same page if the app is installed, and if it's not, then it must be redirected to play store.
const onShare = async () => {
try {
const result = await Share.share({
message:
'React Native | A framework for building native apps using React https://play.google.com/store/apps/details?id=com.test',
});
if (result.action === Share.sharedAction) {
if (result.activityType) {
// shared with activity type of result.activityType
} else {
// shared
}
} else if (result.action === Share.dismissedAction) {
// dismissed
}
} catch (error) {
alert(error.message);
}
};
button:
<Button onPress={onShare} title="Share" />
To add a feature to open the app from the link then we should have to implement the firebase dynamic-link library and use it in our app navigation to check whether we have received the link in our app then we have to set the initial route to open a specific screen otherwise fallback to play store link if app not installed the fallback will auto handled by the dynamic-link library.
checkout the doc.
https://rnfirebase.io/dynamic-links/usage

Is it possible to download an audio file and play it using React Native Expo?

I have audio files hosted on a server that I'd like my app to access after authenticating. Users send a GET request which includes an authentication token, and the server returns the binary audio data.
As far as I can see there is no way to save this 'blob' as an audio file to the filesystem. The current implementation of fetch in react-native doesn't support blobs: link
... and the ideally-suited react-native-fetch-blob library isn't supported in expo either: link
Additionally I can see no way of streaming the audio file from the server. The included audio library with expo allows streaming of audio from a url (e.g. http://example.com/myaudio.mp3) however I can't see any way to attach an authorisation header to the request (e.g. "Authorization": "Bearer [my-token]").
Is there a way of achieving this, either by downloading and saving the audio blob, or streaming from a url with an authorisation header included in the request? I could detach my project from Expo but I'd like to leave that as a last-resort.
Yes, it is. You need to use the Audio module exposed by expo to do it. Below are the steps that you have to follow to load and play an audio file from a given URL. I've also copied over the code for my component that is doing the same for me.
Load Audio module exposed by expo
import { Audio } from 'expo'
Create a new sound Object from it
soundObject = new Audio.Sound()
Asynchronously load your file
await this.soundObject.loadAsync({ uri: this.props.source })
Once loaded play the loaded file using
this.soundObject.playAsync()
Below is a simple component that I wrote for doing it -
import React, { Component } from 'react';
import { View, TouchableNativeFeedback } from 'react-native';
import { Audio } from 'expo';
class AudioPlayer extends Component {
constructor(props) {
super(props);
this.state = { isPlaying: false };
this.loadAudio = this.loadAudio.bind(this);
this.toggleAudioPlayback = this.toggleAudioPlayback.bind(this);
}
componentDidMount() {
this.loadAudio();
}
componentWillUnmount() {
this.soundObject.stopAsync();
}
async loadAudio() {
this.soundObject = new Audio.Sound();
try {
await this.soundObject.loadAsync({ uri: this.props.source /* url for your audio file */ });
} catch (e) {
console.log('ERROR Loading Audio', e);
}
}
toggleAudioPlayback() {
this.setState({
isPlaying: !this.state.isPlaying,
}, () => (this.state.isPlaying
? this.soundObject.playAsync()
: this.soundObject.stopAsync()));
}
render() {
return (
<TouchableNativeFeedback onPress={this.toggleAudioPlayback}>
<View style={this.props.style}>
{this.props.children}
</View>
</TouchableNativeFeedback>
);
}
}
export default AudioPlayer;
i figured it out. I should've load the sound in componentdidmount using async. In case someone met this problem
componentDidMount() {
this.loadAudio();
}
//async function to load the audio
async loadAudio() {
const { navigation } = this.props;
const id = navigation.getParam("id");
this.sound = new Audio.Sound();
for (let i = 0; i < soundArray.length; i++) {
if (soundArray[i].id === id) {
this.currentSound = soundArray[i];
console.log(this.currentSound);
break;
}
}
try {
await this.sound.loadAsync({
uri: this.currentSound.sound /* url for your audio file */
});
await this.sound.setOnPlaybackStatusUpdate(
this._updateScreenForSoundStatus
);
} catch (e) {
console.log("ERROR Loading Audio", e);
}
}

React native , open a url in webview

Im not familiar with ios app development , but is there a simple way to open a url in myApp's webview , in a simple way ?
Im looking for the same behaviour of facebook's app. once you click on http link , a webview is opened by the app.
clickHndlr: function() {
someNativeOrNonNativeModule.openUrl('http://google.com');
}
<Text onClick={this.clickHndlr}>google</Text>
Thanks.
Hi You can use WebView component in reactnative.
var {
....,
WebView,
} = React;
and in initial state give a default url or no url
getInitialState: function() {
return {
url: '', // or default url
yourInitialStates: 'value',
};
},
and then at inside render add component
<WebView ....your styles, properties
url={this.state.url}
/>
Now add your code
clickHndlr: function() {
this.setState({url:'http://google.com'});
}
This will give the result