I am using a library (Voice) that returns an instance of it. I made following component that uses it successfully
But I need multiple instances of following component in an other component. Where each component will have a unique Voice instance
So I needed to clone the imported Voice object to create separate/new instance for each instance of following component.
This component receives a property *unique_key* for its identification at any point. I also bind that key to (cloned) SpeechInstance for its identification
import React, { Component } from 'react';
import { Text, View, Button} from 'react-native';
import Voice from '@react-native-voice/voice';
var all_speech_instances = [];
export default class VoiceRecorder extends Component {
constructor(props) {
super(props);
//like all_instances array Voice is global and its an instance returned by libraray
// So i am cloning it to make specific/new for each instance of this component
this.SpeechInstance = Object.assign(Object.create(Object.getPrototypeOf(Voice)), Voice);
this.SpeechInstance.unique_key = props.unique_key;
let obj_this = this;
this.SpeechInstance.onSpeechError = function(e) { obj_this.onSpeechError(e) };
this.SpeechInstance.onSpeechResults = function(e) { obj_this.onSpeechResults(e) };
//Shown for proof of concept
all_speech_instances.push(this.SpeechInstance);
if(all_speech_instances.length > 1){
console.log('Instance 1 => unique_key='+all_speech_instances[0].unique_key); //shows 1
console.log('Instance 2 => unique_key='+all_speech_instances[1].unique_key); //shows 2
}
}
_startRecognizing = async () => {
await this.SpeechInstance.start();
};
_stopRecognizing = async () => {
await this.SpeechInstance.stop();
};
onSpeechError(e) {
// whenever error
console.log('On speech error Key=' + this.SpeechInstance.unique_key);
// always shows 2
};
onSpeechResults(e){
// whenever speech recognized
console.log('On speech results Key=' + this.SpeechInstance.unique_key, e.value);
//always shows 2
};
//Following tow functions are react-native specific
componentWillUnmount() {
this.SpeechInstance.removeAllListeners();
}
render() {
let obj_this = this;
return (
<View style={{padding:10}}>
<Text>unique_key: {this.SpeechInstance.unique_key}</Text>
<View style={{padding: 5}}>
<Button onPress={()=>{ obj_this._startRecognizing()}} title='Start Listening' />
</View>
<View style={{padding: 5}}>
<Button onPress={()=>{ obj_this._stopRecognizing()}} title='Stop Listening' />
</View>
</View>
);
}
}
Usage I am using above component pretty straightforward
import React from 'react';
import {View} from 'react-native';
import SpeechComponent from '../voice/SpeechComponent';
export default class VoiceTestScreen extends React.Component {
render(){
return(
<View>
<SpeechComponent unique_key='1'/>
<SpeechComponent unique_key='2'/>
</View>
);
}
}
After very careful encapsulation to hide the SpeechInstance within the component instance so that it could not be shared gloabally, I still always result => console On speech results Key=2 weather I start recognition (started on button click) with first instance of component or second
This Explanation Needs Improvements: My question was not correct, @begi made that correction in comment, and also after reading the Api docs as he pointed, I got the idea that it was API specific problem, as single microphone can not be listened by multiple instances separately.
So I tried it an other way and got the solution.
What I tricked was to clone the single static API instance
Voicebefore Voice.start and then destroyed it completely onError and onResult.}