Playing sound on cards - react-native

I have application with cards on stack (a lot of cards - about 500)
I card component I added:
function getVoice() {
try {
const mySound = new Sound(getSoundName(id), Sound.MAIN_BUNDLE,
(error) => {
if (error) {
Alert.alert('Error:', error.message)
return;
}
})
if (mySound != null) {
mySound.play((success, error) => {
if (success) {
Alert.alert('success')
} else {
Alert.alert('err')
}
mySound.release()
})
}
}
catch{
}
};
An alert is triggered here err
What is wrong?
I tried another option.
I called new Sound() at the beginning of component loading
Here the sound was playing but works on up to 8 cards. Later there is the same mistake as now

It works fine:
const getVoice = () => {
try {
const sound = new Sound(getSoundName(id), null, (error) => {
if (error) {
return;
}
sound.play();
});
}
catch{
}
};

Related

Create VIdeocall room with multiple users using WebRtc and firebase

i am trying to create a room video call something like Whatsapp with firebase as signalisation server for two users it works perfect as expected but when a third user join everything stop working
if the user A the first who join and the user B the second until the user C join everything work fine but when C join user A freeze and lost user B connection and B share screen with C but also sometimes freezing
here is my code
onst joinRoom = async () => {
const roomRef = await firestore().collection('meets').doc(params.callId);
roomRef
.collection('users')
.add({name, type: 'join'})
.then(() => {
roomRef
.collection('users')
.get()
.then(async querySnapshot => {
if (querySnapshot.empty) {
console.log('EMPTY');
} else {
querySnapshot.forEach(async snap => {
if (snap.data().name !== name && snap.data().type === 'join') {
// data.push(snap.data().name);
await creatOffer(snap.data().name);
}
// if (data.length > 0) {
// Promise.all(data).then(async user => {
// return await creatOffer(user);
// });
// }
});
}
});
});
// // listen on any new offers
roomRef.collection('offers').onSnapshot(data => {
data.docChanges().forEach(async change => {
if (change.type === 'added') {
// console.log('changes', change.doc.data());
if (change.doc.data().to === name) {
await createAnswer(change.doc.data().from, change.doc.data().offer);
}
}
});
});
//listen to answers
roomRef.collection('answers').onSnapshot(async snapshot => {
snapshot.docChanges().forEach(async change => {
if (change.type === 'added') {
const pc = pcPeers[change.doc.data().from];
if (change.doc.data().to === name) {
const rtcSessionDescription = new RTCSessionDescription(
change.doc.data().answer,
);
if (pc && rtcSessionDescription) {
await pc.setRemoteDescription(rtcSessionDescription);
}
}
}
});
});
//listen to candidate change
roomRef.collection('candidates').onSnapshot(async snapshot => {
snapshot.docChanges().forEach(async change => {
// console.log('answers', change.doc.data());
if (change.type === 'added') {
console.log('added', Platform.OS);
if (change.doc.data().to === name) {
const pc = pcPeers[change.doc.data().from];
// console.log(pc);
if (pc) {
await pc.addIceCandidate(
new RTCIceCandidate(change.doc.data().candidate),
);
}
}
}
});
});
};
and function to create offer
const creatOffer = async to => {
try {
const {roomRef, localPC} = await initializePeer(to);
const offer = await localPC.createOffer();
// console.log('offer', offer);
if (offer) {
await localPC.setLocalDescription(offer);
await roomRef.collection('offers').add({from: name, to, offer});
}
pcPeers = {...pcPeers, [to]: localPC};
} catch (e) {
console.log(e);
}
};
function to create answer
const createAnswer = async (from, offer) => {
try {
const {localPC, roomRef} = await initializePeer(from);
await localPC.setRemoteDescription(new RTCSessionDescription(offer));
const answer = await localPC.createAnswer();
await localPC.setLocalDescription(answer);
// await checkIfAnswerAlreadyCreated(from, name);
await roomRef.collection('answers').add({from: name, to: from, answer});
pcPeers = {...pcPeers, [from]: localPC};
} catch (e) {
console.log(e);
}
};
and here is how i initialise a peer
setLocalStream(initialStream);
const roomRef = await firestore().collection('meets').doc(params.callId);
const collection = roomRef.collection('candidates');
localPC.onicecandidate = async e => {
if (!e.candidate) {
return;
}
// console.log('canditates', Platform.OS);
const state = localPC.iceGatheringState;
if (state !== 'complete') {
await collection.add({
from: name,
candidate: e.candidate.toJSON(),
to,
date: new Date(),
});
} else {
Alert.alert('tes');
}
// InCallManager.setForceSpeakerphoneOn(true);
// InCallManager.setSpeakerphoneOn(true);
};
localPC.onsignalingstatechange = async event => {
// when the signal state become stable record the data and stop ringback
if (event.target.signalingState === 'stable') {
if (Platform.OS === 'ios') {
localStream?.getVideoTracks().forEach(track => {
//For ios to trigger the camera on
track._switchCamera();
track._switchCamera();
});
}
}
};
localPC.onaddstream = e => {
if (e?.stream) {
// console.log(
// `RemotePC received the stream call ${Platform.OS}_${Platform.Version}`,
// e?.stream,
// );
console.log(Platform.OS, ' ', Platform.Version);
if (remoteStream === null) {
// Alert.alert('stream 1');
setRemoteStream(e?.stream);
} else {
// Alert.alert('stream 2');
setRemoteStream_(e?.stream);
}
}
};
return {localPC, roomRef};
};
can anyone help me with some hints where is tthe problem i’ve created for my self here and thank you

