zmxv / react-native-sound

React Native module for playing sound clips
MIT License
2.78k stars 748 forks source link

setSpeakerphoneOn() toggles the Ear Speaker, not the Main Speaker #701

Open cynamonster opened 3 years ago

cynamonster commented 3 years ago

:beetle: Description I see that react-native-sound's setSpeakerphoneOn() method calls Android's method of the same name. In practice, this method instead toggles the Ear Speaker and doesn't affect sound coming from the Main Speaker.

:beetle: What have you tried? Adding <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> to my AndroidManifest.xml.

This stackoverflow question addresses a similar issue and advises to tinker with Android's mediaPlayer.setAudioStreamType() method to accomplish this functionality.

:beetle: Please post your code:

onPlayPressed = async () => {
    this.playerControl = new Sound(await this.props.url(), "", (error) => {
        if (error) {
            console.log('failed to load the sound', error);
            return;
        }

        Sound.setCategory('PlayAndRecord');
        this.playerControl.setSpeakerphoneOn(this.props.isSpeakerActive);

        this.playerControl.play(() => {
            this.playerControl.release();
            this.setState({
                status: STATUS_STOPPED,
                progress: 0
            });
        });

        if (this.playerControl.getDuration() > 0) {
            this.duration = this.playerControl.getDuration();
        }

        this.playerControl.setCurrentTime(this.state.progress);
        setTimeout(() => {
            this.setState({status: STATUS_PLAYING});
            this.intervalId = setInterval(this.updatePlayerProgress, 10);

            if (this.props.onPlay) {
                this.props.onPlay();
            }
        }, 500)
    });
};

componentDidUpdate(prevProps, prevState) {
        if (this.props.isSpeakerActive !== prevProps.isSpeakerActive) {
            if (this.props.isSpeakerActive) {
                Sound.setCategory('Playback');
                if (this.playerControl) {
                    this.playerControl.setSpeakerphoneOn(true);
                }
            } else {
                Sound.setCategory('PlayAndRecord');
                if (this.playerControl) {
                    this.playerControl.setSpeakerphoneOn(false);
                }
            }
        }
    }

:bulb: Possible solution

Is your issue with...

Are you using...

Which versions are you using?

Does the problem occur on...

If your problem is happening on a device, which device?