react native image uri and async storage

i'm trying to save a profile picture and i save it with asyncStorage. store part working perfectly but if i close app and reopen it doesn`t show image.
i logging image uri and there is uri but cant solve the problem.
here is my code
this is image pick part
const ImagePick = async () => {
const options = {
title: 'Seçim yapınız.',
cancelButtonTitle: 'İptal',
takePhotoButtonTitle: 'Bir fotoğraf çek',
chooseFromLibraryButtonTitle: 'Galeriden seç',
chooseWhichLibraryTitle: 'Galeriden seç',
mediaType: 'photo',
storageOptions: {skipBackup: true, path: 'images'},
};
let isCameraPermitted = await requestCameraPermission();
let isStoragePermitted = await requestExternalWritePermission();
if (isCameraPermitted && isStoragePermitted) {
ImagePicker.showImagePicker(options, async response => {
//console.log('response', response);
if (response.didCancel) {
console.log('Kullanıcı fotoğraf seçimini iptal etti');
} else if (response.customButton) {
console.log('Özel butona tıklandı.');
} else if (response.error) {
console.log('error', 'Bir hata oluştu.');
} else {
console.log(response.fileName);
let uri = response.uri;
let path = response.uri;
if (Platform.OS === 'ios') {
path = '~' + path.substring(path.indexOf('/Documents'));
}
if (!response.fileName) {
response.fileName = path.split('/').pop();
}
let name = response.fileName;
let type = `image/${name.split('.').slice(-1)[0]}`;
console.log('uri', uri);
console.log('name', name);
console.log('type', type);
setImageUri(response.uri);
try {
await AsyncStorage.setItem('profilePicture', response.uri);
console.log('async storage kayıt başarılı');
} catch (error) {
console.log(error);
}
}
});
}
};
i get image like this
useEffect(() => {
getProfilePicture();
}, []);
const getProfilePicture = async () => {
const profilePicture = await AsyncStorage.getItem('profilePicture');
console.log('profilePicture', profilePicture);
if (profilePicture !== null) {
setImageUri(profilePicture);
setIsLoading(false);
} else {
setImageUri(
'https://t3.ftcdn.net/jpg/03/46/83/96/360_F_346839683_6nAPzbhpSkIpb8pmAwufkC7c5eD7wYws.jpg',
);
setIsLoading(false);
}
};
emulator is the problem. in device it's working

react-native-sound always showing current playback time as 0

I am using react-native-sound to create an audio player, I want to get the current playback timings of the sound while it plays however when I use the getCurrentTime callback, it is only showing 0. Below is the code for the same:
const listenaudio = (audio, id) => {
console.log("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$")
if (playAudio != null) {
playAudio.release();
}
setsoundpause(id);
playAudio = new Sound(audio, Sound.MAIN_BUNDLE, (error) => {
console.log("rrr")
if (error) {
return;
}
// loaded successfully
// Play the sound with an onEnd callback
playAudio.play((success) => {
if (success) {
setsoundpause(0);
} else {
}
});
});
playAudio.setVolume(1);
playAudio.getCurrentTime((seconds) => console.log('at ' + seconds)); // here
};
It would be great if anyone could suggest how should I do it? Should I use seInterval() ?
Any leads would be appreciated.
I've made a player recently using react-native-sound, where I call getCurrentTime method after some milliseconds to get realtime player time.
My function to play audio
const timerRef = React.useRef();
const playSound = () => {
// Sound.MAIN_BUNDLE
try {
if (!playAudio || !playAudio.isLoaded()) return;
if (timerRef.current) clearInterval(timerRef.current);
timerRef.current = setInterval(() => {
playAudio.getCurrentTime((seconds, isPlaying) => {
setCurrentPlayTime(seconds); // HERE is time of current player
});
}, 300);
playAudio.play(success => {
if (!success) {
console.log('playback failed due to audio decoding errors');
}
stopSound();
});
} catch (err) {
console.log("can't play voice message", err);
}
};

Using AsyncStorage to show screen on first login

I'm trying to only show the disclosure screen the first time the user logs in by using AsyncStorage. Currently getData is returning a Promise and it goes straight to the landing screen on first login.
Could I get some help to get this functioning the way I want it to?
This is my login handler:
const key = 'key';
const storeData = async () => {
try {
await AsyncStorage.setItem('key', 'true');
} catch (error) {
// saving failed
console.log(error.message);
}
};
const getData = async key => {
let value = '';
try {
value = await AsyncStorage.getItem(key);
return JSON.parse(value);
} catch (e) {
console.log(error.message);
}
};
const _loginHandler = () => {
if (userName == '' || password == '') {
console.log('gagagagagagagagagagagagagagagagag');
} else {
setShowLoading(true);
const payload = {userName: userName.trim(), password: password.trim()};
setUserName('');
setPassword('');
_UserLoginHandler(payload).then(data => {
setShowLoading(false);
if (data.error) {
GlobalShowSnackBar(data.error);
} else {
setTimeout(() => {
setUserId(data);
//props.navigation.replace(getData("key")?'Landing':'Disclosure')
console.log('Key Value ' + JSON.stringify(getData('key'))); <-- this outputs Key Value {"_U":0,"_V":0,"_W":null,"_X":null}
if (getData('key')) {
props.navigation.navigate('Landing');
} else {
storeData(key);
props.navigation.navigate('Disclosure');
}
}, 500);
}
});
}
};
I got it to work with
getData('key').then(val => {
if (val) {
props.navigation.navigate('Landing');
} else {
storeData(key);
props.navigation.navigate('Disclosure');
}
});

In a Redux's Action, Calling a Function with Callbacks (Using async/await with React-Native-Contacts)

I am developing a mobile app, which uses React-Native, Redux and React-Native-Contacts.
In an action creator, I am trying to call a function (from React-Native-Contacts), which has callbacks (rather than promises). Following is my code.
I want the action "acContactImport" to wait for the helper function "fContactImport" to finish before proceeding to the "dispatch" statement. It does not wait for it. How can I make it wait for it?
// Action Creator:
import Contacts from 'react-native-contacts';
import { PermissionsAndroid } from 'react-native';
export const acContactImport = (userID) => {
return async (dispatch) => {
let contactList = [];
try {
// The following statement should be executed asynchronously.
// However, it is not. How can I make it asynchronous?
contactList = await fContactImport();
dispatch({
type: CONTACT_IMPORT,
payload: { contactList: contactList },
});
}
catch (err) {
console.log("acContactImport - catch: ", err);
}
};
};
// Helper Function 1
export const fContactImport = async () => {
let contactList = [];
if (Platform.OS === "android") {
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_CONTACTS, {
title: "Contacts",
message: "This app would like to view your contacts."
})
.then(() => {
contactList = _loadContacts();
});
} else {
contactList = _loadContacts();
}
}
// Helper Function 2
export const _loadContacts = () => {
Contacts.getAll((err, data2) => {
if (err) {
return [];
}
else {
let candidates = [];
for (let i = 0; i < data2.length; i++) {
let candidateObject = { name: candidateRecord.givenName + " " + candidateRecord.middleName + " " + candidateRecord.familyName };
candidates.push(candidateObject);
}
return contactList;
}
});
}
Apparently, the problem is NOT in the action creator, but in the helper functions, which do not support the new style of promises (async/wait). So, here is the solution...
// Action Creator:
// No changes are required. Original code is good.
// Helper Function 1
export const fContactImport = async () => {
let contactList = [];
if (Platform.OS === "android") {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
{
title: "Contacts",
message: "This app would like to view your contacts."
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
contactList = await _loadContacts();
} else {
console.log('Contacts access denied');
}
} catch (err) {
console.warn(err);
}
} else {
contactList = await _loadContacts();
}
return contactList;
}
// Helper Function 2
export const _loadContacts = () => {
return new Promise((resolve, reject) => {
Contacts.getAll((err, data2) => {
if (err) {
reject([]);
}
else {
let candidates = [];
for (let i = 0; i < data2.length; i++) {
let candidateObject = { name: candidateRecord.givenName + " " + candidateRecord.middleName + " " + candidateRecord.familyName };
candidates.push(candidateObject);
}
resolve(candidates);
}
});
});
}